   4 0 * {"files":{"package.json":{"size":393,"integrity":{"algorithm":"SHA256","hash":"d697f898be708709e4766c8f4653d724fe85705d5efd0bc30cc5ae76b834efef","blockSize":4194304,"blocks":["d697f898be708709e4766c8f4653d724fe85705d5efd0bc30cc5ae76b834efef"]},"offset":"0"},"electron":{"files":{"main.cjs":{"size":18351,"integrity":{"algorithm":"SHA256","hash":"5c15437826992ae9efb70c8b53191db97431358e18c71eafbdb3c8159bc3d894","blockSize":4194304,"blocks":["5c15437826992ae9efb70c8b53191db97431358e18c71eafbdb3c8159bc3d894"]},"offset":"393"},"preload.cjs":{"size":2586,"integrity":{"algorithm":"SHA256","hash":"46c68a1c85a29b1347db28135ee59a86e37d686b34416912ab7c9b58cada8b6b","blockSize":4194304,"blocks":["46c68a1c85a29b1347db28135ee59a86e37d686b34416912ab7c9b58cada8b6b"]},"offset":"18744"}}},"app":{"files":{"app.js":{"size":21733,"integrity":{"algorithm":"SHA256","hash":"c272ff6fd191c8e47b6962da580606bb1c5398ed856e79ce0edb34522c3413ea","blockSize":4194304,"blocks":["c272ff6fd191c8e47b6962da580606bb1c5398ed856e79ce0edb34522c3413ea"]},"offset":"21330"},"docs.js":{"size":30638,"integrity":{"algorithm":"SHA256","hash":"51d99e0062abec8e8894b8cad0808760f3d220827d59cf2a973f581d767779fa","blockSize":4194304,"blocks":["51d99e0062abec8e8894b8cad0808760f3d220827d59cf2a973f581d767779fa"]},"offset":"43063"},"formula.js":{"size":51839,"integrity":{"algorithm":"SHA256","hash":"be0f0de884024091da6897ed2528167b624b008776da2a23a7d7602bde655375","blockSize":4194304,"blocks":["be0f0de884024091da6897ed2528167b624b008776da2a23a7d7602bde655375"]},"offset":"73701"},"index.html":{"size":3314,"integrity":{"algorithm":"SHA256","hash":"b42e7758f82900b52971c7e6f4b4dc1504aa72305bd651e209a426ec4396b4b4","blockSize":4194304,"blocks":["b42e7758f82900b52971c7e6f4b4dc1504aa72305bd651e209a426ec4396b4b4"]},"offset":"125540"},"sheets.js":{"size":79726,"integrity":{"algorithm":"SHA256","hash":"93c6016f5307f003f1c5db11901d61f376f1187044eeb4c39b90aebdf1ee7609","blockSize":4194304,"blocks":["93c6016f5307f003f1c5db11901d61f376f1187044eeb4c39b90aebdf1ee7609"]},"offset":"128854"},"slides.js":{"size":35140,"integrity":{"algorithm":"SHA256","hash":"5477992c99a2bcb2a642fc1b901edc55da21dbad6d4611cc19271cc9ba348e49","blockSize":4194304,"blocks":["5477992c99a2bcb2a642fc1b901edc55da21dbad6d4611cc19271cc9ba348e49"]},"offset":"208580"},"styles.css":{"size":23854,"integrity":{"algorithm":"SHA256","hash":"71963ca4db6a0d5dcc5d8330f98f6e2d5bfa3b190e402aedd04f0713150cf6dc","blockSize":4194304,"blocks":["71963ca4db6a0d5dcc5d8330f98f6e2d5bfa3b190e402aedd04f0713150cf6dc"]},"offset":"243720"},"ui.js":{"size":19200,"integrity":{"algorithm":"SHA256","hash":"7b139bfbc9619b1fa34d05e69dda3722f1e239071fc992b46922954e193e199a","blockSize":4194304,"blocks":["7b139bfbc9619b1fa34d05e69dda3722f1e239071fc992b46922954e193e199a"]},"offset":"267574"}}},"node_modules":{"files":{"argparse":{"files":{"LICENSE":{"size":12775,"integrity":{"algorithm":"SHA256","hash":"de4d1f2d2ad5ad0cfd1657a106476b31cb5db5ef9d1ff842b237c0c81f0c8a23","blockSize":4194304,"blocks":["de4d1f2d2ad5ad0cfd1657a106476b31cb5db5ef9d1ff842b237c0c81f0c8a23"]},"offset":"286774"},"argparse.js":{"size":129714,"integrity":{"algorithm":"SHA256","hash":"2e73e7a3167ba840dbcf41feeafc3544a3e2b39220b5e997133c519861febf16","blockSize":4194304,"blocks":["2e73e7a3167ba840dbcf41feeafc3544a3e2b39220b5e997133c519861febf16"]},"offset":"299549"},"package.json":{"size":448,"integrity":{"algorithm":"SHA256","hash":"800e809f5cdb0a7dec1834e1d2c0a165b1b63c2d6d7b2a97034b8c668de24a8f","blockSize":4194304,"blocks":["800e809f5cdb0a7dec1834e1d2c0a165b1b63c2d6d7b2a97034b8c668de24a8f"]},"offset":"429263"},"lib":{"files":{"sub.js":{"size":2252,"integrity":{"algorithm":"SHA256","hash":"2bc4ef9e87c47f1a4e0cfcb3706d886e0d73edce88149e300d2364066f396ed6","blockSize":4194304,"blocks":["2bc4ef9e87c47f1a4e0cfcb3706d886e0d73edce88149e300d2364066f396ed6"]},"offset":"429711"},"textwrap.js":{"size":17391,"integrity":{"algorithm":"SHA256","hash":"2550466c9a0425fa583a70e25bb93e190fe09b61f7de4861ea8ec54b7b899db0","blockSize":4194304,"blocks":["2550466c9a0425fa583a70e25bb93e190fe09b61f7de4861ea8ec54b7b899db0"]},"offset":"431963"}}}}},"debug":{"files":{"LICENSE":{"size":1139,"integrity":{"algorithm":"SHA256","hash":"3a61c6c96caf5c1d9b623fb9b04c822b783dfcb78aa7e49c76a3f643e6ed7f95","blockSize":4194304,"blocks":["3a61c6c96caf5c1d9b623fb9b04c822b783dfcb78aa7e49c76a3f643e6ed7f95"]},"offset":"449354"},"package.json":{"size":910,"integrity":{"algorithm":"SHA256","hash":"85f3f142cda5b1a1ed18f4a5181a6c6b31b07a6d35da48dacc507586924c7ccd","blockSize":4194304,"blocks":["85f3f142cda5b1a1ed18f4a5181a6c6b31b07a6d35da48dacc507586924c7ccd"]},"offset":"450493"},"src":{"files":{"browser.js":{"size":6103,"integrity":{"algorithm":"SHA256","hash":"19920671f5902f64ad8ea11767fa50ea9d7a71ae0b7dff7ba5693c0075afc763","blockSize":4194304,"blocks":["19920671f5902f64ad8ea11767fa50ea9d7a71ae0b7dff7ba5693c0075afc763"]},"offset":"451403"},"common.js":{"size":6915,"integrity":{"algorithm":"SHA256","hash":"dbe83d2bb5837f3c4d7fe537b8004c585987270eceed5b06b8e078deb0ae214a","blockSize":4194304,"blocks":["dbe83d2bb5837f3c4d7fe537b8004c585987270eceed5b06b8e078deb0ae214a"]},"offset":"457506"},"index.js":{"size":314,"integrity":{"algorithm":"SHA256","hash":"aa127ff1752b7d9c7415c5c7bb6994d9aa722b81bcbcab4bd48316b013d23bf3","blockSize":4194304,"blocks":["aa127ff1752b7d9c7415c5c7bb6994d9aa722b81bcbcab4bd48316b013d23bf3"]},"offset":"464421"},"node.js":{"size":4728,"integrity":{"algorithm":"SHA256","hash":"d7b26d7c92f8ea7794b77ce11f3c11cd18c9084df7c357e3c7025344fa28aac6","blockSize":4194304,"blocks":["d7b26d7c92f8ea7794b77ce11f3c11cd18c9084df7c357e3c7025344fa28aac6"]},"offset":"464735"}}}}},"electron-updater":{"files":{"LICENSE":{"size":1084,"integrity":{"algorithm":"SHA256","hash":"bed8d0ab3e6031817f775a641ff37313b0f5591bc8ba0ed79b978dafbd4231ce","blockSize":4194304,"blocks":["bed8d0ab3e6031817f775a641ff37313b0f5591bc8ba0ed79b978dafbd4231ce"]},"offset":"469463"},"package.json":{"size":1037,"integrity":{"algorithm":"SHA256","hash":"12cd713a0d940fe32d8b74843aeca32ad4e2674da777e635b72dd0d7252be1fd","blockSize":4194304,"blocks":["12cd713a0d940fe32d8b74843aeca32ad4e2674da777e635b72dd0d7252be1fd"]},"offset":"470547"},"out":{"files":{"AppAdapter.js":{"size":740,"integrity":{"algorithm":"SHA256","hash":"2fd4359fe091d7a42e2e2df8327e03aa52e202cbf593b11d9bc891cefd09caa8","blockSize":4194304,"blocks":["2fd4359fe091d7a42e2e2df8327e03aa52e202cbf593b11d9bc891cefd09caa8"]},"offset":"471584"},"AppAdapter.js.map":{"size":1814,"integrity":{"algorithm":"SHA256","hash":"8e3dbb32bcedad41e5b863d6a21eb2f858d84a82185b5006ac259b3a688c5529","blockSize":4194304,"blocks":["8e3dbb32bcedad41e5b863d6a21eb2f858d84a82185b5006ac259b3a688c5529"]},"offset":"472324"},"AppImageUpdater.js":{"size":5675,"integrity":{"algorithm":"SHA256","hash":"59dc2fee82511b18c8cfc1d301e663feb77674932c40808a155ba4db95cc8d61","blockSize":4194304,"blocks":["59dc2fee82511b18c8cfc1d301e663feb77674932c40808a155ba4db95cc8d61"]},"offset":"474138"},"AppImageUpdater.js.map":{"size":9265,"integrity":{"algorithm":"SHA256","hash":"fa4be85b2b97e134f62ed07a399eb6830609172ae50399ba2dfd8879cb39f34d","blockSize":4194304,"blocks":["fa4be85b2b97e134f62ed07a399eb6830609172ae50399ba2dfd8879cb39f34d"]},"offset":"479813"},"AppUpdater.js":{"size":33190,"integrity":{"algorithm":"SHA256","hash":"99921022d181fbd0637878fdebc74177be167d4d56a92c9a87d828f89ab67344","blockSize":4194304,"blocks":["99921022d181fbd0637878fdebc74177be167d4d56a92c9a87d828f89ab67344"]},"offset":"489078"},"AppUpdater.js.map":{"size":57020,"integrity":{"algorithm":"SHA256","hash":"8192aa87b01cbe4b248255f18becc60ac0569819d398a7cf9ee9fd14244d0d6c","blockSize":4194304,"blocks":["8192aa87b01cbe4b248255f18becc60ac0569819d398a7cf9ee9fd14244d0d6c"]},"offset":"522268"},"BaseUpdater.js":{"size":6035,"integrity":{"algorithm":"SHA256","hash":"9cff8b894ed709f6d9a5b938614fc377be89e1ea5bd1cc1f4cd6143048d918a3","blockSize":4194304,"blocks":["9cff8b894ed709f6d9a5b938614fc377be89e1ea5bd1cc1f4cd6143048d918a3"]},"offset":"579288"},"BaseUpdater.js.map":{"size":10539,"integrity":{"algorithm":"SHA256","hash":"17f78a05184434c5d9c973f173e86c06c8c4d147618740d6720e06dc33aa2d90","blockSize":4194304,"blocks":["17f78a05184434c5d9c973f173e86c06c8c4d147618740d6720e06dc33aa2d90"]},"offset":"585323"},"DebUpdater.js":{"size":3594,"integrity":{"algorithm":"SHA256","hash":"5f59636cd9a3b065c454c2ebecfdef268998fe2489c6700905f867fd0e1e63b4","blockSize":4194304,"blocks":["5f59636cd9a3b065c454c2ebecfdef268998fe2489c6700905f867fd0e1e63b4"]},"offset":"595862"},"DebUpdater.js.map":{"size":6061,"integrity":{"algorithm":"SHA256","hash":"71d2813cf2d925e8e19e94ce08f709028f3e2ebb2362d14eb2603be87bedc554","blockSize":4194304,"blocks":["71d2813cf2d925e8e19e94ce08f709028f3e2ebb2362d14eb2603be87bedc554"]},"offset":"599456"},"DownloadedUpdateHelper.js":{"size":6907,"integrity":{"algorithm":"SHA256","hash":"81d816fdfddf4711218f78c7625e22122b2159ec7c83209613dfb9e71a552e4d","blockSize":4194304,"blocks":["81d816fdfddf4711218f78c7625e22122b2159ec7c83209613dfb9e71a552e4d"]},"offset":"605517"},"DownloadedUpdateHelper.js.map":{"size":12251,"integrity":{"algorithm":"SHA256","hash":"cef2750982fd63ef843c4a274938682a1f8e2abd1eac794f1b612fdb496b1d00","blockSize":4194304,"blocks":["cef2750982fd63ef843c4a274938682a1f8e2abd1eac794f1b612fdb496b1d00"]},"offset":"612424"},"ElectronAppAdapter.js":{"size":1180,"integrity":{"algorithm":"SHA256","hash":"fa8fbf1de1c69924942aa3926878d391fba95007095836abe5f5b878506d4931","blockSize":4194304,"blocks":["fa8fbf1de1c69924942aa3926878d391fba95007095836abe5f5b878506d4931"]},"offset":"624675"},"ElectronAppAdapter.js.map":{"size":2289,"integrity":{"algorithm":"SHA256","hash":"f5b740ccc773315579ac1cc893db314f1bf589d4c499073755c625e8cdfa99a0","blockSize":4194304,"blocks":["f5b740ccc773315579ac1cc893db314f1bf589d4c499073755c625e8cdfa99a0"]},"offset":"625855"},"LinuxUpdater.js":{"size":5089,"integrity":{"algorithm":"SHA256","hash":"47a95d960724e5977b1d81d0e7a35b386fcd5a8ee286fa95f5a19a759e1c6558","blockSize":4194304,"blocks":["47a95d960724e5977b1d81d0e7a35b386fcd5a8ee286fa95f5a19a759e1c6558"]},"offset":"628144"},"LinuxUpdater.js.map":{"size":8236,"integrity":{"algorithm":"SHA256","hash":"919fc747abe6f00f486f15cde98064d32aa0e076f849fa54bfadbf2c17d22d79","blockSize":4194304,"blocks":["919fc747abe6f00f486f15cde98064d32aa0e076f849fa54bfadbf2c17d22d79"]},"offset":"633233"},"MacUpdater.js":{"size":12866,"integrity":{"algorithm":"SHA256","hash":"4824eb5d8c600f61ae69f14221f5252470b46da5be049645fa5ec10a42a5214b","blockSize":4194304,"blocks":["4824eb5d8c600f61ae69f14221f5252470b46da5be049645fa5ec10a42a5214b"]},"offset":"641469"},"MacUpdater.js.map":{"size":21163,"integrity":{"algorithm":"SHA256","hash":"ae785369e1dacc09cfaf567352790124b3a3b522c983f6da6e92dee52d5afbda","blockSize":4194304,"blocks":["ae785369e1dacc09cfaf567352790124b3a3b522c983f6da6e92dee52d5afbda"]},"offset":"654335"},"NsisUpdater.js":{"size":9416,"integrity":{"algorithm":"SHA256","hash":"31f36b4ef5cadd35a93df91d9454aa70044e41c0e6b4c799783dca4302cd03b6","blockSize":4194304,"blocks":["31f36b4ef5cadd35a93df91d9454aa70044e41c0e6b4c799783dca4302cd03b6"]},"offset":"675498"},"NsisUpdater.js.map":{"size":15024,"integrity":{"algorithm":"SHA256","hash":"99eb686f31a06877064a9b6b991898ac63649c9d35d1089f95d6007c4821283e","blockSize":4194304,"blocks":["99eb686f31a06877064a9b6b991898ac63649c9d35d1089f95d6007c4821283e"]},"offset":"684914"},"PacmanUpdater.js":{"size":2796,"integrity":{"algorithm":"SHA256","hash":"e4d76d7072d81503b49de126385c10e8592711d3a10c36e9c23fbd125d298320","blockSize":4194304,"blocks":["e4d76d7072d81503b49de126385c10e8592711d3a10c36e9c23fbd125d298320"]},"offset":"699938"},"PacmanUpdater.js.map":{"size":4838,"integrity":{"algorithm":"SHA256","hash":"c51dfac79e9c9c0d01ad178ecb5554c4e0555d3d16ccba9d5890ed89df9fb309","blockSize":4194304,"blocks":["c51dfac79e9c9c0d01ad178ecb5554c4e0555d3d16ccba9d5890ed89df9fb309"]},"offset":"702734"},"RpmUpdater.js":{"size":2891,"integrity":{"algorithm":"SHA256","hash":"1e05f4be81a4ac304b53d0df1f6d83dd2de7e75aee95896ce67ef8c49cf736e7","blockSize":4194304,"blocks":["1e05f4be81a4ac304b53d0df1f6d83dd2de7e75aee95896ce67ef8c49cf736e7"]},"offset":"707572"},"RpmUpdater.js.map":{"size":5376,"integrity":{"algorithm":"SHA256","hash":"e38408e553e3ad88683fd53cdb0172ea9c49eb27a79bd806766dab4df59e1aa0","blockSize":4194304,"blocks":["e38408e553e3ad88683fd53cdb0172ea9c49eb27a79bd806766dab4df59e1aa0"]},"offset":"710463"},"electronHttpExecutor.js":{"size":3258,"integrity":{"algorithm":"SHA256","hash":"907bc7f2c71c1f964fe83f71337a520073e753f3f35ea00076f5676aebaa6404","blockSize":4194304,"blocks":["907bc7f2c71c1f964fe83f71337a520073e753f3f35ea00076f5676aebaa6404"]},"offset":"715839"},"electronHttpExecutor.js.map":{"size":5547,"integrity":{"algorithm":"SHA256","hash":"3e6eafc704edaa106700ef5ce03e621a33c86a974e5499d3a3551a18e4851e8a","blockSize":4194304,"blocks":["3e6eafc704edaa106700ef5ce03e621a33c86a974e5499d3a3551a18e4851e8a"]},"offset":"719097"},"main.js":{"size":4494,"integrity":{"algorithm":"SHA256","hash":"c0f5cc41a2ef973672066222109850ac22fc70bcca1880e5c3cb8311f7ab05e5","blockSize":4194304,"blocks":["c0f5cc41a2ef973672066222109850ac22fc70bcca1880e5c3cb8311f7ab05e5"]},"offset":"724644"},"main.js.map":{"size":4427,"integrity":{"algorithm":"SHA256","hash":"3b9ef6f5494138aa2e5f13a6d29cc07d8c9ee5546b7a278d233b0d0f9318c243","blockSize":4194304,"blocks":["3b9ef6f5494138aa2e5f13a6d29cc07d8c9ee5546b7a278d233b0d0f9318c243"]},"offset":"729138"},"providerFactory.js":{"size":3363,"integrity":{"algorithm":"SHA256","hash":"b1f323d02b37f9b27439704cd48c06f41159c289cd0b3cd4e4b536231e7d5daa","blockSize":4194304,"blocks":["b1f323d02b37f9b27439704cd48c06f41159c289cd0b3cd4e4b536231e7d5daa"]},"offset":"733565"},"providerFactory.js.map":{"size":5450,"integrity":{"algorithm":"SHA256","hash":"1f180fd23f1b1ce6f1b0f56e7ea8d92ecc3e86f2d53ec798ec224151c475cd29","blockSize":4194304,"blocks":["1f180fd23f1b1ce6f1b0f56e7ea8d92ecc3e86f2d53ec798ec224151c475cd29"]},"offset":"736928"},"types.js":{"size":1551,"integrity":{"algorithm":"SHA256","hash":"b92b36b9fd6ad4790a05d8ef0c1e65b875923ff098e5371a59076b20b17f2e3b","blockSize":4194304,"blocks":["b92b36b9fd6ad4790a05d8ef0c1e65b875923ff098e5371a59076b20b17f2e3b"]},"offset":"742378"},"types.js.map":{"size":3619,"integrity":{"algorithm":"SHA256","hash":"3f31519e9ef41568d2308ccb5a2a7c08e54bffcd43c7547610727235babd2b3e","blockSize":4194304,"blocks":["3f31519e9ef41568d2308ccb5a2a7c08e54bffcd43c7547610727235babd2b3e"]},"offset":"743929"},"util.js":{"size":1278,"integrity":{"algorithm":"SHA256","hash":"104ee9520aecd56ec9311e2ac8980d02f86b07b20010b6b59a280c61478ce1a1","blockSize":4194304,"blocks":["104ee9520aecd56ec9311e2ac8980d02f86b07b20010b6b59a280c61478ce1a1"]},"offset":"747548"},"util.js.map":{"size":2040,"integrity":{"algorithm":"SHA256","hash":"1cc2ff8a950733d982b74c7f0f5f0d3a2b8af6c8a8acb255908dd14fa7058cc0","blockSize":4194304,"blocks":["1cc2ff8a950733d982b74c7f0f5f0d3a2b8af6c8a8acb255908dd14fa7058cc0"]},"offset":"748826"},"windowsExecutableCodeSignatureVerifier.js":{"size":7539,"integrity":{"algorithm":"SHA256","hash":"4738e446904710a2497fd3408fdf6416c5515d9177c0add0f2427bd725969c21","blockSize":4194304,"blocks":["4738e446904710a2497fd3408fdf6416c5515d9177c0add0f2427bd725969c21"]},"offset":"750866"},"windowsExecutableCodeSignatureVerifier.js.map":{"size":11364,"integrity":{"algorithm":"SHA256","hash":"ba0c5ba99b1b429a720b350e7802af84bae782b150beef9c169143758ea9115c","blockSize":4194304,"blocks":["ba0c5ba99b1b429a720b350e7802af84bae782b150beef9c169143758ea9115c"]},"offset":"758405"},"providers":{"files":{"BitbucketProvider.js":{"size":1969,"integrity":{"algorithm":"SHA256","hash":"d918e2d9a98797a36dfa777b380689282187dadf9c881e94b7e2073c8d325416","blockSize":4194304,"blocks":["d918e2d9a98797a36dfa777b380689282187dadf9c881e94b7e2073c8d325416"]},"offset":"769769"},"BitbucketProvider.js.map":{"size":3454,"integrity":{"algorithm":"SHA256","hash":"bf4e8f4f4efbf1c89aa4cb4979d10e4b329cffee9726a12795bb1c5cf324703a","blockSize":4194304,"blocks":["bf4e8f4f4efbf1c89aa4cb4979d10e4b329cffee9726a12795bb1c5cf324703a"]},"offset":"771738"},"GenericProvider.js":{"size":2252,"integrity":{"algorithm":"SHA256","hash":"c0d1f1aed62d7418e4d292118b3e079f9680914c554fe7604786b73771297d8a","blockSize":4194304,"blocks":["c0d1f1aed62d7418e4d292118b3e079f9680914c554fe7604786b73771297d8a"]},"offset":"775192"},"GenericProvider.js.map":{"size":3777,"integrity":{"algorithm":"SHA256","hash":"32687ae2a040a8a153135d9aced2afbffe42d1ad337ce8ca53f2e899a6900640","blockSize":4194304,"blocks":["32687ae2a040a8a153135d9aced2afbffe42d1ad337ce8ca53f2e899a6900640"]},"offset":"777444"},"GitHubProvider.js":{"size":11423,"integrity":{"algorithm":"SHA256","hash":"17c0ae98c1fb7943057fe88c0cc951a84acc81988813dba1aca20e911f82f601","blockSize":4194304,"blocks":["17c0ae98c1fb7943057fe88c0cc951a84acc81988813dba1aca20e911f82f601"]},"offset":"781221"},"GitHubProvider.js.map":{"size":19391,"integrity":{"algorithm":"SHA256","hash":"fd3e616628b2450be2cb1e3286bf92d96a3fc63f1d50d441836a4598ef3d16b9","blockSize":4194304,"blocks":["fd3e616628b2450be2cb1e3286bf92d96a3fc63f1d50d441836a4598ef3d16b9"]},"offset":"792644"},"GitLabProvider.js":{"size":13940,"integrity":{"algorithm":"SHA256","hash":"4adc8262d719fad0569af79d61af13976b6ddd6d0adfd824a156b60c8f8d2f7a","blockSize":4194304,"blocks":["4adc8262d719fad0569af79d61af13976b6ddd6d0adfd824a156b60c8f8d2f7a"]},"offset":"812035"},"GitLabProvider.js.map":{"size":22832,"integrity":{"algorithm":"SHA256","hash":"10a79190f4f09ebefa448c71b0830f1089860bc6b8af771b40217dede31516aa","blockSize":4194304,"blocks":["10a79190f4f09ebefa448c71b0830f1089860bc6b8af771b40217dede31516aa"]},"offset":"825975"},"KeygenProvider.js":{"size":2205,"integrity":{"algorithm":"SHA256","hash":"361cd9b7c29c6db9b94ac74947a6d4c7b48ac01a74c6b7950d9ff256ec783568","blockSize":4194304,"blocks":["361cd9b7c29c6db9b94ac74947a6d4c7b48ac01a74c6b7950d9ff256ec783568"]},"offset":"848807"},"KeygenProvider.js.map":{"size":3892,"integrity":{"algorithm":"SHA256","hash":"a5082b0cd3893d9e77fbbb62cdc8a2ffa3f701c9f65c3b7ab1279eea662b3bb5","blockSize":4194304,"blocks":["a5082b0cd3893d9e77fbbb62cdc8a2ffa3f701c9f65c3b7ab1279eea662b3bb5"]},"offset":"851012"},"PrivateGitHubProvider.js":{"size":4378,"integrity":{"algorithm":"SHA256","hash":"2dff56a9875d783cc0883b6a60dfbf5cfc6d4097201b3b968858f1570b6d0d2f","blockSize":4194304,"blocks":["2dff56a9875d783cc0883b6a60dfbf5cfc6d4097201b3b968858f1570b6d0d2f"]},"offset":"854904"},"PrivateGitHubProvider.js.map":{"size":8136,"integrity":{"algorithm":"SHA256","hash":"af0b5ab6b329450031a9f19c54013d577183f920c2ea804a0a2dc0794d19a8ae","blockSize":4194304,"blocks":["af0b5ab6b329450031a9f19c54013d577183f920c2ea804a0a2dc0794d19a8ae"]},"offset":"859282"},"Provider.js":{"size":6002,"integrity":{"algorithm":"SHA256","hash":"48601c5ceb7aaaeec096b84186a1155964128e64bbe8c009dd2d9cb9afccda37","blockSize":4194304,"blocks":["48601c5ceb7aaaeec096b84186a1155964128e64bbe8c009dd2d9cb9afccda37"]},"offset":"867418"},"Provider.js.map":{"size":11692,"integrity":{"algorithm":"SHA256","hash":"a131fb662af5e7164c84b64b71402e3d84e6a3f09404a204d871f973285ea7e8","blockSize":4194304,"blocks":["a131fb662af5e7164c84b64b71402e3d84e6a3f09404a204d871f973285ea7e8"]},"offset":"873420"}}},"differentialDownloader":{"files":{"DataSplitter.js":{"size":9396,"integrity":{"algorithm":"SHA256","hash":"a1d74dc923cc779b1cc8b8bd6bce24879b7266b8d6f659f09f53d5e5275e9ab4","blockSize":4194304,"blocks":["a1d74dc923cc779b1cc8b8bd6bce24879b7266b8d6f659f09f53d5e5275e9ab4"]},"offset":"885112"},"DataSplitter.js.map":{"size":16649,"integrity":{"algorithm":"SHA256","hash":"7e082ae113a7187cce9b8b86d02d6c1ab4c352a0e45914ef61a8e6f808798acb","blockSize":4194304,"blocks":["7e082ae113a7187cce9b8b86d02d6c1ab4c352a0e45914ef61a8e6f808798acb"]},"offset":"894508"},"DifferentialDownloader.js":{"size":12517,"integrity":{"algorithm":"SHA256","hash":"428ada90afe644da1a7517670ba07aa8cc307f36587e00f2f748f8f6dbc992bd","blockSize":4194304,"blocks":["428ada90afe644da1a7517670ba07aa8cc307f36587e00f2f748f8f6dbc992bd"]},"offset":"911157"},"DifferentialDownloader.js.map":{"size":21368,"integrity":{"algorithm":"SHA256","hash":"f64b2d213f3a9822e37b27e9a70604673c80e689f3ae61a15e67861015ab5b67","blockSize":4194304,"blocks":["f64b2d213f3a9822e37b27e9a70604673c80e689f3ae61a15e67861015ab5b67"]},"offset":"923674"},"FileWithEmbeddedBlockMapDifferentialDownloader.js":{"size":1861,"integrity":{"algorithm":"SHA256","hash":"8f3c12c0d7e6e0284b9c9af068a0c6caa56f691997c763bb5850b8fa98c19650","blockSize":4194304,"blocks":["8f3c12c0d7e6e0284b9c9af068a0c6caa56f691997c763bb5850b8fa98c19650"]},"offset":"945042"},"FileWithEmbeddedBlockMapDifferentialDownloader.js.map":{"size":3213,"integrity":{"algorithm":"SHA256","hash":"f21cdffe96e592998d830c9cf3d62cb1c209cc5aa0697dbff1e5e7b3dc7156f4","blockSize":4194304,"blocks":["f21cdffe96e592998d830c9cf3d62cb1c209cc5aa0697dbff1e5e7b3dc7156f4"]},"offset":"946903"},"GenericDifferentialDownloader.js":{"size":524,"integrity":{"algorithm":"SHA256","hash":"62ca9a1d3ca12deca41ad902a24d8fec34ec150cdc194478d5b4fc987a66921b","blockSize":4194304,"blocks":["62ca9a1d3ca12deca41ad902a24d8fec34ec150cdc194478d5b4fc987a66921b"]},"offset":"950116"},"GenericDifferentialDownloader.js.map":{"size":709,"integrity":{"algorithm":"SHA256","hash":"37a09dab5af73258527d65396a02363f10df71c1d4c60555b4492ee5c847aada","blockSize":4194304,"blocks":["37a09dab5af73258527d65396a02363f10df71c1d4c60555b4492ee5c847aada"]},"offset":"950640"},"ProgressDifferentialDownloadCallbackTransform.js":{"size":3824,"integrity":{"algorithm":"SHA256","hash":"d4b62c2f8eec10bb8edcc0227cde609734ef344bd3e727a48cdb806ea3608ef4","blockSize":4194304,"blocks":["d4b62c2f8eec10bb8edcc0227cde609734ef344bd3e727a48cdb806ea3608ef4"]},"offset":"951349"},"ProgressDifferentialDownloadCallbackTransform.js.map":{"size":6590,"integrity":{"algorithm":"SHA256","hash":"c7d2540b01b43b9a8ffde20eecd5a20d0343265d95ce3dc8cb0a32ecfcb6b304","blockSize":4194304,"blocks":["c7d2540b01b43b9a8ffde20eecd5a20d0343265d95ce3dc8cb0a32ecfcb6b304"]},"offset":"955173"},"downloadPlanBuilder.js":{"size":5517,"integrity":{"algorithm":"SHA256","hash":"4ee0506c1431e86c6e693a5d118c2909f7638cc27000e3c7569cd43da08bfbf4","blockSize":4194304,"blocks":["4ee0506c1431e86c6e693a5d118c2909f7638cc27000e3c7569cd43da08bfbf4"]},"offset":"961763"},"downloadPlanBuilder.js.map":{"size":10248,"integrity":{"algorithm":"SHA256","hash":"f05e73a087686a5d06a1a2ce77f539ee1250653fd192949e3dd466b328fc4898","blockSize":4194304,"blocks":["f05e73a087686a5d06a1a2ce77f539ee1250653fd192949e3dd466b328fc4898"]},"offset":"967280"},"multipleRangeDownloader.js":{"size":5066,"integrity":{"algorithm":"SHA256","hash":"acb4cc89c273776d5bfc0409e032f234a4aafd1f02cc442734d6c4a5db4be4cc","blockSize":4194304,"blocks":["acb4cc89c273776d5bfc0409e032f234a4aafd1f02cc442734d6c4a5db4be4cc"]},"offset":"977528"},"multipleRangeDownloader.js.map":{"size":9247,"integrity":{"algorithm":"SHA256","hash":"89b02ec3b2e23bc1e378eb73e1c6f9fb4eaa0ae592166486ae3a88f97fa6f23d","blockSize":4194304,"blocks":["89b02ec3b2e23bc1e378eb73e1c6f9fb4eaa0ae592166486ae3a88f97fa6f23d"]},"offset":"982594"}}}}},"node_modules":{"files":{"builder-util-runtime":{"files":{"LICENSE":{"size":1084,"integrity":{"algorithm":"SHA256","hash":"bed8d0ab3e6031817f775a641ff37313b0f5591bc8ba0ed79b978dafbd4231ce","blockSize":4194304,"blocks":["bed8d0ab3e6031817f775a641ff37313b0f5591bc8ba0ed79b978dafbd4231ce"]},"offset":"2090575"},"package.json":{"size":630,"integrity":{"algorithm":"SHA256","hash":"a5aefd7643b47da51c78d230068d71035cac7f660cbeaf2af5ab8953bc79b31d","blockSize":4194304,"blocks":["a5aefd7643b47da51c78d230068d71035cac7f660cbeaf2af5ab8953bc79b31d"]},"offset":"2091659"},"out":{"files":{"CancellationToken.js":{"size":3199,"integrity":{"algorithm":"SHA256","hash":"054512fdee2fe810ef46d5ce7fdc2c39d3582ee8c3d463a4ee6c954bca8ec7d5","blockSize":4194304,"blocks":["054512fdee2fe810ef46d5ce7fdc2c39d3582ee8c3d463a4ee6c954bca8ec7d5"]},"offset":"2092289"},"CancellationToken.js.map":{"size":5648,"integrity":{"algorithm":"SHA256","hash":"9fdf32eccac29b57c7703a23cd1201ca6a04c1b81b349900177ec1b948317c89","blockSize":4194304,"blocks":["9fdf32eccac29b57c7703a23cd1201ca6a04c1b81b349900177ec1b948317c89"]},"offset":"2095488"},"MemoLazy.js":{"size":1504,"integrity":{"algorithm":"SHA256","hash":"f92e496315210399d4f58381b25ab4ca17f42991b4a50a0353c7e0acd92836a3","blockSize":4194304,"blocks":["f92e496315210399d4f58381b25ab4ca17f42991b4a50a0353c7e0acd92836a3"]},"offset":"2101136"},"MemoLazy.js.map":{"size":2756,"integrity":{"algorithm":"SHA256","hash":"1603666315d0de55b5553b7223abfba2fdc113fc765f61c5e74d60ed4c3c7a9b","blockSize":4194304,"blocks":["1603666315d0de55b5553b7223abfba2fdc113fc765f61c5e74d60ed4c3c7a9b"]},"offset":"2102640"},"ProgressCallbackTransform.js":{"size":1949,"integrity":{"algorithm":"SHA256","hash":"35503895f7e7dd4329b94dd69eb48674ac55d9d6646d0ea42eada5378d433d32","blockSize":4194304,"blocks":["35503895f7e7dd4329b94dd69eb48674ac55d9d6646d0ea42eada5378d433d32"]},"offset":"2105396"},"ProgressCallbackTransform.js.map":{"size":3693,"integrity":{"algorithm":"SHA256","hash":"7e42abdec49293ecbd388e36213ccf743a0b12a018af5045dd23cd0ed495c7ff","blockSize":4194304,"blocks":["7e42abdec49293ecbd388e36213ccf743a0b12a018af5045dd23cd0ed495c7ff"]},"offset":"2107345"},"blockMapApi.js":{"size":116,"integrity":{"algorithm":"SHA256","hash":"84e270ead20b81c2c527c7cea8c295819fd015c120f67fd686c29534e036c239","blockSize":4194304,"blocks":["84e270ead20b81c2c527c7cea8c295819fd015c120f67fd686c29534e036c239"]},"offset":"2111038"},"blockMapApi.js.map":{"size":403,"integrity":{"algorithm":"SHA256","hash":"cbc5bfdd044fd2f70dd6edaf55449890497bdf67a05686e847da71ac96b94a33","blockSize":4194304,"blocks":["cbc5bfdd044fd2f70dd6edaf55449890497bdf67a05686e847da71ac96b94a33"]},"offset":"2111154"},"error.js":{"size":255,"integrity":{"algorithm":"SHA256","hash":"820464dee13ae1ca3c40d6a0f35bd49cabb154af63f872e9ed3488a0b95cca49","blockSize":4194304,"blocks":["820464dee13ae1ca3c40d6a0f35bd49cabb154af63f872e9ed3488a0b95cca49"]},"offset":"2111557"},"error.js.map":{"size":454,"integrity":{"algorithm":"SHA256","hash":"64580cca1bb760bd55809c02ee1b3789dd6bd3499bee30e82ed8986e3413ef95","blockSize":4194304,"blocks":["64580cca1bb760bd55809c02ee1b3789dd6bd3499bee30e82ed8986e3413ef95"]},"offset":"2111812"},"httpExecutor.js":{"size":23064,"integrity":{"algorithm":"SHA256","hash":"13050c5e047556326a2a17bc991dcf1e0f58b20409e0476486a6fd0ed6c577f6","blockSize":4194304,"blocks":["13050c5e047556326a2a17bc991dcf1e0f58b20409e0476486a6fd0ed6c577f6"]},"offset":"2112266"},"httpExecutor.js.map":{"size":42807,"integrity":{"algorithm":"SHA256","hash":"83ac73f71ec2b611f934a041cfdd60cba331ff30b239bb4053cbe41ea509a95a","blockSize":4194304,"blocks":["83ac73f71ec2b611f934a041cfdd60cba331ff30b239bb4053cbe41ea509a95a"]},"offset":"2135330"},"index.js":{"size":5449,"integrity":{"algorithm":"SHA256","hash":"140b927a94d361c3298a019ba7cf64f355b8ebf40e04b748be3c5b30ceb1e0c6","blockSize":4194304,"blocks":["140b927a94d361c3298a019ba7cf64f355b8ebf40e04b748be3c5b30ceb1e0c6"]},"offset":"2178137"},"index.js.map":{"size":2599,"integrity":{"algorithm":"SHA256","hash":"78e8e0fbca47163dd025468648cf299f66ceb4f6521db5e3fac327e759449d88","blockSize":4194304,"blocks":["78e8e0fbca47163dd025468648cf299f66ceb4f6521db5e3fac327e759449d88"]},"offset":"2183586"},"objects.js":{"size":3132,"integrity":{"algorithm":"SHA256","hash":"48c8df97f69197a400714a0bdbd3674485a511b8606cf3dc84448a576babcd10","blockSize":4194304,"blocks":["48c8df97f69197a400714a0bdbd3674485a511b8606cf3dc84448a576babcd10"]},"offset":"2186185"},"objects.js.map":{"size":6280,"integrity":{"algorithm":"SHA256","hash":"b3fffdc162c574177d44989c26c033c68836852ba8963e0ceb9059e306a80c8c","blockSize":4194304,"blocks":["b3fffdc162c574177d44989c26c033c68836852ba8963e0ceb9059e306a80c8c"]},"offset":"2189317"},"publishOptions.js":{"size":2505,"integrity":{"algorithm":"SHA256","hash":"48e9aa4f6e2eab4b7f2e412f26784950c4701b036a72ae451c6cef3d1eb22435","blockSize":4194304,"blocks":["48e9aa4f6e2eab4b7f2e412f26784950c4701b036a72ae451c6cef3d1eb22435"]},"offset":"2195597"},"publishOptions.js.map":{"size":17843,"integrity":{"algorithm":"SHA256","hash":"7e9e8e9deb02b129e6c15dbe7e85f7f340f24226428b17e34e258f77771544b2","blockSize":4194304,"blocks":["7e9e8e9deb02b129e6c15dbe7e85f7f340f24226428b17e34e258f77771544b2"]},"offset":"2198102"},"retry.js":{"size":941,"integrity":{"algorithm":"SHA256","hash":"f89a0e871d04334725d54112c101475b423ea93ae4db2878b6cc2404791b5b40","blockSize":4194304,"blocks":["f89a0e871d04334725d54112c101475b423ea93ae4db2878b6cc2404791b5b40"]},"offset":"2215945"},"retry.js.map":{"size":1750,"integrity":{"algorithm":"SHA256","hash":"94f3f24d0bc8360c9a0d8eccc766713c5d59557eff573cc1ec8bae1a5cf05c29","blockSize":4194304,"blocks":["94f3f24d0bc8360c9a0d8eccc766713c5d59557eff573cc1ec8bae1a5cf05c29"]},"offset":"2216886"},"rfc2253Parser.js":{"size":2264,"integrity":{"algorithm":"SHA256","hash":"a8a6966c3bc3e6cc0df40128aa591747859257563f46f56b83d76148f8e170c4","blockSize":4194304,"blocks":["a8a6966c3bc3e6cc0df40128aa591747859257563f46f56b83d76148f8e170c4"]},"offset":"2218636"},"rfc2253Parser.js.map":{"size":4168,"integrity":{"algorithm":"SHA256","hash":"8bcf678951773404906d4b9ceb1e6afead0c6db8a15c73b6f273f1f135b176b6","blockSize":4194304,"blocks":["8bcf678951773404906d4b9ceb1e6afead0c6db8a15c73b6f273f1f135b176b6"]},"offset":"2220900"},"updateInfo.js":{"size":115,"integrity":{"algorithm":"SHA256","hash":"935693e55dcf8a1e0ad653bbee7d456594835fdee0b99c9f7559befe1387043a","blockSize":4194304,"blocks":["935693e55dcf8a1e0ad653bbee7d456594835fdee0b99c9f7559befe1387043a"]},"offset":"2225068"},"updateInfo.js.map":{"size":2338,"integrity":{"algorithm":"SHA256","hash":"3069ad55dd2ee1fe12d69db4b43a78da7970c5a1a3886b5e27265c1b4565337a","blockSize":4194304,"blocks":["3069ad55dd2ee1fe12d69db4b43a78da7970c5a1a3886b5e27265c1b4565337a"]},"offset":"2225183"},"uuid.js":{"size":6393,"integrity":{"algorithm":"SHA256","hash":"5a58134245d8e5ae587e995195d3ca33d9f9e273fc077d700e675f4c4005c029","blockSize":4194304,"blocks":["5a58134245d8e5ae587e995195d3ca33d9f9e273fc077d700e675f4c4005c029"]},"offset":"2227521"},"uuid.js.map":{"size":12236,"integrity":{"algorithm":"SHA256","hash":"3f8dc910c8f65bcd60d13787829931ec270933c7009ee667c854a0911e84d338","blockSize":4194304,"blocks":["3f8dc910c8f65bcd60d13787829931ec270933c7009ee667c854a0911e84d338"]},"offset":"2233914"},"xml.js":{"size":3549,"integrity":{"algorithm":"SHA256","hash":"8f637be20077f0634bf36cac8a464973a6e1530e51f4efcfaec0f2c64df6ceb0","blockSize":4194304,"blocks":["8f637be20077f0634bf36cac8a464973a6e1530e51f4efcfaec0f2c64df6ceb0"]},"offset":"2246150"},"xml.js.map":{"size":6987,"integrity":{"algorithm":"SHA256","hash":"405331ede8c0bfb52033a9829b6ae9ca7f87c36b1c663c220309dad6fc8f0ca1","blockSize":4194304,"blocks":["405331ede8c0bfb52033a9829b6ae9ca7f87c36b1c663c220309dad6fc8f0ca1"]},"offset":"2249699"}}}}},"fs-extra":{"files":{"LICENSE":{"size":1084,"integrity":{"algorithm":"SHA256","hash":"1e76029602ae9b21cc4e612db2496d92febed882ba13ba745f8b3309e85f9d39","blockSize":4194304,"blocks":["1e76029602ae9b21cc4e612db2496d92febed882ba13ba745f8b3309e85f9d39"]},"offset":"2256686"},"package.json":{"size":950,"integrity":{"algorithm":"SHA256","hash":"8625f8d6674f3dacbdd5ed9fc553d9583234a6403ef90b1612f786b8fad17711","blockSize":4194304,"blocks":["8625f8d6674f3dacbdd5ed9fc553d9583234a6403ef90b1612f786b8fad17711"]},"offset":"2257770"},"lib":{"files":{"index.js":{"size":358,"integrity":{"algorithm":"SHA256","hash":"4967e903b3dc290f2b401b81bfcad8b2d94fd68c1bf4563df63ac082af0e1dae","blockSize":4194304,"blocks":["4967e903b3dc290f2b401b81bfcad8b2d94fd68c1bf4563df63ac082af0e1dae"]},"offset":"2258720"},"util":{"files":{"stat.js":{"size":5226,"integrity":{"algorithm":"SHA256","hash":"fe33d6c739866764c937e8aaeb518bbda7a36b0f3c006855b26c5bdd846081c3","blockSize":4194304,"blocks":["fe33d6c739866764c937e8aaeb518bbda7a36b0f3c006855b26c5bdd846081c3"]},"offset":"2259078"},"utimes.js":{"size":615,"integrity":{"algorithm":"SHA256","hash":"4a049bcd580984957b8690fb05f7a6bf5c7e59bfc78d6817882945c35f3a44d4","blockSize":4194304,"blocks":["4a049bcd580984957b8690fb05f7a6bf5c7e59bfc78d6817882945c35f3a44d4"]},"offset":"2264304"}}},"remove":{"files":{"index.js":{"size":489,"integrity":{"algorithm":"SHA256","hash":"ad79431e3d1cae731565d3e7403f619aee21f3b276d3541fe794ec7fd59ab0da","blockSize":4194304,"blocks":["ad79431e3d1cae731565d3e7403f619aee21f3b276d3541fe794ec7fd59ab0da"]},"offset":"2264919"},"rimraf.js":{"size":7443,"integrity":{"algorithm":"SHA256","hash":"931cd85d1564a59db583841196cf2773940e7eee30830514b448d2d4919cc534","blockSize":4194304,"blocks":["931cd85d1564a59db583841196cf2773940e7eee30830514b448d2d4919cc534"]},"offset":"2265408"}}},"path-exists":{"files":{"index.js":{"size":263,"integrity":{"algorithm":"SHA256","hash":"5ce096c95daec0259817248921b39a9e0df4d342db171138ccb62440cc7a0cbe","blockSize":4194304,"blocks":["5ce096c95daec0259817248921b39a9e0df4d342db171138ccb62440cc7a0cbe"]},"offset":"2272851"}}},"output-file":{"files":{"index.js":{"size":947,"integrity":{"algorithm":"SHA256","hash":"a27d1a72ed1ecddffc57e70187a4b72467ed0dd34092b7e3d2817b9f4359ab5d","blockSize":4194304,"blocks":["a27d1a72ed1ecddffc57e70187a4b72467ed0dd34092b7e3d2817b9f4359ab5d"]},"offset":"2273114"}}},"move":{"files":{"index.js":{"size":147,"integrity":{"algorithm":"SHA256","hash":"274f9fd31ac65cdc7dd9a6c568fb1163c2b043f6d5fcad30d5177961e9e3e240","blockSize":4194304,"blocks":["274f9fd31ac65cdc7dd9a6c568fb1163c2b043f6d5fcad30d5177961e9e3e240"]},"offset":"2274061"},"move-sync.js":{"size":1485,"integrity":{"algorithm":"SHA256","hash":"10c9f85215adcbc49661e5629d81ab4a5dbae552dd59032836d28cb2836d1cce","blockSize":4194304,"blocks":["10c9f85215adcbc49661e5629d81ab4a5dbae552dd59032836d28cb2836d1cce"]},"offset":"2274208"},"move.js":{"size":2010,"integrity":{"algorithm":"SHA256","hash":"5487cd460cb8af3e0b2ed0055d61185e56bea35d08c01972b7f1a87e0433aabe","blockSize":4194304,"blocks":["5487cd460cb8af3e0b2ed0055d61185e56bea35d08c01972b7f1a87e0433aabe"]},"offset":"2275693"}}},"mkdirs":{"files":{"index.js":{"size":328,"integrity":{"algorithm":"SHA256","hash":"adcd576e2e3868b94adb1bad6d1e3cf2312ffdfa71e49a57fe6247e116e75ecf","blockSize":4194304,"blocks":["adcd576e2e3868b94adb1bad6d1e3cf2312ffdfa71e49a57fe6247e116e75ecf"]},"offset":"2277703"},"make-dir.js":{"size":545,"integrity":{"algorithm":"SHA256","hash":"23c7ce8a3d6b39d1c7cf5d16ba6447c1690a6fdaa8c5f41e6b76526b7afe96f3","blockSize":4194304,"blocks":["23c7ce8a3d6b39d1c7cf5d16ba6447c1690a6fdaa8c5f41e6b76526b7afe96f3"]},"offset":"2278031"},"utils.js":{"size":1655,"integrity":{"algorithm":"SHA256","hash":"5372a36f4b2c5023788c23dbc6639155cb016a1b111e8fc1d6bf97cbaf11b1f8","blockSize":4194304,"blocks":["5372a36f4b2c5023788c23dbc6639155cb016a1b111e8fc1d6bf97cbaf11b1f8"]},"offset":"2278576"}}},"json":{"files":{"index.js":{"size":508,"integrity":{"algorithm":"SHA256","hash":"c5ac6a8005308e5bb36619fed225c987872300d356fa95d0d56878029ebbdc45","blockSize":4194304,"blocks":["c5ac6a8005308e5bb36619fed225c987872300d356fa95d0d56878029ebbdc45"]},"offset":"2280231"},"jsonfile.js":{"size":238,"integrity":{"algorithm":"SHA256","hash":"a986ad3c13166f3bf8f30b18140bfc8ea1754760ab3802aa7c8c3780d54f07ba","blockSize":4194304,"blocks":["a986ad3c13166f3bf8f30b18140bfc8ea1754760ab3802aa7c8c3780d54f07ba"]},"offset":"2280739"},"output-json-sync.js":{"size":276,"integrity":{"algorithm":"SHA256","hash":"a68fde22ad1a194755de03e90861805248f883342e05bd685258e76a90e7a6ab","blockSize":4194304,"blocks":["a68fde22ad1a194755de03e90861805248f883342e05bd685258e76a90e7a6ab"]},"offset":"2280977"},"output-json.js":{"size":277,"integrity":{"algorithm":"SHA256","hash":"b738aaf8ff9aae265b0512cb2554e1f8ce8605d21dc6230189a9be6980079fc8","blockSize":4194304,"blocks":["b738aaf8ff9aae265b0512cb2554e1f8ce8605d21dc6230189a9be6980079fc8"]},"offset":"2281253"}}},"fs":{"files":{"index.js":{"size":3373,"integrity":{"algorithm":"SHA256","hash":"620b6e703880fd6718c354c5359a5c37a2379054c037269dbcf7afd2503e4a6f","blockSize":4194304,"blocks":["620b6e703880fd6718c354c5359a5c37a2379054c037269dbcf7afd2503e4a6f"]},"offset":"2281530"}}},"ensure":{"files":{"file.js":{"size":1709,"integrity":{"algorithm":"SHA256","hash":"a104ff42c9aefd0e34556b9df2e4b5c9cd15315b0b0f70b07938901428b3c608","blockSize":4194304,"blocks":["a104ff42c9aefd0e34556b9df2e4b5c9cd15315b0b0f70b07938901428b3c608"]},"offset":"2284903"},"index.js":{"size":542,"integrity":{"algorithm":"SHA256","hash":"77ccb9b4d1eab607ce7ba8d3d5bed59b0cb9cc4748d02aa896a2413b71dbfe60","blockSize":4194304,"blocks":["77ccb9b4d1eab607ce7ba8d3d5bed59b0cb9cc4748d02aa896a2413b71dbfe60"]},"offset":"2286612"},"link.js":{"size":1652,"integrity":{"algorithm":"SHA256","hash":"339ce737e858367c65f79c0960bc6d1d617638aae07d396ac8ae5c8670b500c3","blockSize":4194304,"blocks":["339ce737e858367c65f79c0960bc6d1d617638aae07d396ac8ae5c8670b500c3"]},"offset":"2287154"},"symlink-paths.js":{"size":3374,"integrity":{"algorithm":"SHA256","hash":"5595b764059fb90ce4a13f5cdf43988da97e636521d3c599ce5260681d75bdfc","blockSize":4194304,"blocks":["5595b764059fb90ce4a13f5cdf43988da97e636521d3c599ce5260681d75bdfc"]},"offset":"2288806"},"symlink-type.js":{"size":694,"integrity":{"algorithm":"SHA256","hash":"17abe9590176305dd04316b2ac5c972dcf54cea32d279f955fbcf25098743dc8","blockSize":4194304,"blocks":["17abe9590176305dd04316b2ac5c972dcf54cea32d279f955fbcf25098743dc8"]},"offset":"2292180"},"symlink.js":{"size":2522,"integrity":{"algorithm":"SHA256","hash":"8b1fa73e5b5554380b710ccfbb4fe23764e53f0e5ce046689741310a82a19e21","blockSize":4194304,"blocks":["8b1fa73e5b5554380b710ccfbb4fe23764e53f0e5ce046689741310a82a19e21"]},"offset":"2292874"}}},"empty":{"files":{"index.js":{"size":747,"integrity":{"algorithm":"SHA256","hash":"1096edcb5ec0ed015b36914beff0826f6cd5d7ce2645ee9dee60c0b272e57856","blockSize":4194304,"blocks":["1096edcb5ec0ed015b36914beff0826f6cd5d7ce2645ee9dee60c0b272e57856"]},"offset":"2295396"}}},"copy":{"files":{"copy-sync.js":{"size":5776,"integrity":{"algorithm":"SHA256","hash":"a50856fe7fab3d1d22e8fbf5f32543d46342257cad5e31df8f2a7409fdf19c97","blockSize":4194304,"blocks":["a50856fe7fab3d1d22e8fbf5f32543d46342257cad5e31df8f2a7409fdf19c97"]},"offset":"2296143"},"copy.js":{"size":7756,"integrity":{"algorithm":"SHA256","hash":"b1ef00cadd368ea903c9a86927e40636cd832d8fa64344637c96e0e223faf876","blockSize":4194304,"blocks":["b1ef00cadd368ea903c9a86927e40636cd832d8fa64344637c96e0e223faf876"]},"offset":"2301919"},"index.js":{"size":147,"integrity":{"algorithm":"SHA256","hash":"f94ad0b8c5f5131a682be2d0427189c260e49fa748fb6f6bcc1f78678354e5d2","blockSize":4194304,"blocks":["f94ad0b8c5f5131a682be2d0427189c260e49fa748fb6f6bcc1f78678354e5d2"]},"offset":"2309675"}}}}}}},"jsonfile":{"files":{"LICENSE":{"size":1110,"integrity":{"algorithm":"SHA256","hash":"a9801fb52ba22ef808682a094da8a7a480584b7ed0dfd0d888ab543616335031","blockSize":4194304,"blocks":["a9801fb52ba22ef808682a094da8a7a480584b7ed0dfd0d888ab543616335031"]},"offset":"2309822"},"index.js":{"size":2014,"integrity":{"algorithm":"SHA256","hash":"ec5a9f1f45014486f1df4a8c11a5b078671e9936c0651e035b67cb5e763954e8","blockSize":4194304,"blocks":["ec5a9f1f45014486f1df4a8c11a5b078671e9936c0651e035b67cb5e763954e8"]},"offset":"2310932"},"package.json":{"size":558,"integrity":{"algorithm":"SHA256","hash":"19b7f70104b503224fc101fc465fb40765b077aa1f996f2d008463689a4fe4e6","blockSize":4194304,"blocks":["19b7f70104b503224fc101fc465fb40765b077aa1f996f2d008463689a4fe4e6"]},"offset":"2312946"},"utils.js":{"size":613,"integrity":{"algorithm":"SHA256","hash":"3a37b4b21c2cd8f75b850f1373f68a39bcaab3ac58d75ab44e62674cdb0d4cad","blockSize":4194304,"blocks":["3a37b4b21c2cd8f75b850f1373f68a39bcaab3ac58d75ab44e62674cdb0d4cad"]},"offset":"2313504"}}},"semver":{"files":{"LICENSE":{"size":765,"integrity":{"algorithm":"SHA256","hash":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","blockSize":4194304,"blocks":["4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b"]},"offset":"2314117"},"index.js":{"size":2630,"integrity":{"algorithm":"SHA256","hash":"646e0b707f56dca7cb90cebc6fe687278bcc1a16fdcc83756dbe23083ff15e06","blockSize":4194304,"blocks":["646e0b707f56dca7cb90cebc6fe687278bcc1a16fdcc83756dbe23083ff15e06"]},"offset":"2314882"},"package.json":{"size":1350,"integrity":{"algorithm":"SHA256","hash":"783e44dd42d6021177385b15de76f71d49d472f79b60ab22ed69f336d5e0f9d9","blockSize":4194304,"blocks":["783e44dd42d6021177385b15de76f71d49d472f79b60ab22ed69f336d5e0f9d9"]},"offset":"2317512"},"preload.js":{"size":83,"integrity":{"algorithm":"SHA256","hash":"edb6808911bebcb324b2df57e5c9935149e56984ff083b74c6cfe215f5b710ba","blockSize":4194304,"blocks":["edb6808911bebcb324b2df57e5c9935149e56984ff083b74c6cfe215f5b710ba"]},"offset":"2318862"},"range.bnf":{"size":619,"integrity":{"algorithm":"SHA256","hash":"ed628fdaff64be366d07f6cc4559eae4de109826f743ea7f5e1588c370bca49a","blockSize":4194304,"blocks":["ed628fdaff64be366d07f6cc4559eae4de109826f743ea7f5e1588c370bca49a"]},"offset":"2318945"},"ranges":{"files":{"gtr.js":{"size":231,"integrity":{"algorithm":"SHA256","hash":"8fadad28e36d28e93d498ac7ac20badba2a407312845eabc18e82e90a0732b19","blockSize":4194304,"blocks":["8fadad28e36d28e93d498ac7ac20badba2a407312845eabc18e82e90a0732b19"]},"offset":"2319564"},"intersects.js":{"size":224,"integrity":{"algorithm":"SHA256","hash":"fe87ac5d3020010ad3ec00636dadbf0c669ff07d0f57e0a8165a8264f79a676f","blockSize":4194304,"blocks":["fe87ac5d3020010ad3ec00636dadbf0c669ff07d0f57e0a8165a8264f79a676f"]},"offset":"2319795"},"ltr.js":{"size":227,"integrity":{"algorithm":"SHA256","hash":"e5186fcc03018acf9be6d968755d4c49727aeb0d981d179eb568ae5fbe983038","blockSize":4194304,"blocks":["e5186fcc03018acf9be6d968755d4c49727aeb0d981d179eb568ae5fbe983038"]},"offset":"2320019"},"max-satisfying.js":{"size":593,"integrity":{"algorithm":"SHA256","hash":"e1a2c0d6144cc772cd20bbc8ecb9e8a3a4074e9172a3d8e794838b591cdeb416","blockSize":4194304,"blocks":["e1a2c0d6144cc772cd20bbc8ecb9e8a3a4074e9172a3d8e794838b591cdeb416"]},"offset":"2320246"},"min-satisfying.js":{"size":591,"integrity":{"algorithm":"SHA256","hash":"2681abf54098aa670f12826b76a6ec77a2441186ae4243afde3be8ae4908f7ca","blockSize":4194304,"blocks":["2681abf54098aa670f12826b76a6ec77a2441186ae4243afde3be8ae4908f7ca"]},"offset":"2320839"},"min-version.js":{"size":1514,"integrity":{"algorithm":"SHA256","hash":"fefba0a88c2bf74d5cede504b5ae50a8dc3edfd69cf0174a491e2cf3e442614b","blockSize":4194304,"blocks":["fefba0a88c2bf74d5cede504b5ae50a8dc3edfd69cf0174a491e2cf3e442614b"]},"offset":"2321430"},"outside.js":{"size":2204,"integrity":{"algorithm":"SHA256","hash":"3a2b0b23593d2f49419c06af2af75450cab103b0c25d665d48fe5bca495a21ca","blockSize":4194304,"blocks":["3a2b0b23593d2f49419c06af2af75450cab103b0c25d665d48fe5bca495a21ca"]},"offset":"2322944"},"simplify.js":{"size":1355,"integrity":{"algorithm":"SHA256","hash":"7b78581c13322bc68ece2088685386b2a9b51c15b94d0a2063bdf2546bd41934","blockSize":4194304,"blocks":["7b78581c13322bc68ece2088685386b2a9b51c15b94d0a2063bdf2546bd41934"]},"offset":"2325148"},"subset.js":{"size":7524,"integrity":{"algorithm":"SHA256","hash":"87387952fbe154f5874d5f09dd2173e782e894a76fa8370ce23f4120e2ae7eae","blockSize":4194304,"blocks":["87387952fbe154f5874d5f09dd2173e782e894a76fa8370ce23f4120e2ae7eae"]},"offset":"2326503"},"to-comparators.js":{"size":282,"integrity":{"algorithm":"SHA256","hash":"6c5e966210cff270fa2850668aaf8460fac7759f8d99f282521ef7a78f4564e9","blockSize":4194304,"blocks":["6c5e966210cff270fa2850668aaf8460fac7759f8d99f282521ef7a78f4564e9"]},"offset":"2334027"},"valid.js":{"size":326,"integrity":{"algorithm":"SHA256","hash":"5ef6f995af801868925940cf8df5735d565ebabb090b068695cae65218bcd3ac","blockSize":4194304,"blocks":["5ef6f995af801868925940cf8df5735d565ebabb090b068695cae65218bcd3ac"]},"offset":"2334309"}}},"internal":{"files":{"constants.js":{"size":873,"integrity":{"algorithm":"SHA256","hash":"38a112baf27ceca0260082ff26ac2fd7a9861cab1af12dd65e720277f68e6ce9","blockSize":4194304,"blocks":["38a112baf27ceca0260082ff26ac2fd7a9861cab1af12dd65e720277f68e6ce9"]},"offset":"2334635"},"debug.js":{"size":240,"integrity":{"algorithm":"SHA256","hash":"8a9f420572260f3cf944463b5090d62a60f0730589dc23a7ec4ca25e2ee41bb3","blockSize":4194304,"blocks":["8a9f420572260f3cf944463b5090d62a60f0730589dc23a7ec4ca25e2ee41bb3"]},"offset":"2335508"},"identifiers.js":{"size":525,"integrity":{"algorithm":"SHA256","hash":"b4916b09dc7869ae0eb05e71c855c942a3a7365f7e6e89185d59a9e45a2451d7","blockSize":4194304,"blocks":["b4916b09dc7869ae0eb05e71c855c942a3a7365f7e6e89185d59a9e45a2451d7"]},"offset":"2335748"},"lrucache.js":{"size":802,"integrity":{"algorithm":"SHA256","hash":"14d087c87da87b6f5c36fc4cdd7d2d14077874b14a68e20fce5b6138fa2ca34f","blockSize":4194304,"blocks":["14d087c87da87b6f5c36fc4cdd7d2d14077874b14a68e20fce5b6138fa2ca34f"]},"offset":"2336273"},"parse-options.js":{"size":338,"integrity":{"algorithm":"SHA256","hash":"fdf51d0de8d5442c35a997ef58cd530d239ce206f961d14c5121354451b01d01","blockSize":4194304,"blocks":["fdf51d0de8d5442c35a997ef58cd530d239ce206f961d14c5121354451b01d01"]},"offset":"2337075"},"re.js":{"size":8138,"integrity":{"algorithm":"SHA256","hash":"6a47e73c279fa8c4011f670471f50830a39922b43797b2884e6cc03f65b64d6c","blockSize":4194304,"blocks":["6a47e73c279fa8c4011f670471f50830a39922b43797b2884e6cc03f65b64d6c"]},"offset":"2337413"}}},"functions":{"files":{"clean.js":{"size":205,"integrity":{"algorithm":"SHA256","hash":"4eadb0892844cf3ae295121a86163a66c73f89acd1b7f0b114ec115b4539512f","blockSize":4194304,"blocks":["4eadb0892844cf3ae295121a86163a66c73f89acd1b7f0b114ec115b4539512f"]},"offset":"2345551"},"cmp.js":{"size":961,"integrity":{"algorithm":"SHA256","hash":"a63d74e87b73788e78e9ce0a4892b5333d6b809c0de88b31e4ed76cbf17f94b3","blockSize":4194304,"blocks":["a63d74e87b73788e78e9ce0a4892b5333d6b809c0de88b31e4ed76cbf17f94b3"]},"offset":"2345756"},"coerce.js":{"size":2004,"integrity":{"algorithm":"SHA256","hash":"28a251c5ab210ddf9e97551b9f37a53329fcce91f0c3943dcbc02de1a1de915a","blockSize":4194304,"blocks":["28a251c5ab210ddf9e97551b9f37a53329fcce91f0c3943dcbc02de1a1de915a"]},"offset":"2346717"},"compare-build.js":{"size":281,"integrity":{"algorithm":"SHA256","hash":"5ab651d5b40af289bd85c645a92b6d8cfe1a986dc413c797cfcc8d623d7c844c","blockSize":4194304,"blocks":["5ab651d5b40af289bd85c645a92b6d8cfe1a986dc413c797cfcc8d623d7c844c"]},"offset":"2348721"},"compare-loose.js":{"size":132,"integrity":{"algorithm":"SHA256","hash":"07b6a3a1db0a5210ceb784c1708bd4679f3a94fc73a9c9eb349349e7070a6f78","blockSize":4194304,"blocks":["07b6a3a1db0a5210ceb784c1708bd4679f3a94fc73a9c9eb349349e7070a6f78"]},"offset":"2349002"},"compare.js":{"size":170,"integrity":{"algorithm":"SHA256","hash":"d404b5aa48aaddc8a654c5da8fb7d4443404b7948589b21ac4b045d1cee4e34c","blockSize":4194304,"blocks":["d404b5aa48aaddc8a654c5da8fb7d4443404b7948589b21ac4b045d1cee4e34c"]},"offset":"2349134"},"diff.js":{"size":1423,"integrity":{"algorithm":"SHA256","hash":"7a11fd39b987cdf06c65e928cb1aca49bec583feb86fb5c8fe47a6fd61d7de31","blockSize":4194304,"blocks":["7a11fd39b987cdf06c65e928cb1aca49bec583feb86fb5c8fe47a6fd61d7de31"]},"offset":"2349304"},"eq.js":{"size":126,"integrity":{"algorithm":"SHA256","hash":"b6e30a7168e52723216fc163d300e2bbabf92ec0251f9ac5438bb6ccf57c8936","blockSize":4194304,"blocks":["b6e30a7168e52723216fc163d300e2bbabf92ec0251f9ac5438bb6ccf57c8936"]},"offset":"2350727"},"gt.js":{"size":124,"integrity":{"algorithm":"SHA256","hash":"135523704aa48cd98834dd170ee9f74f0e68043b379f32d021db11e6304c5c93","blockSize":4194304,"blocks":["135523704aa48cd98834dd170ee9f74f0e68043b379f32d021db11e6304c5c93"]},"offset":"2350853"},"gte.js":{"size":127,"integrity":{"algorithm":"SHA256","hash":"991c5bbe48ecb210a562646872f05862ad9fc0d42186d85aa60bdc6fa323eb9d","blockSize":4194304,"blocks":["991c5bbe48ecb210a562646872f05862ad9fc0d42186d85aa60bdc6fa323eb9d"]},"offset":"2350977"},"inc.js":{"size":478,"integrity":{"algorithm":"SHA256","hash":"952069fc8690b7d3af0fe9d55f7c54fe2ac067b48c5e74f6a54f9ce19a334493","blockSize":4194304,"blocks":["952069fc8690b7d3af0fe9d55f7c54fe2ac067b48c5e74f6a54f9ce19a334493"]},"offset":"2351104"},"lt.js":{"size":124,"integrity":{"algorithm":"SHA256","hash":"1c897a9bc849320e2e9dc0f6c09555c01ee3ddf30734515d717b88ad7740ea25","blockSize":4194304,"blocks":["1c897a9bc849320e2e9dc0f6c09555c01ee3ddf30734515d717b88ad7740ea25"]},"offset":"2351582"},"lte.js":{"size":127,"integrity":{"algorithm":"SHA256","hash":"3a8d0b1d00423f60cc7cb810b36ab77b61330831ad237dbe73eb5cecfa412800","blockSize":4194304,"blocks":["3a8d0b1d00423f60cc7cb810b36ab77b61330831ad237dbe73eb5cecfa412800"]},"offset":"2351706"},"major.js":{"size":136,"integrity":{"algorithm":"SHA256","hash":"5c678480d882f511200fed2c16ec3847dfedb08a1d70328dc2f031d35d825276","blockSize":4194304,"blocks":["5c678480d882f511200fed2c16ec3847dfedb08a1d70328dc2f031d35d825276"]},"offset":"2351833"},"minor.js":{"size":136,"integrity":{"algorithm":"SHA256","hash":"1b051794f1713adec2a236517196691687c35f82e0b596ff3316a78b3cc10ae6","blockSize":4194304,"blocks":["1b051794f1713adec2a236517196691687c35f82e0b596ff3316a78b3cc10ae6"]},"offset":"2351969"},"neq.js":{"size":128,"integrity":{"algorithm":"SHA256","hash":"a662883751918822c162183b46b9e20d09489132f82686c92ab78bee67f3a127","blockSize":4194304,"blocks":["a662883751918822c162183b46b9e20d09489132f82686c92ab78bee67f3a127"]},"offset":"2352105"},"parse.js":{"size":331,"integrity":{"algorithm":"SHA256","hash":"29a69e15b6d02fe381d573f861881a89590e9d0f0f0ca740c5f85eaf0234c4ad","blockSize":4194304,"blocks":["29a69e15b6d02fe381d573f861881a89590e9d0f0f0ca740c5f85eaf0234c4ad"]},"offset":"2352233"},"patch.js":{"size":136,"integrity":{"algorithm":"SHA256","hash":"f02d3c1b059fe3d96ce124886f7eef321d381a95638fd3c4a8d5ccd8e76ffadd","blockSize":4194304,"blocks":["f02d3c1b059fe3d96ce124886f7eef321d381a95638fd3c4a8d5ccd8e76ffadd"]},"offset":"2352564"},"prerelease.js":{"size":234,"integrity":{"algorithm":"SHA256","hash":"baedbf503d5610ad041bfb56071efa48feb331ca278295c399537d35d3ffb593","blockSize":4194304,"blocks":["baedbf503d5610ad041bfb56071efa48feb331ca278295c399537d35d3ffb593"]},"offset":"2352700"},"rcompare.js":{"size":132,"integrity":{"algorithm":"SHA256","hash":"84fa5e88adf08d15c993cac8cdec6d1a65045b7e95a9c55184230a7f807f4dc0","blockSize":4194304,"blocks":["84fa5e88adf08d15c993cac8cdec6d1a65045b7e95a9c55184230a7f807f4dc0"]},"offset":"2352934"},"rsort.js":{"size":163,"integrity":{"algorithm":"SHA256","hash":"6ec659ce3b6c2b173c719286caab04409adba046c0917874ec3b5e36ddfbc7e3","blockSize":4194304,"blocks":["6ec659ce3b6c2b173c719286caab04409adba046c0917874ec3b5e36ddfbc7e3"]},"offset":"2353066"},"satisfies.js":{"size":247,"integrity":{"algorithm":"SHA256","hash":"8cf5e122b757251671ed6c9d9680904b71cd375845853f05312e608cf2cc2946","blockSize":4194304,"blocks":["8cf5e122b757251671ed6c9d9680904b71cd375845853f05312e608cf2cc2946"]},"offset":"2353229"},"sort.js":{"size":161,"integrity":{"algorithm":"SHA256","hash":"c2fe2d3ed0be8a4e9de8f02abdfd5d9c0d3bcc510d88e87af84185592882c4b8","blockSize":4194304,"blocks":["c2fe2d3ed0be8a4e9de8f02abdfd5d9c0d3bcc510d88e87af84185592882c4b8"]},"offset":"2353476"},"valid.js":{"size":176,"integrity":{"algorithm":"SHA256","hash":"0de7ea736cb7807179d46dfac09c830a9338e02b6a07db12d7040cde2def6025","blockSize":4194304,"blocks":["0de7ea736cb7807179d46dfac09c830a9338e02b6a07db12d7040cde2def6025"]},"offset":"2353637"}}},"classes":{"files":{"comparator.js":{"size":3631,"integrity":{"algorithm":"SHA256","hash":"054202956430d63d5ff4599fae09760ce465b489e4f0b5ef5ce7cc7ac21157ac","blockSize":4194304,"blocks":["054202956430d63d5ff4599fae09760ce465b489e4f0b5ef5ce7cc7ac21157ac"]},"offset":"2353813"},"index.js":{"size":143,"integrity":{"algorithm":"SHA256","hash":"3bb69280c2a788d0eb16f915bb9df4dbe812075182024c753dca2283bcea1b17","blockSize":4194304,"blocks":["3bb69280c2a788d0eb16f915bb9df4dbe812075182024c753dca2283bcea1b17"]},"offset":"2357444"},"range.js":{"size":14977,"integrity":{"algorithm":"SHA256","hash":"cf8f8eb6934663ae2a9d04838d4d71555427a2abd3c8748ee5219507969a6b46","blockSize":4194304,"blocks":["cf8f8eb6934663ae2a9d04838d4d71555427a2abd3c8748ee5219507969a6b46"]},"offset":"2357587"},"semver.js":{"size":9480,"integrity":{"algorithm":"SHA256","hash":"d5ba57e5c93f031b1d234fca4bb746746fcd1fe51be7e5ee895601e2c12e2083","blockSize":4194304,"blocks":["d5ba57e5c93f031b1d234fca4bb746746fcd1fe51be7e5ee895601e2c12e2083"]},"offset":"2372564"}}},"bin":{"files":{"semver.js":{"size":4748,"integrity":{"algorithm":"SHA256","hash":"82c28f9bc9e598d255edd507d1e9b157f37b8dac0f2da25a813b5e7121600be8","blockSize":4194304,"blocks":["82c28f9bc9e598d255edd507d1e9b157f37b8dac0f2da25a813b5e7121600be8"]},"offset":"2382044","executable":true}}}}},"universalify":{"files":{"LICENSE":{"size":1100,"integrity":{"algorithm":"SHA256","hash":"3fda5977c0904e226190b4e21d64340c1731e2142d6fe5f3dee0090a216b8b63","blockSize":4194304,"blocks":["3fda5977c0904e226190b4e21d64340c1731e2142d6fe5f3dee0090a216b8b63"]},"offset":"2386792"},"index.js":{"size":706,"integrity":{"algorithm":"SHA256","hash":"83b02adb3872f6c482db4e57c300fa39b5cad65e317fc2f70b9de7d305c035a1","blockSize":4194304,"blocks":["83b02adb3872f6c482db4e57c300fa39b5cad65e317fc2f70b9de7d305c035a1"]},"offset":"2387892"},"package.json":{"size":618,"integrity":{"algorithm":"SHA256","hash":"5b39e9c6305a5ba27c76caf4817244dd1a308b68c7559dfe15471173466cf06e","blockSize":4194304,"blocks":["5b39e9c6305a5ba27c76caf4817244dd1a308b68c7559dfe15471173466cf06e"]},"offset":"2388598"}}}}}}},"graceful-fs":{"files":{"LICENSE":{"size":791,"integrity":{"algorithm":"SHA256","hash":"f65c5d9f22a317b2a10803bd1868461ce6499c2ed7217bc80c0cc772a748789c","blockSize":4194304,"blocks":["f65c5d9f22a317b2a10803bd1868461ce6499c2ed7217bc80c0cc772a748789c"]},"offset":"991841"},"clone.js":{"size":496,"integrity":{"algorithm":"SHA256","hash":"7258eca52e65d69845759503f9fdd66c252f40e5eafb76db5d481172e31ac9ed","blockSize":4194304,"blocks":["7258eca52e65d69845759503f9fdd66c252f40e5eafb76db5d481172e31ac9ed"]},"offset":"992632"},"graceful-fs.js":{"size":12680,"integrity":{"algorithm":"SHA256","hash":"7da35669b6b6b0e4aafee31674c033f2cebb0c8f9ae010f709dcc185d3f17786","blockSize":4194304,"blocks":["7da35669b6b6b0e4aafee31674c033f2cebb0c8f9ae010f709dcc185d3f17786"]},"offset":"993128"},"legacy-streams.js":{"size":2655,"integrity":{"algorithm":"SHA256","hash":"60a6a7ecf7c3e55a3ffaae13433b6cff388b7205bba6daf393c863f77a949e36","blockSize":4194304,"blocks":["60a6a7ecf7c3e55a3ffaae13433b6cff388b7205bba6daf393c863f77a949e36"]},"offset":"1005808"},"package.json":{"size":600,"integrity":{"algorithm":"SHA256","hash":"5f558a45ee1f8ea431e950ab3864f842b9de5325e30a31ba1bd68f6f768457ed","blockSize":4194304,"blocks":["5f558a45ee1f8ea431e950ab3864f842b9de5325e30a31ba1bd68f6f768457ed"]},"offset":"1008463"},"polyfills.js":{"size":10141,"integrity":{"algorithm":"SHA256","hash":"66ea1687ed5edf39d67296d26edccc8da695d9a869303a78d0e580cd770aca27","blockSize":4194304,"blocks":["66ea1687ed5edf39d67296d26edccc8da695d9a869303a78d0e580cd770aca27"]},"offset":"1009063"}}},"js-yaml":{"files":{"LICENSE":{"size":1084,"integrity":{"algorithm":"SHA256","hash":"a07bc24468b9654ce76a547d47a2db282d07733b715db4c73a98bd63961f9550","blockSize":4194304,"blocks":["a07bc24468b9654ce76a547d47a2db282d07733b715db4c73a98bd63961f9550"]},"offset":"1019204"},"index.js":{"size":1585,"integrity":{"algorithm":"SHA256","hash":"e85d524fcd45466669dfc37618284e0c53ccaaf3f4bef1e23cd25ec6c43120bc","blockSize":4194304,"blocks":["e85d524fcd45466669dfc37618284e0c53ccaaf3f4bef1e23cd25ec6c43120bc"]},"offset":"1020288"},"package.json":{"size":1357,"integrity":{"algorithm":"SHA256","hash":"1ccdc693bf7e12b3ef59660ab35ddc0ccc70e23c2b3aff648ad45c823e27ad24","blockSize":4194304,"blocks":["1ccdc693bf7e12b3ef59660ab35ddc0ccc70e23c2b3aff648ad45c823e27ad24"]},"offset":"1021873"},"lib":{"files":{"common.js":{"size":1094,"integrity":{"algorithm":"SHA256","hash":"72216ccee36a52ece3f21f2d58a679c14c1483201ef6cbbfc4a1aa9cb6d34c9c","blockSize":4194304,"blocks":["72216ccee36a52ece3f21f2d58a679c14c1483201ef6cbbfc4a1aa9cb6d34c9c"]},"offset":"1023230"},"dumper.js":{"size":30967,"integrity":{"algorithm":"SHA256","hash":"695c80b3c310ef3f6fbd232bbcd3f82464917a008c24f1e05b560f35c20116a0","blockSize":4194304,"blocks":["695c80b3c310ef3f6fbd232bbcd3f82464917a008c24f1e05b560f35c20116a0"]},"offset":"1024324"},"exception.js":{"size":1285,"integrity":{"algorithm":"SHA256","hash":"9ef16628112beacc7497c3f3d0ab001c66c2db501f9e21fad4c30e7cd21d1d10","blockSize":4194304,"blocks":["9ef16628112beacc7497c3f3d0ab001c66c2db501f9e21fad4c30e7cd21d1d10"]},"offset":"1055291"},"index_vite_proxy.tmp.mjs":{"size":434,"integrity":{"algorithm":"SHA256","hash":"a846cc31e1d31c304edaf94c48624568b699803a79ae2ee88d6e5c66e49552f7","blockSize":4194304,"blocks":["a846cc31e1d31c304edaf94c48624568b699803a79ae2ee88d6e5c66e49552f7"]},"offset":"1056576"},"loader.js":{"size":50665,"integrity":{"algorithm":"SHA256","hash":"8b6c0d49b3cf2f3e423242b3edf4187a69aa8e35c44aa8d716af500edc6914e6","blockSize":4194304,"blocks":["8b6c0d49b3cf2f3e423242b3edf4187a69aa8e35c44aa8d716af500edc6914e6"]},"offset":"1057010"},"schema.js":{"size":3257,"integrity":{"algorithm":"SHA256","hash":"dd26a9e56d934099eb53e04f242ed1962660e4e64697c300ff5c4bc1a83165da","blockSize":4194304,"blocks":["dd26a9e56d934099eb53e04f242ed1962660e4e64697c300ff5c4bc1a83165da"]},"offset":"1107675"},"snippet.js":{"size":3063,"integrity":{"algorithm":"SHA256","hash":"c9180c66091356e16a750c07cbc21ee477d6d07e7c39b6a8622e5882cf85326d","blockSize":4194304,"blocks":["c9180c66091356e16a750c07cbc21ee477d6d07e7c39b6a8622e5882cf85326d"]},"offset":"1110932"},"type.js":{"size":1736,"integrity":{"algorithm":"SHA256","hash":"a595092ee9fb6901769201ff7e5a485ee5f501bd1519d209af93b37dd2314a32","blockSize":4194304,"blocks":["a595092ee9fb6901769201ff7e5a485ee5f501bd1519d209af93b37dd2314a32"]},"offset":"1113995"},"type":{"files":{"binary.js":{"size":2853,"integrity":{"algorithm":"SHA256","hash":"9dd6a70eb318a123fdc11a36d613419d79535b6ecf105bd865de3a5cbbb60e7c","blockSize":4194304,"blocks":["9dd6a70eb318a123fdc11a36d613419d79535b6ecf105bd865de3a5cbbb60e7c"]},"offset":"1115731"},"bool.js":{"size":967,"integrity":{"algorithm":"SHA256","hash":"cc0d255ac6c55064421c19bbea312dcb9e22aee49fa9f8461723d9fbf7a0f8b3","blockSize":4194304,"blocks":["cc0d255ac6c55064421c19bbea312dcb9e22aee49fa9f8461723d9fbf7a0f8b3"]},"offset":"1118584"},"float.js":{"size":2485,"integrity":{"algorithm":"SHA256","hash":"42b4d238e5d00267fe126996b912f34506d273c39725524d662626bb9e2d4e7e","blockSize":4194304,"blocks":["42b4d238e5d00267fe126996b912f34506d273c39725524d662626bb9e2d4e7e"]},"offset":"1119551"},"int.js":{"size":3318,"integrity":{"algorithm":"SHA256","hash":"9d428a6e6de891a52b2b5ebd2bf09f9d1f9506514aaf35c6428f0111ecf86fdb","blockSize":4194304,"blocks":["9d428a6e6de891a52b2b5ebd2bf09f9d1f9506514aaf35c6428f0111ecf86fdb"]},"offset":"1122036"},"map.js":{"size":188,"integrity":{"algorithm":"SHA256","hash":"6dd30a02cabaccf71c230464537bda5785093da80cd3319ed3a6481206e2ec7d","blockSize":4194304,"blocks":["6dd30a02cabaccf71c230464537bda5785093da80cd3319ed3a6481206e2ec7d"]},"offset":"1125354"},"merge.js":{"size":229,"integrity":{"algorithm":"SHA256","hash":"4cd0343e63f3c3d7cea620cf122e3dd8f8d1c4c4105d384e8d82d35ae154d1e2","blockSize":4194304,"blocks":["4cd0343e63f3c3d7cea620cf122e3dd8f8d1c4c4105d384e8d82d35ae154d1e2"]},"offset":"1125542"},"null.js":{"size":791,"integrity":{"algorithm":"SHA256","hash":"5eea804da258ba10fa736199ed0cef9d89dbb01eac1c1bd3609a79a132d1885e","blockSize":4194304,"blocks":["5eea804da258ba10fa736199ed0cef9d89dbb01eac1c1bd3609a79a132d1885e"]},"offset":"1125771"},"omap.js":{"size":1036,"integrity":{"algorithm":"SHA256","hash":"8a865841abeb5f12a30f39f095967b6ac05ef6240e78872573fb23e8c9b5c47f","blockSize":4194304,"blocks":["8a865841abeb5f12a30f39f095967b6ac05ef6240e78872573fb23e8c9b5c47f"]},"offset":"1126562"},"pairs.js":{"size":1031,"integrity":{"algorithm":"SHA256","hash":"f9eb5d2dc3cdbf7dd802e0a62b5aa2d09eedeb0509b71a247ebdad223315d6a5","blockSize":4194304,"blocks":["f9eb5d2dc3cdbf7dd802e0a62b5aa2d09eedeb0509b71a247ebdad223315d6a5"]},"offset":"1127598"},"seq.js":{"size":189,"integrity":{"algorithm":"SHA256","hash":"3a38b7f3242737c2e21462c42a8da1682325686cb2b30dc3630e515cf9c45522","blockSize":4194304,"blocks":["3a38b7f3242737c2e21462c42a8da1682325686cb2b30dc3630e515cf9c45522"]},"offset":"1128629"},"set.js":{"size":547,"integrity":{"algorithm":"SHA256","hash":"fa5b815c6334def52dae5b58193d3798f8e53558f6c7f48a643898e996333dd7","blockSize":4194304,"blocks":["fa5b815c6334def52dae5b58193d3798f8e53558f6c7f48a643898e996333dd7"]},"offset":"1128818"},"str.js":{"size":187,"integrity":{"algorithm":"SHA256","hash":"1f8725eac2dc7bed4b91610f21796ed3c057cee44b81a1ae8cc9beb9cd6c63ff","blockSize":4194304,"blocks":["1f8725eac2dc7bed4b91610f21796ed3c057cee44b81a1ae8cc9beb9cd6c63ff"]},"offset":"1129365"},"timestamp.js":{"size":2364,"integrity":{"algorithm":"SHA256","hash":"54e2070e0319d7fa3becd426dd5bfdb822b9602bd4a3c366976cbaa2278bdb5c","blockSize":4194304,"blocks":["54e2070e0319d7fa3becd426dd5bfdb822b9602bd4a3c366976cbaa2278bdb5c"]},"offset":"1129552"}}},"schema":{"files":{"core.js":{"size":284,"integrity":{"algorithm":"SHA256","hash":"201ffb119aad04c9397df088452e00910becab9a43a3b3a392370878646c06ad","blockSize":4194304,"blocks":["201ffb119aad04c9397df088452e00910becab9a43a3b3a392370878646c06ad"]},"offset":"1131916"},"default.js":{"size":534,"integrity":{"algorithm":"SHA256","hash":"1c4c9573b4c05ce47391c6bcba10401385d8d6a4d596c1c0fd1d6ea664f97ea2","blockSize":4194304,"blocks":["1c4c9573b4c05ce47391c6bcba10401385d8d6a4d596c1c0fd1d6ea664f97ea2"]},"offset":"1132200"},"failsafe.js":{"size":274,"integrity":{"algorithm":"SHA256","hash":"8e109fccabab5c066b66113f5d68bb74372f48bf589de39e44ed26432a98a27a","blockSize":4194304,"blocks":["8e109fccabab5c066b66113f5d68bb74372f48bf589de39e44ed26432a98a27a"]},"offset":"1132734"},"json.js":{"size":519,"integrity":{"algorithm":"SHA256","hash":"b08f46efd2c45c46c6d3eaf9b05489356d80391c5f7d5094fb8ec7713e796281","blockSize":4194304,"blocks":["b08f46efd2c45c46c6d3eaf9b05489356d80391c5f7d5094fb8ec7713e796281"]},"offset":"1133008"}}}}},"dist":{"files":{"js-yaml.js":{"size":131335,"integrity":{"algorithm":"SHA256","hash":"09a14e2cb63130302308b94500c4e6d99fc57be5070c32dc1fbe3d942386ad3c","blockSize":4194304,"blocks":["09a14e2cb63130302308b94500c4e6d99fc57be5070c32dc1fbe3d942386ad3c"]},"offset":"1133527"},"js-yaml.js.map":{"size":190875,"integrity":{"algorithm":"SHA256","hash":"82280e5ab0259cd0a087011d32979254ec8330605f7b14d2a9b904f9a5a1997f","blockSize":4194304,"blocks":["82280e5ab0259cd0a087011d32979254ec8330605f7b14d2a9b904f9a5a1997f"]},"offset":"1264862"},"js-yaml.min.js":{"size":43549,"integrity":{"algorithm":"SHA256","hash":"fdb7c9f75afd2f3b6baa3aa53e648d10fe7815276e305d3d681af37e09454ea6","blockSize":4194304,"blocks":["fdb7c9f75afd2f3b6baa3aa53e648d10fe7815276e305d3d681af37e09454ea6"]},"offset":"1455737"},"js-yaml.min.js.map":{"size":179229,"integrity":{"algorithm":"SHA256","hash":"c3ea061cc5d63fdc4f37ecf6b7287e77145a235296ac42b6eedf9ace6f267786","blockSize":4194304,"blocks":["c3ea061cc5d63fdc4f37ecf6b7287e77145a235296ac42b6eedf9ace6f267786"]},"offset":"1499286"},"js-yaml.mjs":{"size":103891,"integrity":{"algorithm":"SHA256","hash":"33e98d04719e7a7fc8e0433803ad4b26a6f72d4545d279a5b053d45bd7871c7a","blockSize":4194304,"blocks":["33e98d04719e7a7fc8e0433803ad4b26a6f72d4545d279a5b053d45bd7871c7a"]},"offset":"1678515"},"js-yaml.mjs.map":{"size":183161,"integrity":{"algorithm":"SHA256","hash":"f3985e79b3b482fe0b4fa8ad680d87485d9d562af7de4d10e171d9595ad8ca1d","blockSize":4194304,"blocks":["f3985e79b3b482fe0b4fa8ad680d87485d9d562af7de4d10e171d9595ad8ca1d"]},"offset":"1782406"}}},"bin":{"files":{"js-yaml.js":{"size":2658,"integrity":{"algorithm":"SHA256","hash":"b3e6a451bd8bc5cba3a12851396d15fc109faf0a5a018d96b5535fe1fcfedb54","blockSize":4194304,"blocks":["b3e6a451bd8bc5cba3a12851396d15fc109faf0a5a018d96b5535fe1fcfedb54"]},"offset":"1965567","executable":true}}}}},"lazy-val":{"files":{"package.json":{"size":330,"integrity":{"algorithm":"SHA256","hash":"a6f4140d0187f32d95545835aca38684e18d0fcfbecb51709b0aaa54decd3c0b","blockSize":4194304,"blocks":["a6f4140d0187f32d95545835aca38684e18d0fcfbecb51709b0aaa54decd3c0b"]},"offset":"1968225"},"out":{"files":{"main.js":{"size":605,"integrity":{"algorithm":"SHA256","hash":"358fa8cba70c9140edafa85c0b7b25c7261939480186167e6b3440905f5b47da","blockSize":4194304,"blocks":["358fa8cba70c9140edafa85c0b7b25c7261939480186167e6b3440905f5b47da"]},"offset":"1968555"},"main.js.map":{"size":1156,"integrity":{"algorithm":"SHA256","hash":"aa3e70f08a0ce115832e5324c4b96aa1475a3b8b36728f50091ebd22aa0f6646","blockSize":4194304,"blocks":["aa3e70f08a0ce115832e5324c4b96aa1475a3b8b36728f50091ebd22aa0f6646"]},"offset":"1969160"}}}}},"lodash.escaperegexp":{"files":{"LICENSE":{"size":1951,"integrity":{"algorithm":"SHA256","hash":"ffd8b33b354585f4ce119f19c53728281e48a97b074491eb6bf6d5c5ff305272","blockSize":4194304,"blocks":["ffd8b33b354585f4ce119f19c53728281e48a97b074491eb6bf6d5c5ff305272"]},"offset":"1970316"},"index.js":{"size":4398,"integrity":{"algorithm":"SHA256","hash":"584de6ec78e35344eaef8291338a671f223ec225c4df4220b6f91d8f0c004d8d","blockSize":4194304,"blocks":["584de6ec78e35344eaef8291338a671f223ec225c4df4220b6f91d8f0c004d8d"]},"offset":"1972267"},"package.json":{"size":356,"integrity":{"algorithm":"SHA256","hash":"c71b659d3f3f5dfab55d736b6bd17d97f822b13bcf9b1edbce479f8e691e7892","blockSize":4194304,"blocks":["c71b659d3f3f5dfab55d736b6bd17d97f822b13bcf9b1edbce479f8e691e7892"]},"offset":"1976665"}}},"lodash.isequal":{"files":{"LICENSE":{"size":1950,"integrity":{"algorithm":"SHA256","hash":"e159c6d48c989185448658f276375bfb2300362ec6d4ae5525a2d49c4bcb947d","blockSize":4194304,"blocks":["e159c6d48c989185448658f276375bfb2300362ec6d4ae5525a2d49c4bcb947d"]},"offset":"1977021"},"index.js":{"size":49598,"integrity":{"algorithm":"SHA256","hash":"e552928a511748303101cfd03826a777cfa359eade6a4a60f92c923edbf9184c","blockSize":4194304,"blocks":["e552928a511748303101cfd03826a777cfa359eade6a4a60f92c923edbf9184c"]},"offset":"1978971"},"package.json":{"size":346,"integrity":{"algorithm":"SHA256","hash":"6e84ac44b54c17317d096a280e9d0bd72d736e0a0245095cc7c5d72657890406","blockSize":4194304,"blocks":["6e84ac44b54c17317d096a280e9d0bd72d736e0a0245095cc7c5d72657890406"]},"offset":"2028569"}}},"ms":{"files":{"index.js":{"size":3024,"integrity":{"algorithm":"SHA256","hash":"e5f0b6a946a9b2b356a28557728410717df54ea2f599edb619f9839df6b7b0e9","blockSize":4194304,"blocks":["e5f0b6a946a9b2b356a28557728410717df54ea2f599edb619f9839df6b7b0e9"]},"offset":"2028915"},"license.md":{"size":1079,"integrity":{"algorithm":"SHA256","hash":"1662fae9b5314d11cf51284e2dcd1f006a354f7343f08712a730fcff9a359801","blockSize":4194304,"blocks":["1662fae9b5314d11cf51284e2dcd1f006a354f7343f08712a730fcff9a359801"]},"offset":"2031939"},"package.json":{"size":497,"integrity":{"algorithm":"SHA256","hash":"f983ec581f1dd5a47b7f12b58f97c0b44c4e0cce56cbecc40140031aeef99bdf","blockSize":4194304,"blocks":["f983ec581f1dd5a47b7f12b58f97c0b44c4e0cce56cbecc40140031aeef99bdf"]},"offset":"2033018"}}},"sax":{"files":{"LICENSE.md":{"size":1552,"integrity":{"algorithm":"SHA256","hash":"8a1af140fdfbf5afd3df27f7e662f989c5b963a300020dfafce42033cae9e004","blockSize":4194304,"blocks":["8a1af140fdfbf5afd3df27f7e662f989c5b963a300020dfafce42033cae9e004"]},"offset":"2033515"},"package.json":{"size":565,"integrity":{"algorithm":"SHA256","hash":"26df984c41445dbfe2a4981d80660bebc7611e69ab260226b29021a202ee0834","blockSize":4194304,"blocks":["26df984c41445dbfe2a4981d80660bebc7611e69ab260226b29021a202ee0834"]},"offset":"2035067"},"lib":{"files":{"sax.js":{"size":50818,"integrity":{"algorithm":"SHA256","hash":"1cdc1270d987cb0f6ee66dd8efb01c50511aa14d17b6163bbbffb21df8cf1c06","blockSize":4194304,"blocks":["1cdc1270d987cb0f6ee66dd8efb01c50511aa14d17b6163bbbffb21df8cf1c06"]},"offset":"2035632"}}}}},"tiny-typed-emitter":{"files":{"LICENSE":{"size":1104,"integrity":{"algorithm":"SHA256","hash":"4b3faf884ee71eec3df920b66c98fc6618af28e824cf3a32ef3d8774048cc76d","blockSize":4194304,"blocks":["4b3faf884ee71eec3df920b66c98fc6618af28e824cf3a32ef3d8774048cc76d"]},"offset":"2086450"},"package.json":{"size":395,"integrity":{"algorithm":"SHA256","hash":"eb7f51a4a5a7f41baf54271c726724a047f60d45762d650dc00439a10c37645b","blockSize":4194304,"blocks":["eb7f51a4a5a7f41baf54271c726724a047f60d45762d650dc00439a10c37645b"]},"offset":"2087554"},"lib":{"files":{"index.js":{"size":132,"integrity":{"algorithm":"SHA256","hash":"1401fdda105ed67f365bd775397aedb2f5f9e43ace031288f0f6868f9ab041be","blockSize":4194304,"blocks":["1401fdda105ed67f365bd775397aedb2f5f9e43ace031288f0f6868f9ab041be"]},"offset":"2087949"}}}}},"universalify":{"files":{"LICENSE":{"size":1100,"integrity":{"algorithm":"SHA256","hash":"3fda5977c0904e226190b4e21d64340c1731e2142d6fe5f3dee0090a216b8b63","blockSize":4194304,"blocks":["3fda5977c0904e226190b4e21d64340c1731e2142d6fe5f3dee0090a216b8b63"]},"offset":"2088081"},"index.js":{"size":777,"integrity":{"algorithm":"SHA256","hash":"d3411ff41b782d91b9cf61daf5a36fa9f2a0383da19be846aa4463f00226e929","blockSize":4194304,"blocks":["d3411ff41b782d91b9cf61daf5a36fa9f2a0383da19be846aa4463f00226e929"]},"offset":"2089181"},"package.json":{"size":617,"integrity":{"algorithm":"SHA256","hash":"039ab77eb273350d1dcec82dee33f474468767728aa53cc472a4ff227b361175","blockSize":4194304,"blocks":["039ab77eb273350d1dcec82dee33f474468767728aa53cc472a4ff227b361175"]},"offset":"2089958"}}}}}}}  {
  "name": "officeforger",
  "productName": "OfficeForger",
  "version": "1.0.0",
  "private": true,
  "description": "Documents, spreadsheets and presentations. Offline desktop office suite.",
  "author": "OfficeForger <echo4hunter@icloud.com>",
  "homepage": "https://office.crayoneaterdefense.com/",
  "main": "electron/main.cjs",
  "dependencies": {
    "electron-updater": "^6.3.9"
  }
}'use strict';
/*
 * OfficeForger — Electron shell.
 *
 * The renderer is a plain static app (app/index.html). Everything that a browser
 * cannot do lives here: real files on disk, native Open/Save dialogs, the recent
 * files list, printing to PDF, and auto-update.
 *
 * The document model is deliberately the renderer's business. This process never
 * looks inside a file — it reads bytes, writes bytes, and reports the path.
 */

const { app, BrowserWindow, dialog, ipcMain, Menu, shell, nativeTheme } = require('electron');
const path = require('path');
const fs = require('fs');
const fsp = require('fs/promises');
const { autoUpdater } = require('electron-updater');

// ---- File formats -----------------------------------------------------------
// One extension per document kind, so Explorer can show the right icon and
// double-click opens the right editor. JSON on the inside; ours on the outside.
const KINDS = {
  doc:   { ext: 'ofdoc',   label: 'OfficeForger Document' },
  sheet: { ext: 'ofsheet', label: 'OfficeForger Spreadsheet' },
  slide: { ext: 'ofslide', label: 'OfficeForger Presentation' },
};
const ALL_EXTS = Object.values(KINDS).map((k) => k.ext);

/** Filters for an Open dialog: everything by default, or one kind if asked. */
function openFilters(kind) {
  if (kind && KINDS[kind]) {
    return [
      { name: KINDS[kind].label, extensions: [KINDS[kind].ext] },
      { name: 'All Files', extensions: ['*'] },
    ];
  }
  return [
    { name: 'OfficeForger Files', extensions: ALL_EXTS },
    { name: KINDS.doc.label, extensions: [KINDS.doc.ext] },
    { name: KINDS.sheet.label, extensions: [KINDS.sheet.ext] },
    { name: KINDS.slide.label, extensions: [KINDS.slide.ext] },
    { name: 'All Files', extensions: ['*'] },
  ];
}

const RECENT_PATH = path.join(app.getPath('userData'), 'recent.json');
const PREFS_PATH = path.join(app.getPath('userData'), 'prefs.json');
const AUTOSAVE_DIR = path.join(app.getPath('userData'), 'autosave');

/** A file passed on the command line — double-clicking a document in Explorer. */
let pendingOpen = argFile(process.argv);
/** The renderer sets this whenever any open tab has unsaved work. */
let dirty = false;
let forceClose = false;
let mainWindow = null;

function argFile(argv) {
  const hit = argv
    .slice(1)
    .find((a) => ALL_EXTS.some((e) => a.toLowerCase().endsWith('.' + e)) && fs.existsSync(a));
  return hit || null;
}

// ---- Small JSON stores ------------------------------------------------------
function readJson(file, fallback) {
  try {
    return JSON.parse(fs.readFileSync(file, 'utf8'));
  } catch {
    return fallback;
  }
}
function writeJson(file, value) {
  try {
    fs.mkdirSync(path.dirname(file), { recursive: true });
    fs.writeFileSync(file, JSON.stringify(value, null, 2));
  } catch {
    /* a failed prefs write must never take the app down */
  }
}

function getRecent() {
  const list = readJson(RECENT_PATH, []);
  // Files get moved and deleted behind our back; never offer a dead path.
  return Array.isArray(list) ? list.filter((r) => r && r.path && fs.existsSync(r.path)) : [];
}
function addRecent(entry) {
  const list = getRecent().filter((r) => r.path !== entry.path);
  list.unshift({ path: entry.path, name: entry.name, kind: entry.kind, at: Date.now() });
  writeJson(RECENT_PATH, list.slice(0, 20));
  buildMenu();
  return getRecent();
}

// ---- Window -----------------------------------------------------------------
function createWindow() {
  const prefs = readJson(PREFS_PATH, {});
  const b = prefs.bounds || {};

  mainWindow = new BrowserWindow({
    width: b.width || 1440,
    height: b.height || 900,
    x: b.x,
    y: b.y,
    minWidth: 940,
    minHeight: 600,
    show: false,
    backgroundColor: '#f5f6f8',
    title: 'OfficeForger',
    webPreferences: {
      preload: path.join(__dirname, 'preload.cjs'),
      contextIsolation: true,
      nodeIntegration: false,
      spellcheck: true,
    },
  });

  if (prefs.maximized) mainWindow.maximize();
  mainWindow.loadFile(path.join(__dirname, '..', 'app', 'index.html'));

  mainWindow.once('ready-to-show', () => {
    mainWindow.show();
    if (pendingOpen) {
      openPathInRenderer(pendingOpen);
      pendingOpen = null;
    }
  });

  // Links to the outside world open in the real browser, never in the app frame.
  mainWindow.webContents.setWindowOpenHandler(({ url }) => {
    if (/^https?:/.test(url)) shell.openExternal(url);
    return { action: 'deny' };
  });

  // Unsaved work must not vanish because someone hit the X. Ask the renderer which
  // documents are dirty, and let the user decide.
  mainWindow.on('close', (e) => {
    const prefsNow = readJson(PREFS_PATH, {});
    prefsNow.maximized = mainWindow.isMaximized();
    if (!mainWindow.isMaximized()) prefsNow.bounds = mainWindow.getNormalBounds();
    writeJson(PREFS_PATH, prefsNow);

    if (dirty && !forceClose) {
      e.preventDefault();
      const choice = dialog.showMessageBoxSync(mainWindow, {
        type: 'warning',
        buttons: ['Save all and close', "Don't save", 'Cancel'],
        defaultId: 0,
        cancelId: 2,
        title: 'Unsaved changes',
        message: 'You have documents with unsaved changes.',
        detail: 'Save them before closing?',
      });
      if (choice === 2) return;
      if (choice === 0) {
        // Renderer saves everything, then calls back with app:force-close.
        mainWindow.webContents.send('menu', { command: 'save-all-and-close' });
        return;
      }
      forceClose = true;
      mainWindow.close();
    }
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

function openPathInRenderer(p) {
  if (mainWindow) mainWindow.webContents.send('open-file', p);
}

function send(command, arg) {
  if (mainWindow) mainWindow.webContents.send('menu', { command, arg });
}

// ---- Application menu -------------------------------------------------------
// Menu items are intentionally thin: they emit a command and the renderer, which
// is the only thing that knows what kind of document is in front, decides.
function buildMenu() {
  const recent = getRecent();
  const recentItems = recent.length
    ? recent.map((r) => ({
        label: r.name,
        click: () => openPathInRenderer(r.path),
      }))
    : [{ label: 'No recent files', enabled: false }];

  const template = [
    {
      label: '&File',
      submenu: [
        { label: 'New Document', accelerator: 'CmdOrCtrl+N', click: () => send('new-doc') },
        { label: 'New Spreadsheet', accelerator: 'CmdOrCtrl+Shift+N', click: () => send('new-sheet') },
        { label: 'New Presentation', accelerator: 'CmdOrCtrl+Alt+N', click: () => send('new-slide') },
        { type: 'separator' },
        { label: 'Open…', accelerator: 'CmdOrCtrl+O', click: () => send('open') },
        {
          label: 'Open Recent',
          submenu: [
            ...recentItems,
            { type: 'separator' },
            {
              label: 'Clear Recent',
              enabled: recent.length > 0,
              click: () => {
                writeJson(RECENT_PATH, []);
                buildMenu();
                send('recent-cleared');
              },
            },
          ],
        },
        { type: 'separator' },
        { label: 'Save', accelerator: 'CmdOrCtrl+S', click: () => send('save') },
        { label: 'Save As…', accelerator: 'CmdOrCtrl+Shift+S', click: () => send('save-as') },
        { label: 'Save All', click: () => send('save-all') },
        { type: 'separator' },
        {
          label: 'Import',
          submenu: [
            { label: 'CSV into new Spreadsheet…', click: () => send('import-csv') },
            { label: 'Text or HTML into new Document…', click: () => send('import-text') },
          ],
        },
        {
          label: 'Export',
          submenu: [
            { label: 'PDF…', accelerator: 'CmdOrCtrl+P', click: () => send('export-pdf') },
            { label: 'HTML…', click: () => send('export-html') },
            { label: 'CSV… (spreadsheet)', click: () => send('export-csv') },
            { label: 'Plain text… (document)', click: () => send('export-txt') },
          ],
        },
        { type: 'separator' },
        { label: 'Close Tab', accelerator: 'CmdOrCtrl+W', click: () => send('close-tab') },
        { role: 'quit', label: 'Exit' },
      ],
    },
    {
      label: '&Edit',
      submenu: [
        { role: 'undo' },
        { role: 'redo' },
        { type: 'separator' },
        { role: 'cut' },
        { role: 'copy' },
        { role: 'paste' },
        { label: 'Paste without formatting', accelerator: 'CmdOrCtrl+Shift+V', role: 'pasteAndMatchStyle' },
        { role: 'selectAll' },
        { type: 'separator' },
        { label: 'Find and Replace…', accelerator: 'CmdOrCtrl+F', click: () => send('find') },
      ],
    },
    {
      label: '&Insert',
      submenu: [
        { label: 'Image…', click: () => send('insert-image') },
        { label: 'Table…', click: () => send('insert-table') },
        { label: 'Link…', accelerator: 'CmdOrCtrl+K', click: () => send('insert-link') },
        { label: 'Chart… (spreadsheet)', click: () => send('insert-chart') },
        { type: 'separator' },
        { label: 'Page break (document)', click: () => send('insert-pagebreak') },
        { label: 'Slide (presentation)', accelerator: 'CmdOrCtrl+M', click: () => send('insert-slide') },
      ],
    },
    {
      label: '&View',
      submenu: [
        { label: 'Zoom In', accelerator: 'CmdOrCtrl+=', click: () => send('zoom-in') },
        { label: 'Zoom Out', accelerator: 'CmdOrCtrl+-', click: () => send('zoom-out') },
        { label: 'Reset Zoom', accelerator: 'CmdOrCtrl+0', click: () => send('zoom-reset') },
        { type: 'separator' },
        { label: 'Present (presentation)', accelerator: 'F5', click: () => send('present') },
        { type: 'separator' },
        { role: 'togglefullscreen' },
        { role: 'toggleDevTools' },
      ],
    },
    {
      label: '&Help',
      submenu: [
        { label: 'Keyboard shortcuts', click: () => send('shortcuts') },
        {
          label: 'Check for updates',
          click: () => {
            if (!app.isPackaged) {
              dialog.showMessageBox(mainWindow, {
                type: 'info',
                message: 'Updates are only checked in the installed app.',
              });
              return;
            }
            autoUpdater.checkForUpdatesAndNotify().catch((err) => {
              dialog.showMessageBox(mainWindow, {
                type: 'error',
                message: 'Could not check for updates',
                detail: String(err && err.message ? err.message : err),
              });
            });
          },
        },
        {
          label: 'About OfficeForger',
          click: () => {
            dialog.showMessageBox(mainWindow, {
              type: 'info',
              title: 'About OfficeForger',
              message: `OfficeForger ${app.getVersion()}`,
              detail:
                'Documents, spreadsheets and presentations.\n' +
                'Everything is stored as ordinary files on this machine — nothing is uploaded.',
            });
          },
        },
      ],
    },
  ];

  Menu.setApplicationMenu(Menu.buildFromTemplate(template));
}

// ---- IPC --------------------------------------------------------------------
ipcMain.handle('dialog:open', async (_e, { kind } = {}) => {
  const res = await dialog.showOpenDialog(mainWindow, {
    properties: ['openFile', 'multiSelections'],
    filters: openFilters(kind),
  });
  return res.canceled ? [] : res.filePaths;
});

ipcMain.handle('dialog:import', async (_e, { filters, title } = {}) => {
  const res = await dialog.showOpenDialog(mainWindow, {
    title: title || 'Import',
    properties: ['openFile'],
    filters: filters || [{ name: 'All Files', extensions: ['*'] }],
  });
  return res.canceled ? null : res.filePaths[0];
});

ipcMain.handle('dialog:save', async (_e, { defaultName, kind, filters } = {}) => {
  const res = await dialog.showSaveDialog(mainWindow, {
    defaultPath: defaultName,
    filters:
      filters ||
      (kind && KINDS[kind]
        ? [{ name: KINDS[kind].label, extensions: [KINDS[kind].ext] }, { name: 'All Files', extensions: ['*'] }]
        : openFilters()),
  });
  return res.canceled ? null : res.filePath;
});

ipcMain.handle('fs:read', async (_e, p) => {
  const data = await fsp.readFile(p, 'utf8');
  return { path: p, name: path.basename(p), data };
});

ipcMain.handle('fs:readBinary', async (_e, p) => {
  const buf = await fsp.readFile(p);
  return { path: p, name: path.basename(p), base64: buf.toString('base64') };
});

ipcMain.handle('fs:write', async (_e, { path: p, data }) => {
  // Write to a sibling temp file and rename. A crash mid-write then costs you
  // nothing — the original file is still intact on disk.
  const tmp = p + '.tmp-' + process.pid;
  await fsp.writeFile(tmp, data, 'utf8');
  await fsp.rename(tmp, p);
  return { path: p, name: path.basename(p) };
});

ipcMain.handle('fs:writeBinary', async (_e, { path: p, base64 }) => {
  const tmp = p + '.tmp-' + process.pid;
  await fsp.writeFile(tmp, Buffer.from(base64, 'base64'));
  await fsp.rename(tmp, p);
  return { path: p };
});

ipcMain.handle('fs:exists', async (_e, p) => fs.existsSync(p));

ipcMain.handle('recent:list', async () => getRecent());
ipcMain.handle('recent:add', async (_e, entry) => addRecent(entry));
ipcMain.handle('recent:clear', async () => {
  writeJson(RECENT_PATH, []);
  buildMenu();
  return [];
});

ipcMain.handle('prefs:get', async () => readJson(PREFS_PATH, {}));
ipcMain.handle('prefs:set', async (_e, patch) => {
  const prefs = Object.assign(readJson(PREFS_PATH, {}), patch || {});
  writeJson(PREFS_PATH, prefs);
  return prefs;
});

// Autosave: crash insurance for documents that have never been saved to a real
// path. Keyed by the renderer's tab id and cleared when the tab is saved/closed.
ipcMain.handle('autosave:put', async (_e, { id, payload }) => {
  await fsp.mkdir(AUTOSAVE_DIR, { recursive: true });
  await fsp.writeFile(path.join(AUTOSAVE_DIR, `${id}.json`), JSON.stringify(payload), 'utf8');
  return true;
});
ipcMain.handle('autosave:drop', async (_e, id) => {
  try {
    await fsp.unlink(path.join(AUTOSAVE_DIR, `${id}.json`));
  } catch {
    /* already gone */
  }
  return true;
});
ipcMain.handle('autosave:list', async () => {
  try {
    const names = await fsp.readdir(AUTOSAVE_DIR);
    const out = [];
    for (const n of names.filter((n) => n.endsWith('.json'))) {
      try {
        out.push(JSON.parse(await fsp.readFile(path.join(AUTOSAVE_DIR, n), 'utf8')));
      } catch {
        /* skip a corrupt crumb rather than fail the whole recovery */
      }
    }
    return out;
  } catch {
    return [];
  }
});

ipcMain.on('app:dirty', (_e, value) => {
  dirty = !!value;
});
ipcMain.on('app:title', (_e, value) => {
  if (mainWindow) mainWindow.setTitle(value ? `${value} — OfficeForger` : 'OfficeForger');
});
ipcMain.on('app:force-close', () => {
  forceClose = true;
  if (mainWindow) mainWindow.close();
});

ipcMain.handle('app:info', async () => ({
  version: app.getVersion(),
  platform: process.platform,
  packaged: app.isPackaged,
}));

ipcMain.handle('shell:openPath', async (_e, p) => shell.showItemInFolder(p));

// Printing. The renderer builds a print-ready HTML document and hands it over; we
// render it in an offscreen window so the app's own chrome never lands in the PDF.
ipcMain.handle('export:pdf', async (_e, { html, path: outPath, landscape, pageSize, margins }) => {
  const win = new BrowserWindow({
    show: false,
    webPreferences: { offscreen: true, contextIsolation: true, nodeIntegration: false },
  });
  try {
    await win.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(html));
    // Give webfonts and images a moment to settle before the snapshot.
    await new Promise((r) => setTimeout(r, 250));
    const buf = await win.webContents.printToPDF({
      landscape: !!landscape,
      pageSize: pageSize || 'Letter',
      printBackground: true,
      margins: margins || { marginType: 'default' },
    });
    await fsp.writeFile(outPath, buf);
    return { ok: true, path: outPath };
  } finally {
    win.destroy();
  }
});

ipcMain.handle('dialog:message', async (_e, opts) => {
  const res = await dialog.showMessageBox(mainWindow, opts || {});
  return res.response;
});

// ---- Lifecycle --------------------------------------------------------------
// One instance only. A second launch (double-clicking a file) hands its path to
// the window that is already open instead of starting a rival copy.
const gotLock = app.requestSingleInstanceLock();
if (!gotLock) {
  app.quit();
} else {
  app.on('second-instance', (_e, argv) => {
    const file = argFile(argv);
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore();
      mainWindow.focus();
      if (file) openPathInRenderer(file);
    }
  });

  app.on('open-file', (e, p) => {
    e.preventDefault();
    if (mainWindow) openPathInRenderer(p);
    else pendingOpen = p;
  });

  app.whenReady().then(() => {
    nativeTheme.themeSource = 'light';
    buildMenu();
    createWindow();

    if (app.isPackaged) {
      autoUpdater.autoDownload = true;
      autoUpdater.on('update-downloaded', (info) => {
        dialog
          .showMessageBox(mainWindow, {
            type: 'info',
            buttons: ['Restart now', 'Later'],
            defaultId: 0,
            cancelId: 1,
            title: 'Update ready',
            message: `OfficeForger ${info.version} is ready to install.`,
            detail: 'The app will restart to finish the update.',
          })
          .then(({ response }) => {
            if (response === 0) {
              forceClose = true;
              autoUpdater.quitAndInstall();
            }
          });
      });
      // A missing or unreachable feed must never surface as an error on launch.
      autoUpdater.checkForUpdates().catch(() => {});
    }

    app.on('activate', () => {
      if (BrowserWindow.getAllWindows().length === 0) createWindow();
    });
  });

  app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit();
  });
}
'use strict';
/*
 * The only bridge between the renderer and the machine. contextIsolation is on and
 * nodeIntegration is off, so this is the complete list of things the app can do
 * outside its own window — no fs, no child_process, no require in the renderer.
 */
const { contextBridge, ipcRenderer, webUtils } = require('electron');

contextBridge.exposeInMainWorld('forge', {
  // --- dialogs
  openDialog: (opts) => ipcRenderer.invoke('dialog:open', opts || {}),
  importDialog: (opts) => ipcRenderer.invoke('dialog:import', opts || {}),
  saveDialog: (opts) => ipcRenderer.invoke('dialog:save', opts || {}),
  message: (opts) => ipcRenderer.invoke('dialog:message', opts),

  // --- files
  read: (p) => ipcRenderer.invoke('fs:read', p),
  readBinary: (p) => ipcRenderer.invoke('fs:readBinary', p),
  write: (p, data) => ipcRenderer.invoke('fs:write', { path: p, data }),
  writeBinary: (p, base64) => ipcRenderer.invoke('fs:writeBinary', { path: p, base64 }),
  exists: (p) => ipcRenderer.invoke('fs:exists', p),
  revealInFolder: (p) => ipcRenderer.invoke('shell:openPath', p),

  // --- recent files
  recent: () => ipcRenderer.invoke('recent:list'),
  addRecent: (entry) => ipcRenderer.invoke('recent:add', entry),
  clearRecent: () => ipcRenderer.invoke('recent:clear'),

  // --- preferences
  getPrefs: () => ipcRenderer.invoke('prefs:get'),
  setPrefs: (patch) => ipcRenderer.invoke('prefs:set', patch),

  // --- crash insurance for never-saved documents
  autosavePut: (id, payload) => ipcRenderer.invoke('autosave:put', { id, payload }),
  autosaveDrop: (id) => ipcRenderer.invoke('autosave:drop', id),
  autosaveList: () => ipcRenderer.invoke('autosave:list'),

  // --- export
  exportPdf: (opts) => ipcRenderer.invoke('export:pdf', opts),

  // --- window state
  setDirty: (v) => ipcRenderer.send('app:dirty', v),
  setTitle: (v) => ipcRenderer.send('app:title', v),
  forceClose: () => ipcRenderer.send('app:force-close'),
  info: () => ipcRenderer.invoke('app:info'),

  // --- drag and drop
  // File.path is going away in newer Electron; webUtils is the replacement. Ask
  // for whichever this build actually has rather than assuming either.
  pathForFile: (file) => {
    try {
      if (webUtils && webUtils.getPathForFile) return webUtils.getPathForFile(file);
    } catch {
      /* fall through to File.path */
    }
    return file && file.path ? file.path : null;
  },

  // --- events from the menu / OS
  onMenu: (cb) => ipcRenderer.on('menu', (_e, payload) => cb(payload)),
  onOpenFile: (cb) => ipcRenderer.on('open-file', (_e, p) => cb(p)),
});
'use strict';
/*
 * OfficeForger — the application shell.
 *
 * Owns the open documents (tabs), all file I/O, the menu wiring and the start
 * screen. The three editors know nothing about files or tabs; they take data in,
 * hand data back, and tell the shell when something changed.
 */
(function (global) {
  const { el, toast, form, confirm, modal, escapeHtml, fileSize } = global.UI;
  const forge = global.forge;

  const EDITORS = {
    doc: global.DocEditor,
    sheet: global.SheetEditor,
    slide: global.SlideEditor,
  };
  const FILE_VERSION = 1;

  const tabs = [];
  let active = null;
  let seq = 0;
  let untitledCount = { doc: 0, sheet: 0, slide: 0 };

  const $ = (id) => document.getElementById(id);
  const workspace = $('workspace');
  const tabsEl = $('tabs');
  const startEl = $('start');

  // ---- tabs -----------------------------------------------------------------
  function newTab(kind, data, path, name) {
    const Editor = EDITORS[kind];
    if (!Editor) {
      toast('Unknown file type', 'err');
      return null;
    }
    const host = el('div', { class: 'editor-host inactive' });
    workspace.appendChild(host);

    const tab = {
      id: 'tab' + ++seq,
      kind,
      path: path || null,
      name: name || defaultName(kind),
      dirty: !path,
      host,
      editor: null,
    };

    tab.editor = new Editor(host, data, {
      onChange: () => markDirty(tab),
      onStatus: () => { if (tab === active) renderStatus(); },
      tab,
    });

    tabs.push(tab);
    setActive(tab);
    renderTabs();
    // A brand-new unsaved document gets crash insurance straight away.
    if (!path) scheduleAutosave(tab);
    return tab;
  }

  function defaultName(kind) {
    untitledCount[kind]++;
    const label = { doc: 'Untitled document', sheet: 'Untitled spreadsheet', slide: 'Untitled presentation' }[kind];
    return `${label} ${untitledCount[kind]}`;
  }

  function setActive(tab) {
    active = tab;
    for (const t of tabs) t.host.classList.toggle('inactive', t !== tab);
    startEl.classList.toggle('hidden', !!tab);
    renderTabs();
    renderStatus();
    updateTitle();
    if (tab) setTimeout(() => tab.editor.focus(), 0);
  }

  function renderTabs() {
    tabsEl.innerHTML = '';
    for (const t of tabs) {
      const Editor = EDITORS[t.kind];
      const node = el('div', {
        class: 'tab' + (t === active ? ' active' : ''),
        title: t.path || 'Not saved yet',
        onmousedown: (e) => { if (e.button === 0) setActive(t); },
        onauxclick: (e) => { if (e.button === 1) { e.preventDefault(); closeTab(t); } },
        oncontextmenu: (e) => {
          e.preventDefault();
          global.UI.menu(e.clientX, e.clientY, [
            { label: 'Save', hint: 'Ctrl+S', onClick: () => saveTab(t) },
            { label: 'Save as…', onClick: () => saveTab(t, true) },
            t.path ? { label: 'Show in folder', onClick: () => forge.revealInFolder(t.path) } : null,
            '-',
            { label: 'Close', hint: 'Ctrl+W', onClick: () => closeTab(t) },
            { label: 'Close others', onClick: () => [...tabs].filter((x) => x !== t).forEach(closeTab) },
          ].filter(Boolean));
        },
      }, [
        el('span', { class: 'tab-kind ' + t.kind, text: Editor.icon }),
        el('span', { class: 'tab-name', text: t.name }),
        t.dirty ? el('span', { class: 'tab-dot', text: '•', title: 'Unsaved changes' }) : null,
        el('button', {
          class: 'tab-close', text: '✕', title: 'Close (Ctrl+W)',
          onmousedown: (e) => e.stopPropagation(),
          onclick: (e) => { e.stopPropagation(); closeTab(t); },
        }),
      ]);
      tabsEl.appendChild(node);
    }
  }

  function markDirty(tab) {
    if (!tab.dirty) {
      tab.dirty = true;
      renderTabs();
      updateTitle();
    }
    forge.setDirty(tabs.some((t) => t.dirty));
    scheduleAutosave(tab);
  }

  function renderStatus() {
    if (!active) {
      $('statusLeft').textContent = '';
      $('statusRight').textContent = '';
      return;
    }
    const s = active.editor.status ? active.editor.status() : { left: '', right: '' };
    $('statusLeft').textContent = s.left || '';
    $('statusRight').textContent = (active.path ? '' : 'Not saved · ') + (s.right || '');
  }

  function updateTitle() {
    forge.setTitle(active ? (active.dirty ? '• ' : '') + active.name : '');
    forge.setDirty(tabs.some((t) => t.dirty));
  }

  async function closeTab(tab) {
    if (tab.dirty) {
      const choice = await forge.message({
        type: 'warning',
        buttons: ['Save', "Don't save", 'Cancel'],
        defaultId: 0,
        cancelId: 2,
        title: 'Unsaved changes',
        message: `Save changes to "${tab.name}"?`,
        detail: 'Your changes will be lost if you do not save them.',
      });
      if (choice === 2) return false;
      if (choice === 0) {
        const ok = await saveTab(tab);
        if (!ok) return false;
      }
    }
    forge.autosaveDrop(tab.id);
    if (tab.editor.destroy) tab.editor.destroy();
    tab.host.remove();
    const i = tabs.indexOf(tab);
    tabs.splice(i, 1);
    setActive(tabs[Math.min(i, tabs.length - 1)] || null);
    if (!tabs.length) refreshRecent();
    return true;
  }

  // ---- file I/O -------------------------------------------------------------
  function envelope(tab) {
    return JSON.stringify({
      app: 'OfficeForger',
      kind: tab.kind,
      version: FILE_VERSION,
      savedAt: new Date().toISOString(),
      data: tab.editor.serialize(),
    });
  }

  async function saveTab(tab, saveAs) {
    let path = tab.path;
    if (!path || saveAs) {
      const ext = EDITORS[tab.kind].ext;
      const suggestion = (tab.name.replace(/\.[^.]+$/, '') || 'Untitled') + '.' + ext;
      path = await forge.saveDialog({ defaultName: suggestion, kind: tab.kind });
      if (!path) return false;
      if (!path.toLowerCase().endsWith('.' + ext)) path += '.' + ext;
    }
    try {
      const payload = envelope(tab);
      const res = await forge.write(path, payload);
      tab.path = res.path;
      tab.name = res.name;
      tab.dirty = false;
      tab.lastSize = payload.length;
      forge.autosaveDrop(tab.id);
      await forge.addRecent({ path: tab.path, name: tab.name, kind: tab.kind });
      renderTabs();
      updateTitle();
      renderStatus();
      toast(`Saved ${tab.name}`);
      return true;
    } catch (err) {
      toast('Could not save: ' + (err && err.message ? err.message : err), 'err');
      return false;
    }
  }

  async function saveAll() {
    let ok = true;
    for (const t of tabs) {
      if (!t.dirty) continue;
      if (!(await saveTab(t))) ok = false;
    }
    return ok;
  }

  async function openPath(path) {
    const existing = tabs.find((t) => t.path === path);
    if (existing) { setActive(existing); return existing; }

    try {
      const file = await forge.read(path);
      let parsed;
      try {
        parsed = JSON.parse(file.data);
      } catch {
        toast(`${file.name} is not an OfficeForger file`, 'err');
        return null;
      }
      if (!parsed || parsed.app !== 'OfficeForger' || !EDITORS[parsed.kind]) {
        toast(`${file.name} is not an OfficeForger file`, 'err');
        return null;
      }
      if (parsed.version > FILE_VERSION) {
        const go = await confirm({
          title: 'Saved by a newer version',
          message: `${file.name} was written by a newer version of OfficeForger. Opening it may lose parts of the document. Continue?`,
          okLabel: 'Open anyway',
        });
        if (!go) return null;
      }
      const tab = newTab(parsed.kind, parsed.data, path, file.name);
      if (tab) {
        tab.dirty = false;
        tab.lastSize = file.data.length;
        renderTabs();
        updateTitle();
        renderStatus();
        await forge.addRecent({ path, name: file.name, kind: parsed.kind });
        refreshRecent();
      }
      return tab;
    } catch (err) {
      toast('Could not open: ' + (err && err.message ? err.message : err), 'err');
      return null;
    }
  }

  async function openDialog() {
    const paths = await forge.openDialog({});
    for (const p of paths) await openPath(p);
  }

  // ---- import / export ------------------------------------------------------
  async function importCsv() {
    const p = await forge.importDialog({
      title: 'Import CSV',
      filters: [{ name: 'CSV and text', extensions: ['csv', 'tsv', 'txt'] }, { name: 'All Files', extensions: ['*'] }],
    });
    if (!p) return;
    const file = await forge.read(p);
    const rows = p.toLowerCase().endsWith('.tsv')
      ? file.data.replace(/\r\n?/g, '\n').replace(/\n$/, '').split('\n').map((l) => l.split('\t'))
      : global.parseCSV(file.data);
    const tab = newTab('sheet', global.SheetEditor.fromRows(rows), null, file.name.replace(/\.[^.]+$/, ''));
    if (tab) toast(`Imported ${rows.length} rows`);
  }

  async function importText() {
    const p = await forge.importDialog({
      title: 'Import text or HTML',
      filters: [{ name: 'Text and HTML', extensions: ['txt', 'md', 'html', 'htm'] }, { name: 'All Files', extensions: ['*'] }],
    });
    if (!p) return;
    const file = await forge.read(p);
    const isHtml = /\.html?$/i.test(p);
    const content = isHtml
      ? global.sanitizeHtml(file.data)
      : file.data
          .split(/\n{2,}/)
          .map((para) => `<p>${escapeHtml(para).replace(/\n/g, '<br>')}</p>`)
          .join('');
    newTab('doc', { content: content || '<p><br></p>', zoom: 1 }, null, file.name.replace(/\.[^.]+$/, ''));
  }

  async function exportAs(what) {
    if (!active) { toast('Open a document first', 'err'); return; }
    const base = (active.name.replace(/\.[^.]+$/, '') || 'Untitled');

    if (what === 'pdf') {
      const path = await forge.saveDialog({
        defaultName: base + '.pdf',
        filters: [{ name: 'PDF', extensions: ['pdf'] }],
      });
      if (!path) return;
      try {
        const landscape = active.kind !== 'doc';
        await forge.exportPdf({
          html: active.editor.toPrintHTML(base),
          path,
          landscape,
          pageSize: active.kind === 'slide'
            ? { width: 9600, height: 5400 }   // microns: a 960x540 slide page
            : 'Letter',
          margins: active.kind === 'slide' ? { marginType: 'none' } : { marginType: 'default' },
        });
        toast('Exported PDF');
        forge.revealInFolder(path);
      } catch (err) {
        toast('PDF export failed: ' + (err && err.message ? err.message : err), 'err');
      }
      return;
    }

    if (what === 'html') {
      const path = await forge.saveDialog({
        defaultName: base + '.html',
        filters: [{ name: 'HTML', extensions: ['html'] }],
      });
      if (!path) return;
      await forge.write(path, active.editor.toPrintHTML(base));
      toast('Exported HTML');
      return;
    }

    if (what === 'csv') {
      if (active.kind !== 'sheet') { toast('CSV export is for spreadsheets', 'err'); return; }
      const path = await forge.saveDialog({
        defaultName: base + '.csv',
        filters: [{ name: 'CSV', extensions: ['csv'] }],
      });
      if (!path) return;
      await forge.write(path, active.editor.toCSV());
      toast('Exported CSV');
      return;
    }

    if (what === 'txt') {
      const path = await forge.saveDialog({
        defaultName: base + '.txt',
        filters: [{ name: 'Plain text', extensions: ['txt'] }],
      });
      if (!path) return;
      await forge.write(path, active.editor.toPlainText());
      toast('Exported text');
    }
  }

  // ---- autosave -------------------------------------------------------------
  // Only unsaved documents are shadowed. Anything with a real path is the user's
  // to save; second-guessing that would put surprise writes on their disk.
  const autosaveTimers = new Map();
  function scheduleAutosave(tab) {
    if (tab.path) return;
    clearTimeout(autosaveTimers.get(tab.id));
    autosaveTimers.set(tab.id, setTimeout(() => {
      try {
        forge.autosavePut(tab.id, {
          id: tab.id,
          kind: tab.kind,
          name: tab.name,
          at: Date.now(),
          data: tab.editor.serialize(),
        });
      } catch {
        /* autosave is best-effort; never interrupt the user over it */
      }
    }, 4000));
  }

  async function offerRecovery() {
    const crumbs = await forge.autosaveList();
    if (!crumbs || !crumbs.length) return;
    const ok = await confirm({
      title: `Recover ${crumbs.length} unsaved ${crumbs.length === 1 ? 'document' : 'documents'}?`,
      message: crumbs.map((c) => `• ${c.name}`).join('\n') +
        '\n\nThese were open but never saved to a file when OfficeForger last closed.',
      okLabel: 'Recover',
      cancelLabel: 'Discard',
    });
    for (const c of crumbs) {
      if (ok && EDITORS[c.kind]) newTab(c.kind, c.data, null, c.name);
      forge.autosaveDrop(c.id);
    }
  }

  // ---- start screen ---------------------------------------------------------
  async function refreshRecent() {
    const list = await forge.recent();
    const host = $('recentList');
    host.innerHTML = '';
    if (!list.length) {
      host.appendChild(el('li', { class: 'recent-empty', text: 'Nothing yet — create or open a file and it will show up here.' }));
      return;
    }
    for (const r of list) {
      const Editor = EDITORS[r.kind];
      host.appendChild(el('li', {
        onclick: () => openPath(r.path),
        oncontextmenu: (e) => {
          e.preventDefault();
          global.UI.menu(e.clientX, e.clientY, [
            { label: 'Open', onClick: () => openPath(r.path) },
            { label: 'Show in folder', onClick: () => forge.revealInFolder(r.path) },
          ]);
        },
      }, [
        el('span', { class: 'rk ' + r.kind, text: Editor ? Editor.icon : '▤' }),
        el('span', { class: 'rn', text: r.name }),
        el('span', { class: 'rp', text: r.path }),
      ]));
    }
  }

  // ---- shortcuts help -------------------------------------------------------
  function showShortcuts() {
    const rows = [
      ['grp', 'Files'],
      ['Ctrl+N', 'New document'],
      ['Ctrl+Shift+N', 'New spreadsheet'],
      ['Ctrl+Alt+N', 'New presentation'],
      ['Ctrl+O', 'Open'],
      ['Ctrl+S', 'Save'],
      ['Ctrl+Shift+S', 'Save as'],
      ['Ctrl+P', 'Export to PDF'],
      ['Ctrl+W', 'Close tab'],
      ['Ctrl+Tab', 'Next tab'],
      ['Ctrl+1…9', 'Jump to tab'],
      ['grp', 'Documents'],
      ['Ctrl+B / I / U', 'Bold, italic, underline'],
      ['Ctrl+K', 'Insert link'],
      ['Ctrl+F', 'Find and replace'],
      ['Ctrl+\\', 'Clear formatting'],
      ['Tab / Shift+Tab', 'Indent, or move between table cells'],
      ['Ctrl+= / Ctrl+-', 'Zoom in and out'],
      ['grp', 'Spreadsheets'],
      ['Enter / F2', 'Edit the current cell'],
      ['Ctrl+arrow', 'Jump to the edge of the data'],
      ['Shift+arrow', 'Extend the selection'],
      ['Ctrl+A', 'Select the whole sheet'],
      ['Ctrl+;', "Insert today's date"],
      ['Del', 'Clear the selected cells'],
      ['Drag the corner square', 'Fill down or across'],
      ['grp', 'Presentations'],
      ['F5', 'Present'],
      ['Ctrl+M', 'New slide'],
      ['Ctrl+D', 'Duplicate the selection'],
      ['Enter / double-click', 'Edit a text box'],
      ['Arrows / Shift+arrows', 'Nudge by 1 or 10 pixels'],
      ['Esc', 'Deselect, or exit presenting'],
    ];
    modal({
      title: 'Keyboard shortcuts',
      body: (host) => {
        const grid = el('div', { class: 'keys' });
        for (const [k, label] of rows) {
          if (k === 'grp') { grid.appendChild(el('div', { class: 'grp', text: label })); continue; }
          grid.appendChild(el('kbd', { text: k }));
          grid.appendChild(el('span', { text: label }));
        }
        host.appendChild(grid);
      },
      actions: [{ label: 'Close', primary: true, onClick: () => global.UI.closeModal() }],
    });
  }

  // ---- menu wiring ----------------------------------------------------------
  forge.onMenu(async ({ command }) => {
    switch (command) {
      case 'new-doc': newTab('doc', null); return;
      case 'new-sheet': newTab('sheet', null); return;
      case 'new-slide': newTab('slide', null); return;
      case 'open': openDialog(); return;
      case 'save': if (active) saveTab(active); return;
      case 'save-as': if (active) saveTab(active, true); return;
      case 'save-all': await saveAll(); return;
      case 'close-tab': if (active) closeTab(active); return;
      case 'import-csv': importCsv(); return;
      case 'import-text': importText(); return;
      case 'export-pdf': exportAs('pdf'); return;
      case 'export-html': exportAs('html'); return;
      case 'export-csv': exportAs('csv'); return;
      case 'export-txt': exportAs('txt'); return;
      case 'shortcuts': showShortcuts(); return;
      case 'recent-cleared': refreshRecent(); return;
      case 'save-all-and-close': {
        const ok = await saveAll();
        if (ok) forge.forceClose();
        return;
      }
      default:
        // Anything else belongs to whichever editor is in front.
        if (active && active.editor.command && active.editor.command(command)) return;
        if (['find', 'insert-image', 'insert-table', 'insert-link', 'insert-chart', 'insert-slide',
             'present', 'insert-pagebreak', 'zoom-in', 'zoom-out', 'zoom-reset'].includes(command)) {
          toast(active ? 'Not available for this kind of file' : 'Open a document first');
        }
    }
  });

  forge.onOpenFile((p) => openPath(p));

  // ---- global keys ----------------------------------------------------------
  document.addEventListener('keydown', (e) => {
    if (!(e.ctrlKey || e.metaKey)) return;
    if (e.key === 'Tab') {
      e.preventDefault();
      if (tabs.length < 2) return;
      const i = tabs.indexOf(active);
      setActive(tabs[(i + (e.shiftKey ? -1 : 1) + tabs.length) % tabs.length]);
      return;
    }
    if (/^[1-9]$/.test(e.key) && !e.shiftKey && !e.altKey) {
      const t = tabs[parseInt(e.key, 10) - 1];
      if (t) { e.preventDefault(); setActive(t); }
    }
  }, true);

  // ---- drag and drop --------------------------------------------------------
  let veil = null;
  window.addEventListener('dragover', (e) => {
    if (!e.dataTransfer || !Array.from(e.dataTransfer.types).includes('Files')) return;
    e.preventDefault();
    if (!veil) {
      veil = el('div', { class: 'drop-veil', text: 'Drop to open' });
      document.body.appendChild(veil);
    }
  });
  window.addEventListener('dragleave', (e) => {
    if (e.clientX === 0 && e.clientY === 0 && veil) { veil.remove(); veil = null; }
  });
  window.addEventListener('drop', async (e) => {
    e.preventDefault();
    if (veil) { veil.remove(); veil = null; }
    const files = Array.from((e.dataTransfer && e.dataTransfer.files) || []);
    for (const f of files) {
      const path = global.forgePathOf(f);
      if (!path) continue;
      if (/\.(ofdoc|ofsheet|ofslide)$/i.test(path)) await openPath(path);
      else if (/\.(csv|tsv)$/i.test(path)) {
        const file = await forge.read(path);
        const rows = /\.tsv$/i.test(path)
          ? file.data.replace(/\r\n?/g, '\n').replace(/\n$/, '').split('\n').map((l) => l.split('\t'))
          : global.parseCSV(file.data);
        newTab('sheet', global.SheetEditor.fromRows(rows), null, file.name.replace(/\.[^.]+$/, ''));
      } else if (/\.(txt|md|html?)$/i.test(path)) {
        const file = await forge.read(path);
        const content = /\.html?$/i.test(path)
          ? global.sanitizeHtml(file.data)
          : file.data.split(/\n{2,}/).map((p) => `<p>${escapeHtml(p).replace(/\n/g, '<br>')}</p>`).join('');
        newTab('doc', { content, zoom: 1 }, null, file.name.replace(/\.[^.]+$/, ''));
      } else {
        toast(`${path.split(/[\\/]/).pop()} is not a file OfficeForger can open`, 'err');
      }
    }
  });

  // The real filesystem path of a dropped file comes from the preload bridge.
  global.forgePathOf = (file) => (forge.pathForFile && forge.pathForFile(file)) || file.path || null;

  // ---- start screen buttons -------------------------------------------------
  for (const card of document.querySelectorAll('[data-new]')) {
    card.addEventListener('click', () => newTab(card.dataset.new, null));
  }
  $('openBtn').addEventListener('click', openDialog);
  $('newTabBtn').addEventListener('click', (e) => {
    global.UI.menu(e.clientX, e.clientY + 10, [
      { label: 'New document', hint: 'Ctrl+N', onClick: () => newTab('doc', null) },
      { label: 'New spreadsheet', hint: 'Ctrl+Shift+N', onClick: () => newTab('sheet', null) },
      { label: 'New presentation', hint: 'Ctrl+Alt+N', onClick: () => newTab('slide', null) },
      '-',
      { label: 'Open…', hint: 'Ctrl+O', onClick: openDialog },
    ]);
  });
  $('homeBtn').addEventListener('click', () => setActive(null));
  $('clearRecentBtn').addEventListener('click', async () => {
    await forge.clearRecent();
    refreshRecent();
  });

  // ---- boot -----------------------------------------------------------------
  (async function boot() {
    const info = await forge.info();
    $('versionLabel').textContent =
      `Version ${info.version} · files are saved as .ofdoc, .ofsheet and .ofslide on this computer`;
    await refreshRecent();
    await offerRecovery();
    setActive(tabs.length ? tabs[tabs.length - 1] : null);
  })();

  // Expose a little of the shell for the menu handler and for debugging.
  global.OfficeForger = { tabs: () => tabs, active: () => active, openPath, newTab, saveTab };
})(window);
'use strict';
/*
 * OfficeForger — the word processor.
 *
 * A contenteditable page driven by document.execCommand. execCommand is formally
 * deprecated, but in a fixed Chromium it is still by far the most reliable way to
 * do rich-text editing: it gets undo, selection repair and list semantics right,
 * and hand-rolling those is a year of work with worse results.
 */
(function (global) {
  const { el, tbtn, sep, spacer, toast, form, confirm, swatchButton, escapeHtml, ICONS } = global.UI;

  const FONTS = [
    'Georgia', 'Times New Roman', 'Garamond', 'Book Antiqua',
    'Arial', 'Helvetica', 'Verdana', 'Tahoma', 'Trebuchet MS', 'Calibri', 'Segoe UI',
    'Courier New', 'Consolas', 'Comic Sans MS', 'Impact',
  ];
  const SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 40, 48, 60, 72];
  // execCommand's fontSize only understands 1-7, so sizes go on as inline CSS.
  const BLOCKS = [
    { value: 'p', label: 'Normal text' },
    { value: 'h1', label: 'Title' },
    { value: 'h2', label: 'Heading 1' },
    { value: 'h3', label: 'Heading 2' },
    { value: 'h4', label: 'Heading 3' },
    { value: 'blockquote', label: 'Quote' },
    { value: 'pre', label: 'Code block' },
  ];

  class DocEditor {
    static get kind() { return 'doc'; }
    static get ext() { return 'ofdoc'; }
    static get label() { return 'Document'; }
    static get icon() { return '▤'; }

    static newData() {
      return {
        content: '<h1>Untitled document</h1><p><br></p>',
        zoom: 1,
        pageSize: 'Letter',
      };
    }

    constructor(host, data, ctx) {
      this.host = host;
      this.ctx = ctx;
      this.data = Object.assign(DocEditor.newData(), data || {});
      this.zoom = this.data.zoom || 1;
      this.find = { term: '', matches: [], index: -1, matchCase: false };
      this.build();
    }

    // ---- construction -------------------------------------------------------
    build() {
      this.host.appendChild(this.buildToolbar());

      this.scroll = el('div', { class: 'doc-scroll' });
      this.zoomWrap = el('div', { class: 'doc-zoom' });
      this.page = el('div', {
        class: 'page',
        contenteditable: 'true',
        spellcheck: 'true',
        role: 'textbox',
      });
      this.page.innerHTML = this.data.content || '<p><br></p>';

      this.zoomWrap.appendChild(this.page);
      this.scroll.appendChild(this.zoomWrap);
      this.host.appendChild(this.scroll);
      this.applyZoom();

      // execCommand should emit <span style> rather than <font>, so exported HTML
      // and printed output stay sane.
      document.execCommand('styleWithCSS', false, true);
      document.execCommand('defaultParagraphSeparator', false, 'p');

      const changed = () => {
        this.data.content = this.page.innerHTML;
        this.ctx.onChange();
        this.refreshStatus();
      };
      this.page.addEventListener('input', changed);
      this.page.addEventListener('keyup', () => this.syncToolbar());
      this.page.addEventListener('mouseup', () => this.syncToolbar());
      this.page.addEventListener('focus', () => this.syncToolbar());

      this.page.addEventListener('keydown', (e) => this.onKeyDown(e));
      this.page.addEventListener('paste', (e) => this.onPaste(e));

      // Ctrl-click a link to follow it; a plain click keeps editing, as in Word.
      this.page.addEventListener('click', (e) => {
        const a = e.target.closest && e.target.closest('a');
        if (a && (e.ctrlKey || e.metaKey) && a.href) {
          e.preventDefault();
          window.open(a.href, '_blank');
        }
      });

      this.refreshStatus();
    }

    buildToolbar() {
      const bar = el('div', { class: 'toolbar' });
      const cmd = (name, arg) => () => {
        this.page.focus();
        document.execCommand(name, false, arg);
        this.afterCommand();
      };

      bar.appendChild(tbtn({ html: ICONS.undo, title: 'Undo (Ctrl+Z)', onClick: cmd('undo') }));
      bar.appendChild(tbtn({ html: ICONS.redo, title: 'Redo (Ctrl+Y)', onClick: cmd('redo') }));
      bar.appendChild(sep());

      this.blockSel = el('select', {
        class: 'tsel w-style',
        title: 'Paragraph style',
        onchange: (e) => {
          this.page.focus();
          document.execCommand('formatBlock', false, e.target.value);
          this.afterCommand();
        },
      }, BLOCKS.map((b) => el('option', { value: b.value, text: b.label })));
      bar.appendChild(this.blockSel);

      this.fontSel = el('select', {
        class: 'tsel w-font',
        title: 'Font',
        onchange: (e) => {
          this.page.focus();
          document.execCommand('fontName', false, e.target.value);
          this.afterCommand();
        },
      }, FONTS.map((f) => el('option', { value: f, text: f })));
      bar.appendChild(this.fontSel);

      this.sizeSel = el('select', {
        class: 'tsel w-size',
        title: 'Font size',
        onchange: (e) => this.setFontSize(parseInt(e.target.value, 10)),
      }, SIZES.map((s) => el('option', { value: s, text: s })));
      this.sizeSel.value = '11';
      bar.appendChild(this.sizeSel);
      bar.appendChild(sep());

      this.btnBold = tbtn({ html: '<b>B</b>', title: 'Bold (Ctrl+B)', onClick: cmd('bold') });
      this.btnItalic = tbtn({ html: '<i>I</i>', title: 'Italic (Ctrl+I)', onClick: cmd('italic') });
      this.btnUnderline = tbtn({ html: '<u>U</u>', title: 'Underline (Ctrl+U)', onClick: cmd('underline') });
      this.btnStrike = tbtn({ html: '<s>S</s>', title: 'Strikethrough', onClick: cmd('strikeThrough') });
      bar.append(this.btnBold, this.btnItalic, this.btnUnderline, this.btnStrike);

      this.fgSwatch = swatchButton({
        icon: 'A', title: 'Text colour', color: '#000000',
        onPick: (c) => { this.page.focus(); document.execCommand('foreColor', false, c || '#000000'); this.afterCommand(); },
      });
      this.bgSwatch = swatchButton({
        icon: '▮', title: 'Highlight', color: '#ffff00', allowNone: true, noneLabel: 'No highlight',
        onPick: (c) => {
          this.page.focus();
          document.execCommand('hiliteColor', false, c || 'transparent');
          this.afterCommand();
        },
      });
      bar.append(this.fgSwatch, this.bgSwatch);
      bar.appendChild(sep());

      this.btnAlignL = tbtn({ html: ICONS.alignLeft, title: 'Align left', onClick: cmd('justifyLeft') });
      this.btnAlignC = tbtn({ html: ICONS.alignCenter, title: 'Centre', onClick: cmd('justifyCenter') });
      this.btnAlignR = tbtn({ html: ICONS.alignRight, title: 'Align right', onClick: cmd('justifyRight') });
      this.btnAlignJ = tbtn({ html: ICONS.justify, title: 'Justify', onClick: cmd('justifyFull') });
      bar.append(this.btnAlignL, this.btnAlignC, this.btnAlignR, this.btnAlignJ);
      bar.appendChild(sep());

      this.btnUL = tbtn({ html: ICONS.bulletList, title: 'Bulleted list', onClick: cmd('insertUnorderedList') });
      this.btnOL = tbtn({ html: ICONS.numberList, title: 'Numbered list', onClick: cmd('insertOrderedList') });
      bar.append(this.btnUL, this.btnOL);
      bar.appendChild(tbtn({ html: ICONS.indent, title: 'Increase indent', onClick: cmd('indent') }));
      bar.appendChild(tbtn({ html: ICONS.outdent, title: 'Decrease indent', onClick: cmd('outdent') }));
      bar.appendChild(sep());

      bar.appendChild(tbtn({ html: ICONS.link, title: 'Insert link (Ctrl+K)', onClick: () => this.insertLink() }));
      bar.appendChild(tbtn({ html: ICONS.image, title: 'Insert image', onClick: () => this.insertImage() }));
      bar.appendChild(tbtn({ html: ICONS.table, title: 'Insert table', onClick: () => this.insertTable() }));
      bar.appendChild(tbtn({ html: ICONS.rule, title: 'Horizontal rule', onClick: cmd('insertHorizontalRule') }));
      bar.appendChild(tbtn({ html: ICONS.pageBreak, title: 'Page break', onClick: () => this.insertPageBreak() }));
      bar.appendChild(sep());
      bar.appendChild(tbtn({ html: ICONS.clearFormat, title: 'Clear formatting (Ctrl+\\)', onClick: () => this.clearFormatting() }));

      bar.appendChild(spacer());
      bar.appendChild(tbtn({ html: ICONS.find, title: 'Find and replace (Ctrl+F)', onClick: () => this.openFind() }));
      return bar;
    }

    // ---- commands -----------------------------------------------------------
    afterCommand() {
      this.data.content = this.page.innerHTML;
      this.ctx.onChange();
      this.syncToolbar();
      this.refreshStatus();
    }

    setFontSize(pt) {
      this.page.focus();
      const sel = window.getSelection();
      if (!sel.rangeCount) return;
      if (sel.isCollapsed) {
        // Nothing selected: set the size for whatever gets typed next.
        document.execCommand('fontSize', false, 7);
        this.page.querySelectorAll('font[size="7"]').forEach((f) => {
          const span = document.createElement('span');
          span.style.fontSize = pt + 'pt';
          span.innerHTML = f.innerHTML || '​';
          f.replaceWith(span);
        });
      } else {
        // execCommand has no point-size mode; tag the run, then rewrite the tag.
        document.execCommand('fontSize', false, 7);
        this.page.querySelectorAll('font[size="7"]').forEach((f) => {
          const span = document.createElement('span');
          span.style.fontSize = pt + 'pt';
          while (f.firstChild) span.appendChild(f.firstChild);
          f.replaceWith(span);
        });
      }
      this.afterCommand();
    }

    clearFormatting() {
      this.page.focus();
      document.execCommand('removeFormat');
      document.execCommand('formatBlock', false, 'p');
      this.afterCommand();
    }

    async insertLink() {
      const sel = window.getSelection();
      const selected = sel && !sel.isCollapsed ? sel.toString() : '';
      const savedRange = sel && sel.rangeCount ? sel.getRangeAt(0).cloneRange() : null;

      const v = await form({
        title: 'Insert link',
        fields: [
          { name: 'text', label: 'Text to display', value: selected },
          { name: 'url', label: 'Link', placeholder: 'https://example.com', value: '' },
        ],
        okLabel: 'Insert',
      });
      if (!v || !v.url) return;

      let url = v.url.trim();
      if (!/^([a-z][a-z0-9+.-]*:|#|\/)/i.test(url)) url = 'https://' + url;

      this.page.focus();
      if (savedRange) {
        const s = window.getSelection();
        s.removeAllRanges();
        s.addRange(savedRange);
      }
      const text = (v.text || url).trim();
      if (selected && text === selected) {
        document.execCommand('createLink', false, url);
      } else {
        document.execCommand('insertHTML', false, `<a href="${escapeHtml(url)}">${escapeHtml(text)}</a>`);
      }
      this.afterCommand();
    }

    async insertImage() {
      const p = await window.forge.importDialog({
        title: 'Insert image',
        filters: [{ name: 'Images', extensions: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg'] }],
      });
      if (!p) return;
      const file = await window.forge.readBinary(p);
      const ext = p.split('.').pop().toLowerCase();
      const mime = ext === 'svg' ? 'image/svg+xml' : ext === 'jpg' ? 'image/jpeg' : 'image/' + ext;
      this.page.focus();
      // Images are embedded, not linked: the .ofdoc stays a single portable file.
      document.execCommand('insertHTML', false,
        `<img src="data:${mime};base64,${file.base64}" alt="${escapeHtml(file.name)}" />`);
      this.afterCommand();
    }

    async insertTable() {
      const v = await form({
        title: 'Insert table',
        fields: [
          { name: 'rows', label: 'Rows', type: 'number', value: 3, min: 1, max: 60 },
          { name: 'cols', label: 'Columns', type: 'number', value: 3, min: 1, max: 20 },
          { name: 'header', label: 'First row is a header', type: 'checkbox', value: true },
        ],
        okLabel: 'Insert',
      });
      if (!v) return;
      const rows = Math.max(1, Math.min(60, parseInt(v.rows, 10) || 3));
      const cols = Math.max(1, Math.min(20, parseInt(v.cols, 10) || 3));
      let html = '<table>';
      for (let r = 0; r < rows; r++) {
        html += '<tr>';
        for (let c = 0; c < cols; c++) {
          html += v.header && r === 0 ? '<th><br></th>' : '<td><br></td>';
        }
        html += '</tr>';
      }
      html += '</table><p><br></p>';
      this.page.focus();
      document.execCommand('insertHTML', false, html);
      this.afterCommand();
    }

    insertPageBreak() {
      this.page.focus();
      document.execCommand('insertHTML', false, '<div class="pagebreak" contenteditable="false"></div><p><br></p>');
      this.afterCommand();
    }

    // ---- keyboard -----------------------------------------------------------
    onKeyDown(e) {
      // Tab indents rather than leaving the editor. Inside a table it moves cells.
      if (e.key === 'Tab') {
        const cell = this.selectionCell();
        if (cell) {
          e.preventDefault();
          this.moveTableCell(cell, e.shiftKey ? -1 : 1);
          return;
        }
        e.preventDefault();
        document.execCommand(e.shiftKey ? 'outdent' : 'indent');
        this.afterCommand();
        return;
      }
      if ((e.ctrlKey || e.metaKey) && !e.altKey) {
        const k = e.key.toLowerCase();
        if (k === 'k') { e.preventDefault(); this.insertLink(); return; }
        if (k === 'f') { e.preventDefault(); this.openFind(); return; }
        if (k === '\\') { e.preventDefault(); this.clearFormatting(); return; }
      }
      if (e.key === 'Escape' && this.findBar) { this.closeFind(); }
    }

    selectionCell() {
      const sel = window.getSelection();
      if (!sel.rangeCount) return null;
      let n = sel.getRangeAt(0).startContainer;
      if (n.nodeType === 3) n = n.parentElement;
      return n && n.closest ? n.closest('td, th') : null;
    }

    moveTableCell(cell, dir) {
      const table = cell.closest('table');
      const cells = Array.from(table.querySelectorAll('td, th'));
      const i = cells.indexOf(cell);
      let next = cells[i + dir];
      if (!next && dir > 0) {
        // Tab out of the last cell appends a row, which is what people expect.
        const row = table.rows[table.rows.length - 1];
        const fresh = table.insertRow();
        for (let c = 0; c < row.cells.length; c++) fresh.insertCell().innerHTML = '<br>';
        next = fresh.cells[0];
        this.afterCommand();
      }
      if (!next) return;
      const range = document.createRange();
      range.selectNodeContents(next);
      range.collapse(true);
      const sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(range);
    }

    onPaste(e) {
      const cd = e.clipboardData;
      if (!cd) return;

      // An image on the clipboard becomes an embedded image.
      const item = Array.from(cd.items || []).find((i) => i.type.startsWith('image/'));
      if (item) {
        e.preventDefault();
        const blob = item.getAsFile();
        const reader = new FileReader();
        reader.onload = () => {
          document.execCommand('insertHTML', false, `<img src="${reader.result}" />`);
          this.afterCommand();
        };
        reader.readAsDataURL(blob);
        return;
      }

      // HTML from a browser arrives full of classes, scripts and absolute styles.
      // Keep the formatting that means something and drop the rest.
      const html = cd.getData('text/html');
      if (html) {
        e.preventDefault();
        document.execCommand('insertHTML', false, sanitizeHtml(html));
        this.afterCommand();
      }
    }

    // ---- find & replace -----------------------------------------------------
    openFind() {
      if (this.findBar) {
        this.findInput.focus();
        this.findInput.select();
        return;
      }
      const input = el('input', {
        class: 'tinput', placeholder: 'Find', value: this.find.term,
        oninput: () => this.runFind(input.value),
        onkeydown: (e) => {
          if (e.key === 'Enter') { e.preventDefault(); this.stepFind(e.shiftKey ? -1 : 1); }
          if (e.key === 'Escape') { e.preventDefault(); this.closeFind(); }
        },
      });
      const replaceInput = el('input', { class: 'tinput', placeholder: 'Replace with', style: { width: '150px' } });
      const count = el('span', { class: 'count', text: '0 / 0' });

      this.findInput = input;
      this.findCount = count;
      this.findBar = el('div', { class: 'findbar' }, [
        input,
        count,
        tbtn({ html: '&#8593;', title: 'Previous (Shift+Enter)', onClick: () => this.stepFind(-1) }),
        tbtn({ html: '&#8595;', title: 'Next (Enter)', onClick: () => this.stepFind(1) }),
        sep(),
        replaceInput,
        tbtn({ html: 'Replace', wide: true, onClick: () => this.replaceOne(replaceInput.value) }),
        tbtn({ html: 'All', wide: true, onClick: () => this.replaceAll(replaceInput.value) }),
        tbtn({ html: 'Aa', title: 'Match case', class: this.find.matchCase ? 'on' : '', onClick: (e) => {
          this.find.matchCase = !this.find.matchCase;
          e.currentTarget.classList.toggle('on', this.find.matchCase);
          this.runFind(input.value);
        } }),
        sep(),
        tbtn({ html: '✕', title: 'Close (Esc)', onClick: () => this.closeFind() }),
      ]);
      this.scroll.appendChild(this.findBar);
      input.focus();
      input.select();
      if (input.value) this.runFind(input.value);
    }

    closeFind() {
      if (!this.findBar) return;
      this.findBar.remove();
      this.findBar = null;
      this.clearHighlights();
      this.page.focus();
    }

    clearHighlights() {
      if (global.CSS && CSS.highlights) {
        CSS.highlights.delete('forge-find');
        CSS.highlights.delete('forge-find-active');
      }
      this.find.matches = [];
      this.find.index = -1;
    }

    /** Every text node in the page, in document order, with its running offset. */
    textNodes() {
      const walker = document.createTreeWalker(this.page, NodeFilter.SHOW_TEXT, {
        acceptNode: (n) =>
          n.nodeValue && n.nodeValue.length ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT,
      });
      const nodes = [];
      let offset = 0;
      let n;
      while ((n = walker.nextNode())) {
        nodes.push({ node: n, start: offset, end: offset + n.nodeValue.length });
        offset += n.nodeValue.length;
      }
      return nodes;
    }

    runFind(term) {
      this.find.term = term;
      this.clearHighlights();
      if (!term) {
        if (this.findCount) this.findCount.textContent = '0 / 0';
        return;
      }
      const nodes = this.textNodes();
      const haystack = nodes.map((n) => n.node.nodeValue).join('');
      const hay = this.find.matchCase ? haystack : haystack.toLowerCase();
      const needle = this.find.matchCase ? term : term.toLowerCase();

      const ranges = [];
      let at = 0;
      while (needle && (at = hay.indexOf(needle, at)) !== -1) {
        const range = rangeForSpan(nodes, at, at + needle.length);
        if (range) ranges.push(range);
        at += needle.length;
      }
      this.find.matches = ranges;
      this.find.index = ranges.length ? 0 : -1;
      this.paintFind();
    }

    paintFind() {
      if (!(global.CSS && CSS.highlights && global.Highlight)) return;
      const { matches, index } = this.find;
      const others = matches.filter((_, i) => i !== index);
      if (others.length) CSS.highlights.set('forge-find', new Highlight(...others));
      else CSS.highlights.delete('forge-find');
      if (index >= 0 && matches[index]) {
        CSS.highlights.set('forge-find-active', new Highlight(matches[index]));
        const rect = matches[index].getBoundingClientRect();
        const box = this.scroll.getBoundingClientRect();
        if (rect.top < box.top + 40 || rect.bottom > box.bottom - 40) {
          this.scroll.scrollTop += rect.top - box.top - box.height / 2;
        }
      } else {
        CSS.highlights.delete('forge-find-active');
      }
      if (this.findCount) {
        this.findCount.textContent = `${matches.length ? index + 1 : 0} / ${matches.length}`;
      }
    }

    stepFind(dir) {
      if (!this.find.matches.length) return;
      this.find.index = (this.find.index + dir + this.find.matches.length) % this.find.matches.length;
      this.paintFind();
    }

    replaceOne(replacement) {
      const { matches, index } = this.find;
      if (index < 0 || !matches[index]) return;
      const range = matches[index];
      range.deleteContents();
      if (replacement) range.insertNode(document.createTextNode(replacement));
      this.afterCommand();
      // The DOM moved under the ranges, so recompute rather than patch them.
      this.runFind(this.find.term);
      if (this.find.matches.length) {
        this.find.index = Math.min(index, this.find.matches.length - 1);
        this.paintFind();
      }
    }

    replaceAll(replacement) {
      if (!this.find.term || !this.find.matches.length) return;
      const n = this.find.matches.length;
      // Back to front: replacing early text would invalidate the later ranges.
      for (let i = this.find.matches.length - 1; i >= 0; i--) {
        const r = this.find.matches[i];
        r.deleteContents();
        if (replacement) r.insertNode(document.createTextNode(replacement));
      }
      this.afterCommand();
      this.runFind(this.find.term);
      toast(`Replaced ${n} ${n === 1 ? 'match' : 'matches'}`);
    }

    // ---- toolbar state ------------------------------------------------------
    syncToolbar() {
      if (!document.activeElement || !this.page.contains(document.activeElement)) {
        // Selection may still be inside the page even when focus has moved to a
        // toolbar control, so keep going — only bail if there is no selection.
        const s = window.getSelection();
        if (!s || !s.rangeCount || !this.page.contains(s.anchorNode)) return;
      }
      const on = (name) => {
        try { return document.queryCommandState(name); } catch { return false; }
      };
      this.btnBold.classList.toggle('on', on('bold'));
      this.btnItalic.classList.toggle('on', on('italic'));
      this.btnUnderline.classList.toggle('on', on('underline'));
      this.btnStrike.classList.toggle('on', on('strikeThrough'));
      this.btnAlignL.classList.toggle('on', on('justifyLeft'));
      this.btnAlignC.classList.toggle('on', on('justifyCenter'));
      this.btnAlignR.classList.toggle('on', on('justifyRight'));
      this.btnAlignJ.classList.toggle('on', on('justifyFull'));
      this.btnUL.classList.toggle('on', on('insertUnorderedList'));
      this.btnOL.classList.toggle('on', on('insertOrderedList'));

      const sel = window.getSelection();
      let node = sel && sel.anchorNode;
      if (node && node.nodeType === 3) node = node.parentElement;
      if (node && this.page.contains(node)) {
        const block = node.closest('h1,h2,h3,h4,blockquote,pre,p,li,td,th,div');
        if (block) {
          const tag = block.tagName.toLowerCase();
          const known = BLOCKS.find((b) => b.value === tag);
          this.blockSel.value = known ? tag : 'p';
        }
        const cs = getComputedStyle(node);
        const family = cs.fontFamily.split(',')[0].replace(/["']/g, '').trim();
        const match = FONTS.find((f) => f.toLowerCase() === family.toLowerCase());
        if (match) this.fontSel.value = match;
        const pt = Math.round((parseFloat(cs.fontSize) || 14.66) * 0.75);
        const nearest = SIZES.reduce((a, b) => (Math.abs(b - pt) < Math.abs(a - pt) ? b : a), SIZES[0]);
        this.sizeSel.value = String(nearest);
      }
    }

    // ---- zoom ---------------------------------------------------------------
    applyZoom() {
      this.zoomWrap.style.transform = `scale(${this.zoom})`;
      // A scaled element still reserves its unscaled height, leaving a gap under
      // the page; pull the wrapper's own height back in line with what is drawn.
      this.zoomWrap.style.height = this.zoom < 1 ? `${this.zoomWrap.scrollHeight * this.zoom}px` : '';
      this.data.zoom = this.zoom;
      this.refreshStatus();
    }
    setZoom(z) {
      this.zoom = Math.max(0.5, Math.min(2.5, Math.round(z * 20) / 20));
      this.applyZoom();
      this.ctx.onChange();
    }

    // ---- status bar ---------------------------------------------------------
    counts() {
      const text = this.page.innerText || '';
      const words = text.trim() ? text.trim().split(/\s+/).length : 0;
      return { words, chars: text.length, paras: this.page.querySelectorAll('p, h1, h2, h3, h4, li').length };
    }
    refreshStatus() { this.ctx.onStatus && this.ctx.onStatus(); }
    status() {
      const c = this.counts();
      return {
        left: `${c.words} words · ${c.chars} characters`,
        right: `Document · ${Math.round(this.zoom * 100)}%`,
      };
    }

    // ---- shell interface ----------------------------------------------------
    focus() {
      this.page.focus();
      this.syncToolbar();
    }

    serialize() {
      this.data.content = this.page.innerHTML;
      this.data.zoom = this.zoom;
      return this.data;
    }

    /** Menu commands the shell forwards. Returns true when handled. */
    command(name) {
      switch (name) {
        case 'find': this.openFind(); return true;
        case 'insert-image': this.insertImage(); return true;
        case 'insert-table': this.insertTable(); return true;
        case 'insert-link': this.insertLink(); return true;
        case 'insert-pagebreak': this.insertPageBreak(); return true;
        case 'zoom-in': this.setZoom(this.zoom + 0.1); return true;
        case 'zoom-out': this.setZoom(this.zoom - 0.1); return true;
        case 'zoom-reset': this.setZoom(1); return true;
        default: return false;
      }
    }

    toPlainText() { return this.page.innerText; }

    /** Standalone HTML: used for both HTML export and the PDF renderer. */
    toPrintHTML(title) {
      return `<!doctype html><html><head><meta charset="utf-8"><title>${escapeHtml(title || 'Document')}</title>
<style>
  @page { size: ${this.data.pageSize === 'A4' ? 'A4' : 'Letter'}; margin: 1in; }
  body { font-family: Georgia, "Times New Roman", serif; font-size: 11pt; line-height: 1.5; color: #14181f; margin: 0; }
  h1 { font-size: 22pt; margin: 0 0 .35em; line-height: 1.22; }
  h2 { font-size: 16pt; margin: 1em 0 .3em; }
  h3 { font-size: 13pt; margin: 1em 0 .3em; }
  h4 { font-size: 11.5pt; margin: 1em 0 .3em; }
  p { margin: 0 0 .55em; }
  ul, ol { margin: 0 0 .6em; padding-left: 1.9em; }
  blockquote { margin: .7em 0; padding-left: 1em; border-left: 3px solid #c9d2e0; color: #47526a; font-style: italic; }
  img { max-width: 100%; height: auto; }
  a { color: #1a56b0; }
  hr { border: 0; border-top: 1px solid #ccd2dd; margin: 1.1em 0; }
  table { border-collapse: collapse; width: 100%; margin: .7em 0; }
  td, th { border: 1px solid #b9c0ce; padding: 5px 8px; vertical-align: top; }
  th { background: #f0f2f6; }
  pre { font-family: Consolas, monospace; font-size: 10pt; background: #f4f5f8; border: 1px solid #e2e5ec; padding: 9px 11px; }
  /* A page break in the editor becomes a real one on paper. */
  .pagebreak { break-before: page; page-break-before: always; border: 0; height: 0; }
</style></head><body>${this.page.innerHTML}</body></html>`;
    }

    destroy() { this.clearHighlights(); }
  }

  // ---- helpers --------------------------------------------------------------
  /** Build a Range spanning [start,end) of the concatenated text of `nodes`. */
  function rangeForSpan(nodes, start, end) {
    let startNode = null, startOffset = 0, endNode = null, endOffset = 0;
    for (const n of nodes) {
      if (startNode === null && start >= n.start && start < n.end) {
        startNode = n.node;
        startOffset = start - n.start;
      }
      if (end > n.start && end <= n.end) {
        endNode = n.node;
        endOffset = end - n.start;
        break;
      }
    }
    if (!startNode || !endNode) return null;
    const r = document.createRange();
    r.setStart(startNode, startOffset);
    r.setEnd(endNode, endOffset);
    return r;
  }

  /**
   * Strip pasted HTML down to formatting we actually render. Scripts, event
   * handlers and remote references never make it into a document.
   */
  const ALLOWED = new Set(['P','BR','B','STRONG','I','EM','U','S','STRIKE','SPAN','DIV','A','H1','H2','H3','H4','H5','H6',
    'UL','OL','LI','BLOCKQUOTE','PRE','CODE','HR','TABLE','THEAD','TBODY','TR','TD','TH','IMG','SUB','SUP','FONT']);
  const ALLOWED_STYLE = ['font-weight','font-style','text-decoration','text-align','color','background-color','font-size','font-family','margin-left'];

  function sanitizeHtml(html) {
    const doc = new DOMParser().parseFromString(html, 'text/html');
    const walk = (node) => {
      for (const child of Array.from(node.childNodes)) {
        if (child.nodeType === 8) { child.remove(); continue; } // comments
        if (child.nodeType !== 1) continue;
        const tag = child.tagName.toUpperCase();
        if (!ALLOWED.has(tag)) {
          // Keep the text, lose the wrapper.
          const parent = child.parentNode;
          while (child.firstChild) parent.insertBefore(child.firstChild, child);
          child.remove();
          continue;
        }
        for (const attr of Array.from(child.attributes)) {
          const name = attr.name.toLowerCase();
          if (name === 'href' && tag === 'A') {
            if (!/^(https?:|mailto:|#)/i.test(attr.value)) child.removeAttribute(attr.name);
          } else if (name === 'src' && tag === 'IMG') {
            // Only inline data URLs survive; a remote src would be blocked by CSP
            // anyway and would leave a broken image in the document.
            if (!/^data:image\//i.test(attr.value)) child.remove();
          } else if (name === 'style') {
            const kept = attr.value
              .split(';')
              .map((d) => d.trim())
              .filter((d) => ALLOWED_STYLE.some((p) => d.toLowerCase().startsWith(p + ':')))
              .join('; ');
            if (kept) child.setAttribute('style', kept);
            else child.removeAttribute('style');
          } else if (!['colspan', 'rowspan', 'alt'].includes(name)) {
            child.removeAttribute(attr.name);
          }
        }
        walk(child);
      }
    };
    walk(doc.body);
    return doc.body.innerHTML;
  }

  global.DocEditor = DocEditor;
  global.sanitizeHtml = sanitizeHtml;
})(window);
'use strict';
/*
 * OfficeForger — spreadsheet formula engine.
 *
 * Self-contained and free of DOM: a string goes in, a value comes out. The grid
 * supplies cell lookups through a context object, which is also what makes cross-
 * sheet references (Budget!B4) and circular-reference detection possible.
 *
 * Values that flow through here are: number | string | boolean | ForgeError.
 * Errors are values, not exceptions — that is how a spreadsheet works. #DIV/0! in
 * one cell must not stop the other four hundred from calculating.
 */
(function (global) {
  // ---- errors ---------------------------------------------------------------
  class ForgeError {
    constructor(code) {
      this.code = code;
    }
    toString() {
      return this.code;
    }
  }
  const ERR = {
    div0: () => new ForgeError('#DIV/0!'),
    value: () => new ForgeError('#VALUE!'),
    ref: () => new ForgeError('#REF!'),
    name: () => new ForgeError('#NAME?'),
    na: () => new ForgeError('#N/A'),
    num: () => new ForgeError('#NUM!'),
    cycle: () => new ForgeError('#CYCLE!'),
    parse: (m) => new ForgeError('#ERROR!' + (m ? ' ' + m : '')),
  };
  const isErr = (v) => v instanceof ForgeError;

  // ---- A1 <-> index ---------------------------------------------------------
  function colToIndex(letters) {
    let n = 0;
    for (const ch of letters.toUpperCase()) n = n * 26 + (ch.charCodeAt(0) - 64);
    return n - 1; // 0-based
  }
  function indexToCol(i) {
    let s = '';
    i += 1;
    while (i > 0) {
      const rem = (i - 1) % 26;
      s = String.fromCharCode(65 + rem) + s;
      i = Math.floor((i - 1) / 26);
    }
    return s;
  }
  function a1(col, row) {
    return indexToCol(col) + (row + 1);
  }
  /** "B7" / "$B$7" -> {col, row, absCol, absRow}; null if not a reference. */
  function parseA1(s) {
    const m = /^(\$?)([A-Za-z]{1,3})(\$?)([0-9]{1,7})$/.exec(s);
    if (!m) return null;
    return {
      absCol: m[1] === '$',
      col: colToIndex(m[2]),
      absRow: m[3] === '$',
      row: parseInt(m[4], 10) - 1,
    };
  }

  // ---- tokenizer ------------------------------------------------------------
  const T = {
    NUM: 'num', STR: 'str', BOOL: 'bool', REF: 'ref', FUNC: 'func',
    OP: 'op', LP: '(', RP: ')', COMMA: ',', COLON: ':', NAME: 'name', ERRLIT: 'errlit',
  };

  // Error values can appear literally in a formula — deleting a referenced cell
  // rewrites =SUM(A2:A6) to =SUM(#REF!), and that has to parse, not blow up.
  const ERR_LITERAL = /^#(REF!|DIV\/0!|VALUE!|NAME\?|N\/A|NUM!|NULL!|CYCLE!|ERROR!)/i;

  function tokenize(src) {
    const out = [];
    let i = 0;
    const n = src.length;
    while (i < n) {
      const c = src[i];

      if (c === ' ' || c === '\t' || c === '\n' || c === '\r') { i++; continue; }

      if (c === '#') {
        const m = ERR_LITERAL.exec(src.slice(i));
        if (!m) throw ERR.parse('unexpected character #');
        out.push({ t: T.ERRLIT, v: '#' + m[1].toUpperCase() });
        i += m[0].length;
        continue;
      }

      // number
      if (/[0-9]/.test(c) || (c === '.' && /[0-9]/.test(src[i + 1] || ''))) {
        let j = i;
        while (j < n && /[0-9.]/.test(src[j])) j++;
        if (j < n && /[eE]/.test(src[j]) && /[0-9+\-]/.test(src[j + 1] || '')) {
          j++;
          if (/[+\-]/.test(src[j])) j++;
          while (j < n && /[0-9]/.test(src[j])) j++;
        }
        const text = src.slice(i, j);
        const val = parseFloat(text);
        if (isNaN(val)) throw ERR.parse('bad number ' + text);
        out.push({ t: T.NUM, v: val });
        i = j;
        continue;
      }

      // string — "" inside a string is a literal quote
      if (c === '"') {
        let j = i + 1;
        let s = '';
        while (j < n) {
          if (src[j] === '"') {
            if (src[j + 1] === '"') { s += '"'; j += 2; continue; }
            break;
          }
          s += src[j++];
        }
        if (j >= n) throw ERR.parse('unterminated string');
        out.push({ t: T.STR, v: s });
        i = j + 1;
        continue;
      }

      // operators (two-character first)
      const two = src.slice(i, i + 2);
      if (two === '<=' || two === '>=' || two === '<>') {
        out.push({ t: T.OP, v: two });
        i += 2;
        continue;
      }
      if ('+-*/^&=<>%'.includes(c)) { out.push({ t: T.OP, v: c }); i++; continue; }
      if (c === '(') { out.push({ t: T.LP }); i++; continue; }
      if (c === ')') { out.push({ t: T.RP }); i++; continue; }
      if (c === ',' || c === ';') { out.push({ t: T.COMMA }); i++; continue; }
      if (c === ':') { out.push({ t: T.COLON }); i++; continue; }

      // An absolute reference starts with '$', so it never reaches the identifier
      // branch below: $A$1 and $A1 have to be picked up here.
      if (c === '$') {
        let j = i;
        let refTxt = '';
        while (j < n && /[A-Za-z0-9$]/.test(src[j])) refTxt += src[j++];
        const ref = parseA1(refTxt);
        if (!ref) throw ERR.parse('bad absolute reference ' + refTxt);
        out.push({ t: T.REF, sheet: null, ref });
        i = j;
        continue;
      }

      // 'Sheet name'!A1 — quoted sheet name
      if (c === "'") {
        let j = i + 1;
        let name = '';
        while (j < n && src[j] !== "'") name += src[j++];
        if (src[j] !== "'" || src[j + 1] !== '!') throw ERR.parse('bad sheet reference');
        j += 2;
        let refTxt = '';
        while (j < n && /[A-Za-z0-9$]/.test(src[j])) refTxt += src[j++];
        const ref = parseA1(refTxt);
        if (!ref) throw ERR.parse('bad reference after sheet name');
        out.push({ t: T.REF, sheet: name, ref });
        i = j;
        continue;
      }

      // identifier: function name, boolean, bare sheet ref, or cell ref
      if (/[A-Za-z_]/.test(c)) {
        let j = i;
        while (j < n && /[A-Za-z0-9_.$]/.test(src[j])) j++;
        let word = src.slice(i, j);

        // Sheet!A1 (unquoted)
        if (src[j] === '!') {
          let k = j + 1;
          let refTxt = '';
          while (k < n && /[A-Za-z0-9$]/.test(src[k])) refTxt += src[k++];
          const ref = parseA1(refTxt);
          if (!ref) throw ERR.parse('bad reference after sheet name');
          out.push({ t: T.REF, sheet: word, ref });
          i = k;
          continue;
        }

        const upper = word.toUpperCase();
        if (upper === 'TRUE' || upper === 'FALSE') {
          out.push({ t: T.BOOL, v: upper === 'TRUE' });
          i = j;
          continue;
        }

        // function call if an open paren follows (whitespace allowed)
        let k = j;
        while (k < n && /\s/.test(src[k])) k++;
        if (src[k] === '(') {
          out.push({ t: T.FUNC, v: upper });
          i = k; // leave the '(' for the parser
          continue;
        }

        const ref = parseA1(word);
        if (ref) { out.push({ t: T.REF, sheet: null, ref }); i = j; continue; }

        out.push({ t: T.NAME, v: upper }); // unknown bare word -> #NAME?
        i = j;
        continue;
      }

      throw ERR.parse('unexpected character ' + c);
    }
    return out;
  }

  // ---- parser ---------------------------------------------------------------
  // Precedence, loosest first: comparison < concat < +- < */ < ^ < unary < %
  function parse(src) {
    const toks = tokenize(src);
    let p = 0;
    const peek = () => toks[p];
    const next = () => toks[p++];
    const expect = (t) => {
      const tok = next();
      if (!tok || tok.t !== t) throw ERR.parse('expected ' + t);
      return tok;
    };

    function expr() { return comparison(); }

    function comparison() {
      let left = concat();
      while (peek() && peek().t === T.OP && ['=', '<>', '<', '>', '<=', '>='].includes(peek().v)) {
        const op = next().v;
        left = { k: 'bin', op, a: left, b: concat() };
      }
      return left;
    }
    function concat() {
      let left = additive();
      while (peek() && peek().t === T.OP && peek().v === '&') {
        next();
        left = { k: 'bin', op: '&', a: left, b: additive() };
      }
      return left;
    }
    function additive() {
      let left = multiplicative();
      while (peek() && peek().t === T.OP && (peek().v === '+' || peek().v === '-')) {
        const op = next().v;
        left = { k: 'bin', op, a: left, b: multiplicative() };
      }
      return left;
    }
    function multiplicative() {
      let left = power();
      while (peek() && peek().t === T.OP && (peek().v === '*' || peek().v === '/')) {
        const op = next().v;
        left = { k: 'bin', op, a: left, b: power() };
      }
      return left;
    }
    function power() {
      // Left-associative, matching Excel and Sheets: 2^3^2 is (2^3)^2 = 64.
      // Most programming languages disagree; the spreadsheet is the standard here.
      let left = unary();
      while (peek() && peek().t === T.OP && peek().v === '^') {
        next();
        left = { k: 'bin', op: '^', a: left, b: unary() };
      }
      return left;
    }
    function unary() {
      if (peek() && peek().t === T.OP && (peek().v === '-' || peek().v === '+')) {
        const op = next().v;
        return { k: 'un', op, a: unary() };
      }
      return postfix();
    }
    function postfix() {
      let node = primary();
      while (peek() && peek().t === T.OP && peek().v === '%') {
        next();
        node = { k: 'pct', a: node };
      }
      return node;
    }
    function primary() {
      const tok = next();
      if (!tok) throw ERR.parse('unexpected end of formula');

      if (tok.t === T.NUM) return { k: 'num', v: tok.v };
      if (tok.t === T.STR) return { k: 'str', v: tok.v };
      if (tok.t === T.BOOL) return { k: 'bool', v: tok.v };
      if (tok.t === T.NAME) return { k: 'nameErr', v: tok.v };
      if (tok.t === T.ERRLIT) return { k: 'errLit', v: tok.v };

      if (tok.t === T.REF) {
        // A range is two references joined by ':'
        if (peek() && peek().t === T.COLON) {
          next();
          const b = next();
          if (!b || b.t !== T.REF) throw ERR.parse('bad range');
          return { k: 'range', sheet: tok.sheet || b.sheet, a: tok.ref, b: b.ref };
        }
        return { k: 'ref', sheet: tok.sheet, ref: tok.ref };
      }

      if (tok.t === T.FUNC) {
        expect(T.LP);
        const args = [];
        if (peek() && peek().t !== T.RP) {
          args.push(expr());
          while (peek() && peek().t === T.COMMA) {
            next();
            args.push(expr());
          }
        }
        expect(T.RP);
        return { k: 'call', name: tok.v, args };
      }

      if (tok.t === T.LP) {
        const e = expr();
        expect(T.RP);
        return e;
      }

      throw ERR.parse('unexpected token');
    }

    const tree = expr();
    if (p < toks.length) throw ERR.parse('trailing input');
    return tree;
  }

  // ---- coercion -------------------------------------------------------------
  function toNum(v) {
    if (isErr(v)) return v;
    if (typeof v === 'number') return v;
    if (typeof v === 'boolean') return v ? 1 : 0;
    if (v === null || v === undefined || v === '') return 0;
    if (typeof v === 'string') {
      const s = v.trim().replace(/^\$/, '').replace(/,/g, '');
      if (s === '') return 0;
      if (/^-?\d*\.?\d+(e[+-]?\d+)?$/i.test(s)) return parseFloat(s);
      if (/^-?\d*\.?\d+%$/.test(s)) return parseFloat(s) / 100;
      const d = Date.parse(v);
      if (!isNaN(d) && /[-/]/.test(v)) return dateToSerial(new Date(d));
      return ERR.value();
    }
    return ERR.value();
  }
  function toStr(v) {
    if (isErr(v)) return v;
    if (v === null || v === undefined) return '';
    if (typeof v === 'boolean') return v ? 'TRUE' : 'FALSE';
    if (typeof v === 'number') return formatNumberPlain(v);
    return String(v);
  }
  function toBool(v) {
    if (isErr(v)) return v;
    if (typeof v === 'boolean') return v;
    if (typeof v === 'number') return v !== 0;
    if (typeof v === 'string') {
      const u = v.trim().toUpperCase();
      if (u === 'TRUE') return true;
      if (u === 'FALSE') return false;
      if (u === '') return false;
      const n = toNum(v);
      if (isErr(n)) return ERR.value();
      return n !== 0;
    }
    if (v === null || v === undefined) return false;
    return ERR.value();
  }
  function formatNumberPlain(n) {
    if (!isFinite(n)) return String(n);
    // 0.1 + 0.2 must display as 0.3, not 0.30000000000000004.
    const r = Math.round(n * 1e10) / 1e10;
    return String(r);
  }

  // ---- dates (serial numbers, 1899-12-30 epoch, as in Excel/Sheets) ----------
  const DAY_MS = 86400000;
  const EPOCH = Date.UTC(1899, 11, 30);
  function dateToSerial(d) {
    return (Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) - EPOCH) / DAY_MS;
  }
  function serialToDate(s) {
    return new Date(EPOCH + Math.round(s) * DAY_MS);
  }

  // ---- flattening helpers ---------------------------------------------------
  /** Every scalar in the arguments, ranges expanded. Blanks preserved as null. */
  function flatten(args) {
    const out = [];
    const walk = (v) => {
      if (Array.isArray(v)) v.forEach(walk);
      else out.push(v);
    };
    args.forEach(walk);
    return out;
  }
  /** Numbers only, the way SUM/AVERAGE see a range: text and blanks are skipped. */
  function numbersIn(args) {
    const out = [];
    for (const v of flatten(args)) {
      if (isErr(v)) return v;
      if (v === null || v === undefined || v === '') continue;
      if (typeof v === 'number') out.push(v);
      else if (typeof v === 'boolean') out.push(v ? 1 : 0);
      else if (typeof v === 'string') {
        const n = toNum(v);
        if (!isErr(n) && v.trim() !== '') out.push(n);
      }
    }
    return out;
  }
  const firstErr = (vals) => flatten(vals).find(isErr);

  // ---- criteria (COUNTIF / SUMIF / AVERAGEIF) -------------------------------
  function makeMatcher(criteria) {
    if (isErr(criteria)) return () => criteria;
    let op = '=';
    let target = criteria;
    if (typeof criteria === 'string') {
      const m = /^(<=|>=|<>|<|>|=)?\s*(.*)$/.exec(criteria.trim());
      op = m[1] || '=';
      target = m[2];
      const asNum = target !== '' && /^-?\d*\.?\d+%?$/.test(target.trim()) ? toNum(target) : null;
      if (asNum !== null && !isErr(asNum)) target = asNum;
    }
    // "=" and "<>" against text support * and ? wildcards.
    const wildcard =
      typeof target === 'string' && (op === '=' || op === '<>') && /[*?]/.test(target)
        ? new RegExp(
            '^' +
              target
                .replace(/[.+^${}()|[\]\\]/g, '\\$&')
                .replace(/\*/g, '.*')
                .replace(/\?/g, '.') +
              '$',
            'i'
          )
        : null;

    return (value) => {
      if (isErr(value)) return false;
      if (wildcard) {
        const hit = wildcard.test(toStr(value == null ? '' : value));
        return op === '<>' ? !hit : hit;
      }
      let a = value;
      let b = target;
      if (typeof b === 'number') {
        if (a === null || a === '' || a === undefined) return op === '<>';
        const an = toNum(a);
        if (isErr(an)) return op === '<>';
        a = an;
      } else {
        a = toStr(a === null || a === undefined ? '' : a).toLowerCase();
        b = toStr(b).toLowerCase();
      }
      switch (op) {
        case '=': return a === b;
        case '<>': return a !== b;
        case '<': return a < b;
        case '>': return a > b;
        case '<=': return a <= b;
        case '>=': return a >= b;
        default: return a === b;
      }
    };
  }

  // ---- function library -----------------------------------------------------
  // Each entry takes already-evaluated arguments. Ranges arrive as nested arrays;
  // `raw` entries receive unevaluated AST nodes instead (IF's lazy branches).
  const FUNCS = {};
  const def = (names, arity, fn) => {
    for (const n of [].concat(names)) FUNCS[n] = { arity, fn };
  };
  /** Functions that are handed an error argument instead of being replaced by it. */
  const ERROR_TOLERANT = new Set(['ISERROR', 'ISERR', 'ISNA', 'ISBLANK', 'ISNUMBER', 'ISTEXT', 'ISLOGICAL']);

  // -- math
  def('SUM', [1, Infinity], (a) => {
    const ns = numbersIn(a);
    return isErr(ns) ? ns : ns.reduce((s, x) => s + x, 0);
  });
  def('PRODUCT', [1, Infinity], (a) => {
    const ns = numbersIn(a);
    if (isErr(ns)) return ns;
    return ns.length ? ns.reduce((s, x) => s * x, 1) : 0;
  });
  def(['AVERAGE', 'MEAN'], [1, Infinity], (a) => {
    const ns = numbersIn(a);
    if (isErr(ns)) return ns;
    return ns.length ? ns.reduce((s, x) => s + x, 0) / ns.length : ERR.div0();
  });
  def('MIN', [1, Infinity], (a) => {
    const ns = numbersIn(a);
    if (isErr(ns)) return ns;
    return ns.length ? Math.min(...ns) : 0;
  });
  def('MAX', [1, Infinity], (a) => {
    const ns = numbersIn(a);
    if (isErr(ns)) return ns;
    return ns.length ? Math.max(...ns) : 0;
  });
  def('COUNT', [1, Infinity], (a) => {
    const ns = numbersIn(a);
    return isErr(ns) ? ns : ns.length;
  });
  def('COUNTA', [1, Infinity], (a) =>
    flatten(a).filter((v) => v !== null && v !== undefined && v !== '').length);
  def('COUNTBLANK', [1, 1], (a) =>
    flatten(a).filter((v) => v === null || v === undefined || v === '').length);
  def('MEDIAN', [1, Infinity], (a) => {
    const ns = numbersIn(a);
    if (isErr(ns)) return ns;
    if (!ns.length) return ERR.num();
    const s = [...ns].sort((x, y) => x - y);
    const m = Math.floor(s.length / 2);
    return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
  });
  def(['STDEV', 'STDEVS'], [1, Infinity], (a) => {
    const ns = numbersIn(a);
    if (isErr(ns)) return ns;
    if (ns.length < 2) return ERR.div0();
    const mean = ns.reduce((s, x) => s + x, 0) / ns.length;
    return Math.sqrt(ns.reduce((s, x) => s + (x - mean) ** 2, 0) / (ns.length - 1));
  });
  def('STDEVP', [1, Infinity], (a) => {
    const ns = numbersIn(a);
    if (isErr(ns)) return ns;
    if (!ns.length) return ERR.div0();
    const mean = ns.reduce((s, x) => s + x, 0) / ns.length;
    return Math.sqrt(ns.reduce((s, x) => s + (x - mean) ** 2, 0) / ns.length);
  });

  const num1 = (fn) => (a) => {
    const n = toNum(flatten(a)[0]);
    return isErr(n) ? n : fn(n);
  };
  def('ABS', [1, 1], num1(Math.abs));
  def('SQRT', [1, 1], num1((n) => (n < 0 ? ERR.num() : Math.sqrt(n))));
  def('INT', [1, 1], num1(Math.floor));
  def('SIGN', [1, 1], num1(Math.sign));
  def('LN', [1, 1], num1((n) => (n <= 0 ? ERR.num() : Math.log(n))));
  def('LOG10', [1, 1], num1((n) => (n <= 0 ? ERR.num() : Math.log10(n))));
  def('EXP', [1, 1], num1(Math.exp));
  def('SIN', [1, 1], num1(Math.sin));
  def('COS', [1, 1], num1(Math.cos));
  def('TAN', [1, 1], num1(Math.tan));
  def('ATAN', [1, 1], num1(Math.atan));
  def('DEGREES', [1, 1], num1((n) => (n * 180) / Math.PI));
  def('RADIANS', [1, 1], num1((n) => (n * Math.PI) / 180));
  def('PI', [0, 0], () => Math.PI);
  def('RAND', [0, 0], () => Math.random());
  def('RANDBETWEEN', [2, 2], (a) => {
    const lo = toNum(a[0]), hi = toNum(a[1]);
    if (isErr(lo)) return lo;
    if (isErr(hi)) return hi;
    return Math.floor(Math.random() * (Math.floor(hi) - Math.ceil(lo) + 1)) + Math.ceil(lo);
  });
  def('LOG', [1, 2], (a) => {
    const n = toNum(a[0]);
    if (isErr(n)) return n;
    const base = a.length > 1 ? toNum(a[1]) : 10;
    if (isErr(base)) return base;
    if (n <= 0 || base <= 0 || base === 1) return ERR.num();
    return Math.log(n) / Math.log(base);
  });
  def('POWER', [2, 2], (a) => {
    const x = toNum(a[0]), y = toNum(a[1]);
    if (isErr(x)) return x;
    if (isErr(y)) return y;
    const r = Math.pow(x, y);
    return isNaN(r) ? ERR.num() : r;
  });
  def('MOD', [2, 2], (a) => {
    const x = toNum(a[0]), y = toNum(a[1]);
    if (isErr(x)) return x;
    if (isErr(y)) return y;
    if (y === 0) return ERR.div0();
    return x - y * Math.floor(x / y); // sign follows the divisor, as in Excel
  });
  def('ROUND', [1, 2], (a) => {
    const x = toNum(a[0]);
    if (isErr(x)) return x;
    const d = a.length > 1 ? toNum(a[1]) : 0;
    if (isErr(d)) return d;
    const f = Math.pow(10, d);
    return Math.round((x * f + (x >= 0 ? 1e-9 : -1e-9))) / f;
  });
  def('ROUNDUP', [1, 2], (a) => {
    const x = toNum(a[0]);
    if (isErr(x)) return x;
    const d = a.length > 1 ? toNum(a[1]) : 0;
    const f = Math.pow(10, isErr(d) ? 0 : d);
    return (x >= 0 ? Math.ceil(x * f) : Math.floor(x * f)) / f;
  });
  def('ROUNDDOWN', [1, 2], (a) => {
    const x = toNum(a[0]);
    if (isErr(x)) return x;
    const d = a.length > 1 ? toNum(a[1]) : 0;
    const f = Math.pow(10, isErr(d) ? 0 : d);
    return (x >= 0 ? Math.floor(x * f) : Math.ceil(x * f)) / f;
  });
  def('CEILING', [1, 2], (a) => {
    const x = toNum(a[0]);
    if (isErr(x)) return x;
    const step = a.length > 1 ? toNum(a[1]) : 1;
    if (isErr(step)) return step;
    if (step === 0) return 0;
    return Math.ceil(x / step) * step;
  });
  def('FLOOR', [1, 2], (a) => {
    const x = toNum(a[0]);
    if (isErr(x)) return x;
    const step = a.length > 1 ? toNum(a[1]) : 1;
    if (isErr(step)) return step;
    if (step === 0) return ERR.div0();
    return Math.floor(x / step) * step;
  });
  def('TRUNC', [1, 2], (a) => {
    const x = toNum(a[0]);
    if (isErr(x)) return x;
    const d = a.length > 1 ? toNum(a[1]) : 0;
    const f = Math.pow(10, isErr(d) ? 0 : d);
    return Math.trunc(x * f) / f;
  });

  // -- conditional aggregates
  def('SUMIF', [2, 3], (a) => {
    const range = Array.isArray(a[0]) ? flatten([a[0]]) : [a[0]];
    const match = makeMatcher(a[1]);
    const sumRange = a.length > 2 ? (Array.isArray(a[2]) ? flatten([a[2]]) : [a[2]]) : range;
    let total = 0;
    for (let i = 0; i < range.length; i++) {
      if (!match(range[i])) continue;
      const v = toNum(sumRange[i]);
      if (!isErr(v)) total += v;
    }
    return total;
  });
  def('COUNTIF', [2, 2], (a) => {
    const range = Array.isArray(a[0]) ? flatten([a[0]]) : [a[0]];
    const match = makeMatcher(a[1]);
    return range.filter(match).length;
  });
  def('AVERAGEIF', [2, 3], (a) => {
    const range = Array.isArray(a[0]) ? flatten([a[0]]) : [a[0]];
    const match = makeMatcher(a[1]);
    const avgRange = a.length > 2 ? (Array.isArray(a[2]) ? flatten([a[2]]) : [a[2]]) : range;
    let total = 0, count = 0;
    for (let i = 0; i < range.length; i++) {
      if (!match(range[i])) continue;
      const v = toNum(avgRange[i]);
      if (!isErr(v)) { total += v; count++; }
    }
    return count ? total / count : ERR.div0();
  });
  def('SUMIFS', [3, Infinity], (a) => conditionalMulti(a, 'sum'));
  def('COUNTIFS', [2, Infinity], (a) => conditionalMulti([null, ...a], 'count'));
  def('AVERAGEIFS', [3, Infinity], (a) => conditionalMulti(a, 'avg'));
  function conditionalMulti(a, mode) {
    const target = mode === 'count' ? null : (Array.isArray(a[0]) ? flatten([a[0]]) : [a[0]]);
    const pairs = [];
    for (let i = 1; i + 1 < a.length; i += 2) {
      pairs.push([Array.isArray(a[i]) ? flatten([a[i]]) : [a[i]], makeMatcher(a[i + 1])]);
    }
    if (!pairs.length) return ERR.value();
    const len = pairs[0][0].length;
    let total = 0, count = 0;
    for (let r = 0; r < len; r++) {
      if (!pairs.every(([range, match]) => match(range[r]))) continue;
      count++;
      if (target) {
        const v = toNum(target[r]);
        if (!isErr(v)) total += v;
      }
    }
    if (mode === 'count') return count;
    if (mode === 'sum') return total;
    return count ? total / count : ERR.div0();
  }

  // -- logic
  def('AND', [1, Infinity], (a) => {
    const vals = flatten(a).filter((v) => v !== null && v !== '');
    const e = vals.find(isErr);
    if (e) return e;
    if (!vals.length) return ERR.value();
    for (const v of vals) {
      const b = toBool(v);
      if (isErr(b)) return b;
      if (!b) return false;
    }
    return true;
  });
  def('OR', [1, Infinity], (a) => {
    const vals = flatten(a).filter((v) => v !== null && v !== '');
    const e = vals.find(isErr);
    if (e) return e;
    if (!vals.length) return ERR.value();
    for (const v of vals) {
      const b = toBool(v);
      if (isErr(b)) return b;
      if (b) return true;
    }
    return false;
  });
  def('NOT', [1, 1], (a) => {
    const b = toBool(flatten(a)[0]);
    return isErr(b) ? b : !b;
  });
  def('XOR', [1, Infinity], (a) => {
    let count = 0;
    for (const v of flatten(a)) {
      const b = toBool(v);
      if (isErr(b)) return b;
      if (b) count++;
    }
    return count % 2 === 1;
  });
  def('TRUE', [0, 0], () => true);
  def('FALSE', [0, 0], () => false);
  def('NA', [0, 0], () => ERR.na());

  // -- text
  def(['CONCAT', 'CONCATENATE'], [1, Infinity], (a) => {
    let s = '';
    for (const v of flatten(a)) {
      const t = toStr(v);
      if (isErr(t)) return t;
      s += t;
    }
    return s;
  });
  def('TEXTJOIN', [3, Infinity], (a) => {
    const sep = toStr(a[0]);
    if (isErr(sep)) return sep;
    const skipEmpty = toBool(a[1]);
    const parts = [];
    for (const v of flatten(a.slice(2))) {
      if (skipEmpty === true && (v === null || v === undefined || v === '')) continue;
      const t = toStr(v);
      if (isErr(t)) return t;
      parts.push(t);
    }
    return parts.join(sep);
  });
  def('LEN', [1, 1], (a) => {
    const s = toStr(flatten(a)[0]);
    return isErr(s) ? s : s.length;
  });
  def('LEFT', [1, 2], (a) => {
    const s = toStr(a[0]);
    if (isErr(s)) return s;
    const n = a.length > 1 ? toNum(a[1]) : 1;
    return isErr(n) ? n : s.slice(0, Math.max(0, Math.floor(n)));
  });
  def('RIGHT', [1, 2], (a) => {
    const s = toStr(a[0]);
    if (isErr(s)) return s;
    const n = a.length > 1 ? toNum(a[1]) : 1;
    if (isErr(n)) return n;
    const k = Math.max(0, Math.floor(n));
    return k === 0 ? '' : s.slice(-k);
  });
  def('MID', [3, 3], (a) => {
    const s = toStr(a[0]);
    if (isErr(s)) return s;
    const start = toNum(a[1]), len = toNum(a[2]);
    if (isErr(start)) return start;
    if (isErr(len)) return len;
    if (start < 1) return ERR.value();
    return s.substr(Math.floor(start) - 1, Math.max(0, Math.floor(len)));
  });
  def('UPPER', [1, 1], (a) => { const s = toStr(a[0]); return isErr(s) ? s : s.toUpperCase(); });
  def('LOWER', [1, 1], (a) => { const s = toStr(a[0]); return isErr(s) ? s : s.toLowerCase(); });
  def('PROPER', [1, 1], (a) => {
    const s = toStr(a[0]);
    return isErr(s) ? s : s.replace(/\w\S*/g, (w) => w[0].toUpperCase() + w.slice(1).toLowerCase());
  });
  def('TRIM', [1, 1], (a) => {
    const s = toStr(a[0]);
    return isErr(s) ? s : s.trim().replace(/\s+/g, ' ');
  });
  def('SUBSTITUTE', [3, 4], (a) => {
    const s = toStr(a[0]), find = toStr(a[1]), rep = toStr(a[2]);
    if (isErr(s)) return s;
    if (isErr(find)) return find;
    if (isErr(rep)) return rep;
    if (find === '') return s;
    if (a.length > 3) {
      const nth = toNum(a[3]);
      if (isErr(nth)) return nth;
      let idx = -1;
      for (let i = 0; i < nth; i++) {
        idx = s.indexOf(find, idx + 1);
        if (idx === -1) return s;
      }
      return s.slice(0, idx) + rep + s.slice(idx + find.length);
    }
    return s.split(find).join(rep);
  });
  def('REPLACE', [4, 4], (a) => {
    const s = toStr(a[0]);
    if (isErr(s)) return s;
    const start = toNum(a[1]), len = toNum(a[2]), rep = toStr(a[3]);
    if (isErr(start)) return start;
    if (isErr(len)) return len;
    if (isErr(rep)) return rep;
    return s.slice(0, start - 1) + rep + s.slice(start - 1 + len);
  });
  def('FIND', [2, 3], (a) => {
    const find = toStr(a[0]), s = toStr(a[1]);
    if (isErr(find)) return find;
    if (isErr(s)) return s;
    const from = a.length > 2 ? toNum(a[2]) : 1;
    const i = s.indexOf(find, (isErr(from) ? 1 : from) - 1);
    return i === -1 ? ERR.value() : i + 1;
  });
  def('SEARCH', [2, 3], (a) => {
    const find = toStr(a[0]).toLowerCase(), s = toStr(a[1]).toLowerCase();
    const from = a.length > 2 ? toNum(a[2]) : 1;
    const i = s.indexOf(find, (isErr(from) ? 1 : from) - 1);
    return i === -1 ? ERR.value() : i + 1;
  });
  def('REPT', [2, 2], (a) => {
    const s = toStr(a[0]);
    if (isErr(s)) return s;
    const n = toNum(a[1]);
    if (isErr(n)) return n;
    if (n < 0 || n * s.length > 32767) return ERR.value();
    return s.repeat(Math.floor(n));
  });
  def('VALUE', [1, 1], (a) => toNum(a[0]));
  def('T', [1, 1], (a) => (typeof a[0] === 'string' ? a[0] : ''));
  def('CHAR', [1, 1], (a) => {
    const n = toNum(a[0]);
    return isErr(n) ? n : String.fromCharCode(n);
  });
  def('CODE', [1, 1], (a) => {
    const s = toStr(a[0]);
    if (isErr(s)) return s;
    return s.length ? s.charCodeAt(0) : ERR.value();
  });
  def('TEXT', [2, 2], (a) => {
    const n = toNum(a[0]);
    const pattern = toStr(a[1]);
    if (isErr(pattern)) return pattern;
    if (isErr(n)) return toStr(a[0]);
    return applyTextPattern(n, pattern);
  });
  function applyTextPattern(n, pattern) {
    // A useful subset: decimal places, thousands separator, %, $ and date codes.
    if (/[ymdhs]/i.test(pattern) && !/[#0]/.test(pattern.replace(/[ymdhs:/\- ]/gi, ''))) {
      return formatDatePattern(serialToDate(n), pattern, n);
    }
    const pct = pattern.includes('%');
    let value = pct ? n * 100 : n;
    const decMatch = /\.(0+|#+)/.exec(pattern);
    const decimals = decMatch ? decMatch[1].length : 0;
    const grouped = /[#0],[#0]/.test(pattern) || pattern.includes('#,##');
    let s = Math.abs(value).toFixed(decimals);
    if (grouped) {
      const [int, dec] = s.split('.');
      s = int.replace(/\B(?=(\d{3})+(?!\d))/g, ',') + (dec ? '.' + dec : '');
    }
    if (value < 0) s = '-' + s;
    if (pattern.includes('$')) s = s.startsWith('-') ? '-$' + s.slice(1) : '$' + s;
    if (pct) s += '%';
    return s;
  }
  function formatDatePattern(d, pattern, serial) {
    const MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];
    const DAYS = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
    const frac = serial - Math.floor(serial);
    const totalMin = Math.round(frac * 1440);
    const hh = Math.floor(totalMin / 60), mi = totalMin % 60;
    const p2 = (x) => String(x).padStart(2, '0');
    return pattern.replace(/yyyy|yy|mmmm|mmm|mm|m|dddd|ddd|dd|d|hh|h|ss|s|AM\/PM/gi, (tok) => {
      switch (tok.toLowerCase()) {
        case 'yyyy': return String(d.getUTCFullYear());
        case 'yy': return p2(d.getUTCFullYear() % 100);
        case 'mmmm': return MONTHS[d.getUTCMonth()];
        case 'mmm': return MONTHS[d.getUTCMonth()].slice(0, 3);
        case 'mm': return p2(d.getUTCMonth() + 1);
        case 'm': return String(d.getUTCMonth() + 1);
        case 'dddd': return DAYS[d.getUTCDay()];
        case 'ddd': return DAYS[d.getUTCDay()].slice(0, 3);
        case 'dd': return p2(d.getUTCDate());
        case 'd': return String(d.getUTCDate());
        case 'hh': return p2(hh);
        case 'h': return String(hh);
        case 'ss': return p2(0);
        case 's': return '0';
        case 'am/pm': return hh < 12 ? 'AM' : 'PM';
        default: return tok;
      }
    }).replace(/\bmm\b/g, p2(mi));
  }

  // -- dates
  def('TODAY', [0, 0], () => dateToSerial(new Date()));
  def('NOW', [0, 0], () => {
    const d = new Date();
    return dateToSerial(d) + (d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds()) / 86400;
  });
  def('DATE', [3, 3], (a) => {
    const y = toNum(a[0]), m = toNum(a[1]), d = toNum(a[2]);
    if (isErr(y)) return y;
    if (isErr(m)) return m;
    if (isErr(d)) return d;
    return (Date.UTC(y, m - 1, d) - EPOCH) / DAY_MS;
  });
  const datePart = (fn) => (a) => {
    const n = toNum(a[0]);
    if (isErr(n)) return n;
    return fn(serialToDate(n));
  };
  def('YEAR', [1, 1], datePart((d) => d.getUTCFullYear()));
  def('MONTH', [1, 1], datePart((d) => d.getUTCMonth() + 1));
  def('DAY', [1, 1], datePart((d) => d.getUTCDate()));
  def('WEEKDAY', [1, 2], (a) => {
    const n = toNum(a[0]);
    if (isErr(n)) return n;
    return serialToDate(n).getUTCDay() + 1;
  });
  def('DAYS', [2, 2], (a) => {
    const end = toNum(a[0]), start = toNum(a[1]);
    if (isErr(end)) return end;
    if (isErr(start)) return start;
    return Math.round(end - start);
  });
  def('EDATE', [2, 2], (a) => {
    const n = toNum(a[0]), months = toNum(a[1]);
    if (isErr(n)) return n;
    if (isErr(months)) return months;
    const d = serialToDate(n);
    return (Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + Math.floor(months), d.getUTCDate()) - EPOCH) / DAY_MS;
  });

  // -- lookup
  def('VLOOKUP', [3, 4], (a) => {
    const key = a[0];
    const table = a[1];
    const colIdx = toNum(a[2]);
    if (isErr(colIdx)) return colIdx;
    const approx = a.length > 3 ? toBool(a[3]) : true;
    if (!Array.isArray(table) || !Array.isArray(table[0])) return ERR.ref();
    const col = Math.floor(colIdx) - 1;
    if (col < 0 || col >= table[0].length) return ERR.ref();

    if (approx === true) {
      let best = null;
      const kn = toNum(key);
      for (const row of table) {
        const cn = toNum(row[0]);
        if (isErr(cn) || isErr(kn)) {
          if (toStr(row[0]).toLowerCase() === toStr(key).toLowerCase()) return row[col];
          continue;
        }
        if (cn <= kn) best = row;
      }
      return best ? best[col] : ERR.na();
    }
    for (const row of table) {
      const same =
        typeof key === 'number' || typeof row[0] === 'number'
          ? toNum(row[0]) === toNum(key)
          : toStr(row[0]).toLowerCase() === toStr(key).toLowerCase();
      if (same) return row[col];
    }
    return ERR.na();
  });
  def('HLOOKUP', [3, 4], (a) => {
    const key = a[0];
    const table = a[1];
    const rowIdx = toNum(a[2]);
    if (isErr(rowIdx)) return rowIdx;
    if (!Array.isArray(table) || !Array.isArray(table[0])) return ERR.ref();
    const r = Math.floor(rowIdx) - 1;
    if (r < 0 || r >= table.length) return ERR.ref();
    const header = table[0];
    for (let c = 0; c < header.length; c++) {
      const same =
        typeof key === 'number' || typeof header[c] === 'number'
          ? toNum(header[c]) === toNum(key)
          : toStr(header[c]).toLowerCase() === toStr(key).toLowerCase();
      if (same) return table[r][c];
    }
    return ERR.na();
  });
  def('INDEX', [2, 3], (a) => {
    const table = a[0];
    if (!Array.isArray(table)) return a.length > 1 && toNum(a[1]) === 1 ? table : ERR.ref();
    const r = toNum(a[1]);
    if (isErr(r)) return r;
    const rows = Array.isArray(table[0]) ? table : [table];
    if (a.length > 2) {
      const c = toNum(a[2]);
      if (isErr(c)) return c;
      const row = rows[Math.floor(r) - 1];
      if (!row) return ERR.ref();
      const v = row[Math.floor(c) - 1];
      return v === undefined ? ERR.ref() : v;
    }
    // One index into a single-row or single-column range.
    const flat = flatten([table]);
    const v = flat[Math.floor(r) - 1];
    return v === undefined ? ERR.ref() : v;
  });
  def('MATCH', [2, 3], (a) => {
    const key = a[0];
    const flat = flatten([a[1]]);
    const type = a.length > 2 ? toNum(a[2]) : 1;
    if (type === 0) {
      for (let i = 0; i < flat.length; i++) {
        const same =
          typeof key === 'number' || typeof flat[i] === 'number'
            ? toNum(flat[i]) === toNum(key)
            : toStr(flat[i]).toLowerCase() === toStr(key).toLowerCase();
        if (same) return i + 1;
      }
      return ERR.na();
    }
    const kn = toNum(key);
    let best = -1;
    for (let i = 0; i < flat.length; i++) {
      const cn = toNum(flat[i]);
      if (isErr(cn)) continue;
      if (type >= 1 ? cn <= kn : cn >= kn) best = i;
    }
    return best === -1 ? ERR.na() : best + 1;
  });

  // -- info / error handling
  def('ISBLANK', [1, 1], (a) => a[0] === null || a[0] === undefined || a[0] === '');
  def('ISNUMBER', [1, 1], (a) => typeof a[0] === 'number');
  def('ISTEXT', [1, 1], (a) => typeof a[0] === 'string' && a[0] !== '');
  def('ISERROR', [1, 1], (a) => isErr(a[0]));
  def('ISERR', [1, 1], (a) => isErr(a[0]) && a[0].code !== '#N/A');
  def('ISNA', [1, 1], (a) => isErr(a[0]) && a[0].code === '#N/A');
  def('ISLOGICAL', [1, 1], (a) => typeof a[0] === 'boolean');
  def('ROWS', [1, 1], (a) => (Array.isArray(a[0]) ? a[0].length : 1));
  def('COLUMNS', [1, 1], (a) => (Array.isArray(a[0]) && Array.isArray(a[0][0]) ? a[0][0].length : Array.isArray(a[0]) ? 1 : 1));

  // -- finance
  def('PMT', [3, 5], (a) => {
    const rate = toNum(a[0]), nper = toNum(a[1]), pv = toNum(a[2]);
    if (isErr(rate)) return rate;
    if (isErr(nper)) return nper;
    if (isErr(pv)) return pv;
    const fv = a.length > 3 ? toNum(a[3]) : 0;
    const type = a.length > 4 ? toNum(a[4]) : 0;
    if (nper === 0) return ERR.num();
    if (rate === 0) return -(pv + (isErr(fv) ? 0 : fv)) / nper;
    const p = Math.pow(1 + rate, nper);
    let pmt = (-rate * (pv * p + (isErr(fv) ? 0 : fv))) / ((p - 1) * (1 + rate * (isErr(type) ? 0 : type)));
    return pmt;
  });
  def('FV', [3, 5], (a) => {
    const rate = toNum(a[0]), nper = toNum(a[1]), pmt = toNum(a[2]);
    if (isErr(rate)) return rate;
    if (isErr(nper)) return nper;
    if (isErr(pmt)) return pmt;
    const pv = a.length > 3 ? toNum(a[3]) : 0;
    if (rate === 0) return -(pv + pmt * nper);
    const p = Math.pow(1 + rate, nper);
    return -(pv * p + pmt * ((p - 1) / rate));
  });

  // ---- evaluator ------------------------------------------------------------
  /*
   * ctx must provide:
   *   getValue(sheetName|null, col, row) -> scalar value (already computed)
   *   sheet                              -> name of the sheet the formula lives on
   *   hasSheet(name)                     -> boolean
   */
  function evaluate(node, ctx) {
    switch (node.k) {
      case 'num': return node.v;
      case 'str': return node.v;
      case 'bool': return node.v;
      case 'nameErr': return ERR.name();
      case 'errLit': return new ForgeError(node.v);

      case 'ref': {
        if (node.sheet && !ctx.hasSheet(node.sheet)) return ERR.ref();
        return ctx.getValue(node.sheet, node.ref.col, node.ref.row);
      }

      case 'range': {
        if (node.sheet && !ctx.hasSheet(node.sheet)) return ERR.ref();
        const r1 = Math.min(node.a.row, node.b.row);
        const r2 = Math.max(node.a.row, node.b.row);
        const c1 = Math.min(node.a.col, node.b.col);
        const c2 = Math.max(node.a.col, node.b.col);
        // A guard rail, not a limit anyone hits by accident: a runaway range like
        // A1:ZZ100000 would otherwise lock the app up building millions of cells.
        if ((r2 - r1 + 1) * (c2 - c1 + 1) > 250000) return ERR.num();
        const rows = [];
        for (let r = r1; r <= r2; r++) {
          const row = [];
          for (let c = c1; c <= c2; c++) row.push(ctx.getValue(node.sheet, c, r));
          rows.push(row);
        }
        return rows;
      }

      case 'un': {
        const v = evaluate(node.a, ctx);
        if (isErr(v)) return v;
        const n = toNum(scalar(v));
        if (isErr(n)) return n;
        return node.op === '-' ? -n : n;
      }

      case 'pct': {
        const v = evaluate(node.a, ctx);
        if (isErr(v)) return v;
        const n = toNum(scalar(v));
        return isErr(n) ? n : n / 100;
      }

      case 'bin': {
        // IF-like short-circuiting does not apply to operators; both sides run.
        const a = scalar(evaluate(node.a, ctx));
        const b = scalar(evaluate(node.b, ctx));
        if (isErr(a)) return a;
        if (isErr(b)) return b;
        return binop(node.op, a, b);
      }

      case 'call': {
        const name = node.name;

        // Lazy arguments: only the taken branch is evaluated, so
        // =IF(A1=0,"n/a",100/A1) does not produce #DIV/0! when A1 is 0.
        if (name === 'IF') {
          if (node.args.length < 2) return ERR.value();
          const cond = toBool(scalar(evaluate(node.args[0], ctx)));
          if (isErr(cond)) return cond;
          if (cond) return scalar(evaluate(node.args[1], ctx));
          return node.args.length > 2 ? scalar(evaluate(node.args[2], ctx)) : false;
        }
        if (name === 'IFERROR' || name === 'IFNA') {
          if (node.args.length < 1) return ERR.value();
          let v;
          try {
            v = scalar(evaluate(node.args[0], ctx));
          } catch (e) {
            v = isErr(e) ? e : ERR.value();
          }
          const bad = name === 'IFERROR' ? isErr(v) : isErr(v) && v.code === '#N/A';
          if (!bad) return v;
          return node.args.length > 1 ? scalar(evaluate(node.args[1], ctx)) : '';
        }
        if (name === 'IFS') {
          for (let i = 0; i + 1 < node.args.length; i += 2) {
            const cond = toBool(scalar(evaluate(node.args[i], ctx)));
            if (isErr(cond)) return cond;
            if (cond) return scalar(evaluate(node.args[i + 1], ctx));
          }
          return ERR.na();
        }
        if (name === 'SWITCH') {
          if (node.args.length < 3) return ERR.value();
          const subject = scalar(evaluate(node.args[0], ctx));
          let i = 1;
          for (; i + 1 < node.args.length; i += 2) {
            const test = scalar(evaluate(node.args[i], ctx));
            if (binop('=', subject, test) === true) return scalar(evaluate(node.args[i + 1], ctx));
          }
          return i < node.args.length ? scalar(evaluate(node.args[i], ctx)) : ERR.na();
        }

        const fn = FUNCS[name];
        if (!fn) return ERR.name();

        const args = node.args.map((a) => evaluate(a, ctx));
        if (args.length < fn.arity[0] || args.length > fn.arity[1]) return ERR.value();

        // An error anywhere in a scalar argument propagates — except to the
        // functions whose entire job is to inspect one. ISERROR(#N/A) must see
        // the error, not be replaced by it.
        if (!ERROR_TOLERANT.has(name)) {
          for (const a of args) if (isErr(a)) return a;
        }

        try {
          const out = fn.fn(args);
          return out === undefined || out === null ? '' : out;
        } catch (e) {
          return isErr(e) ? e : ERR.value();
        }
      }

      default:
        return ERR.value();
    }
  }

  /** Where a single value is wanted, a 1x1 range collapses and anything bigger errors. */
  function scalar(v) {
    if (Array.isArray(v)) {
      if (v.length === 1 && Array.isArray(v[0]) && v[0].length === 1) return v[0][0];
      if (v.length === 1 && !Array.isArray(v[0])) return v[0];
      return ERR.value();
    }
    return v;
  }

  function binop(op, a, b) {
    if (op === '&') {
      const sa = toStr(a === null ? '' : a);
      const sb = toStr(b === null ? '' : b);
      if (isErr(sa)) return sa;
      if (isErr(sb)) return sb;
      return sa + sb;
    }

    if (['=', '<>', '<', '>', '<=', '>='].includes(op)) {
      // Blank compares equal to 0 and to "", the way a spreadsheet expects.
      const an = a === null || a === undefined ? '' : a;
      const bn = b === null || b === undefined ? '' : b;
      let x = an, y = bn;
      if (typeof an === 'number' || typeof bn === 'number') {
        const xa = toNum(an), yb = toNum(bn);
        if (!isErr(xa) && !isErr(yb)) { x = xa; y = yb; }
        else { x = toStr(an).toLowerCase(); y = toStr(bn).toLowerCase(); }
      } else if (typeof an === 'boolean' || typeof bn === 'boolean') {
        x = toBool(an) === true ? 1 : 0;
        y = toBool(bn) === true ? 1 : 0;
      } else {
        x = toStr(an).toLowerCase();
        y = toStr(bn).toLowerCase();
      }
      switch (op) {
        case '=': return x === y;
        case '<>': return x !== y;
        case '<': return x < y;
        case '>': return x > y;
        case '<=': return x <= y;
        case '>=': return x >= y;
      }
    }

    const x = toNum(a), y = toNum(b);
    if (isErr(x)) return x;
    if (isErr(y)) return y;
    switch (op) {
      case '+': return x + y;
      case '-': return x - y;
      case '*': return x * y;
      case '/': return y === 0 ? ERR.div0() : x / y;
      case '^': {
        const r = Math.pow(x, y);
        return isNaN(r) || !isFinite(r) ? ERR.num() : r;
      }
      default: return ERR.value();
    }
  }

  // ---- reference rewriting (used by copy/paste and the fill handle) ----------
  /**
   * Shift every relative reference in a formula by (dCol, dRow). Absolute parts
   * ($A$1) stay put, which is the entire point of the $ in the first place.
   */
  function offsetFormula(formula, dCol, dRow) {
    if (!formula || formula[0] !== '=') return formula;
    let out = '';
    let i = 1;
    const src = formula;
    out = '=';
    while (i < src.length) {
      // Skip string literals wholesale — "A1" is text, not a reference.
      if (src[i] === '"') {
        let j = i + 1;
        out += '"';
        while (j < src.length) {
          out += src[j];
          if (src[j] === '"') {
            if (src[j + 1] === '"') { out += src[j + 1]; j += 2; continue; }
            j++;
            break;
          }
          j++;
        }
        i = j;
        continue;
      }
      const m = /^(\$?)([A-Za-z]{1,3})(\$?)([0-9]{1,7})(?![\w(])/.exec(src.slice(i));
      // A function name immediately followed by '(' is not a reference.
      if (m && !/^[A-Za-z_][A-Za-z0-9_.]*\s*\(/.test(src.slice(i))) {
        const absCol = m[1] === '$';
        const absRow = m[3] === '$';
        let col = colToIndex(m[2]);
        let row = parseInt(m[4], 10) - 1;
        if (!absCol) col += dCol;
        if (!absRow) row += dRow;
        if (col < 0 || row < 0) {
          out += '#REF!';
        } else {
          out += (absCol ? '$' : '') + indexToCol(col) + (absRow ? '$' : '') + (row + 1);
        }
        i += m[0].length;
        continue;
      }
      out += src[i];
      i++;
    }
    return out;
  }

  /** Every cell a formula depends on, as "sheet col,row" keys. */
  // A reference, with an optional sheet prefix. The trailing guard stops it from
  // swallowing a function name — SUM( is not a reference to a cell called SUM.
  const REF_RE = /^(?:'((?:[^']|'')+)'!|([A-Za-z_][A-Za-z0-9_.]*)!)?(\$?)([A-Za-z]{1,3})(\$?)(\d{1,7})(?![\w(])/;

  function writeRef(prefix, absCol, col, absRow, row) {
    return prefix + (absCol ? '$' : '') + indexToCol(col) + (absRow ? '$' : '') + (row + 1);
  }

  /**
   * Rewrite a formula for rows or columns being inserted or deleted.
   *
   * This is what keeps =SUM(B2:B4) meaning the same three cells after a row is
   * inserted above it. Unlike copy and paste, a $ does NOT pin a reference here:
   * inserting a row above $B$4 moves it to $B$5 in every spreadsheet there is,
   * because the cell itself moved. $ controls what happens when a formula moves,
   * not what happens when its target moves.
   *
   * A reference to a deleted cell becomes #REF!. A range that merely overlaps the
   * deleted band shrinks instead — that is what Excel does, and what people mean.
   */
  function adjustFormula(formula, opts) {
    if (!formula || formula[0] !== '=') return formula;
    const { axis, at, count, remove, targetSheet, formulaSheet } = opts;

    const shift = (pos) => {
      if (!remove) return pos >= at ? pos + count : pos;
      if (pos < at) return pos;
      if (pos < at + count) return null; // inside the deleted band
      return pos - count;
    };
    const same = (a, b) => String(a).toLowerCase() === String(b).toLowerCase();

    const src = formula;
    let out = '=';
    let i = 1;

    while (i < src.length) {
      // Text inside quotes is copied straight through: "A1" is a string, not a ref.
      if (src[i] === '"') {
        out += '"';
        let j = i + 1;
        while (j < src.length) {
          out += src[j];
          if (src[j] === '"') {
            if (src[j + 1] === '"') { out += src[j + 1]; j += 2; continue; }
            j++;
            break;
          }
          j++;
        }
        i = j;
        continue;
      }

      const m = REF_RE.exec(src.slice(i));
      if (!m) { out += src[i]; i++; continue; }

      const tail = m[3] + m[4] + m[5] + m[6];
      const prefix = m[0].slice(0, m[0].length - tail.length);
      const sheetName = m[1] !== undefined ? m[1].replace(/''/g, "'") : m[2];
      const applies = sheetName ? same(sheetName, targetSheet) : same(formulaSheet, targetSheet);

      // A ':' immediately after makes this the start of a range.
      const m2 = src[i + m[0].length] === ':' ? REF_RE.exec(src.slice(i + m[0].length + 1)) : null;
      const total = m[0].length + (m2 ? 1 + m2[0].length : 0);

      if (!applies) { out += src.substr(i, total); i += total; continue; }

      const a = { absCol: m[3] === '$', col: colToIndex(m[4]), absRow: m[5] === '$', row: parseInt(m[6], 10) - 1 };

      if (!m2) {
        const moved = shift(axis === 'row' ? a.row : a.col);
        if (moved === null) out += '#REF!';
        else {
          if (axis === 'row') a.row = moved; else a.col = moved;
          out += writeRef(prefix, a.absCol, a.col, a.absRow, a.row);
        }
        i += total;
        continue;
      }

      const tail2 = m2[3] + m2[4] + m2[5] + m2[6];
      const prefix2 = m2[0].slice(0, m2[0].length - tail2.length);
      const b = { absCol: m2[3] === '$', col: colToIndex(m2[4]), absRow: m2[5] === '$', row: parseInt(m2[6], 10) - 1 };

      const posA = axis === 'row' ? a.row : a.col;
      const posB = axis === 'row' ? b.row : b.col;
      const lo = Math.min(posA, posB);
      const hi = Math.max(posA, posB);
      let newLo = shift(lo);
      let newHi = shift(hi);

      if (newLo === null && newHi === null) { out += '#REF!'; i += total; continue; }
      if (newLo === null) newLo = at;       // start was cut: the range now begins at the gap
      if (newHi === null) newHi = at - 1;   // end was cut: the range now stops before it
      if (newHi < newLo) { out += '#REF!'; i += total; continue; }

      // Put the endpoints back the way round the user wrote them.
      const aIsLo = posA <= posB;
      if (axis === 'row') { a.row = aIsLo ? newLo : newHi; b.row = aIsLo ? newHi : newLo; }
      else { a.col = aIsLo ? newLo : newHi; b.col = aIsLo ? newHi : newLo; }

      out += writeRef(prefix, a.absCol, a.col, a.absRow, a.row) + ':' +
             writeRef(prefix2, b.absCol, b.col, b.absRow, b.row);
      i += total;
    }
    return out;
  }

  function dependencies(node, sheetName, out) {
    out = out || [];
    if (!node || typeof node !== 'object') return out;
    if (node.k === 'ref') {
      out.push({ sheet: node.sheet || sheetName, col: node.ref.col, row: node.ref.row });
    } else if (node.k === 'range') {
      const r1 = Math.min(node.a.row, node.b.row), r2 = Math.max(node.a.row, node.b.row);
      const c1 = Math.min(node.a.col, node.b.col), c2 = Math.max(node.a.col, node.b.col);
      if ((r2 - r1 + 1) * (c2 - c1 + 1) <= 250000) {
        for (let r = r1; r <= r2; r++)
          for (let c = c1; c <= c2; c++) out.push({ sheet: node.sheet || sheetName, col: c, row: r });
      }
    }
    for (const key of ['a', 'b']) if (node[key]) dependencies(node[key], sheetName, out);
    if (node.args) node.args.forEach((a) => dependencies(a, sheetName, out));
    return out;
  }

  global.Formula = {
    parse,
    evaluate,
    tokenize,
    offsetFormula,
    adjustFormula,
    dependencies,
    ForgeError,
    isErr,
    ERR,
    toNum,
    toStr,
    toBool,
    scalar,
    colToIndex,
    indexToCol,
    a1,
    parseA1,
    dateToSerial,
    serialToDate,
    formatNumberPlain,
    applyTextPattern,
    FUNCS,
  };
})(typeof window !== 'undefined' ? window : globalThis);
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy"
      content="default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self'; media-src 'self' data: blob:;" />
<title>OfficeForger</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>

<div id="app">
  <!-- Tab strip: every open document, plus the new-file menu. -->
  <div id="tabstrip">
    <div id="tabs"></div>
    <button id="newTabBtn" class="tabstrip-btn" title="New file">＋</button>
    <div class="tabstrip-spacer"></div>
    <button id="homeBtn" class="tabstrip-btn" title="Start screen">⌂</button>
  </div>

  <!-- Editors mount into #workspace, one host element per open tab. The start
       screen lives inside it too, so it covers the editors but never the tab
       strip above them. -->
  <div id="workspace">

  <div id="start" class="start">
    <div class="start-inner">
      <div class="start-brand">
        <div class="start-logo">OF</div>
        <div>
          <h1>OfficeForger</h1>
          <p class="start-sub">Documents, spreadsheets and presentations — stored as files on this
            machine. Nothing is uploaded anywhere.</p>
        </div>
      </div>

      <div class="start-cards">
        <button class="start-card" data-new="doc">
          <span class="card-icon doc">▤</span>
          <span class="card-title">Document</span>
          <span class="card-sub">Letters, reports, notes</span>
          <span class="card-key">Ctrl+N</span>
        </button>
        <button class="start-card" data-new="sheet">
          <span class="card-icon sheet">▦</span>
          <span class="card-title">Spreadsheet</span>
          <span class="card-sub">Formulas, budgets, tables</span>
          <span class="card-key">Ctrl+Shift+N</span>
        </button>
        <button class="start-card" data-new="slide">
          <span class="card-icon slide">▭</span>
          <span class="card-title">Presentation</span>
          <span class="card-sub">Slides and speaker view</span>
          <span class="card-key">Ctrl+Alt+N</span>
        </button>
      </div>

      <div class="start-row">
        <button id="openBtn" class="btn btn-primary">Open a file…</button>
        <span class="start-hint">or drop a file anywhere on this window</span>
      </div>

      <div class="start-recent">
        <div class="start-recent-head">
          <h2>Recent</h2>
          <button id="clearRecentBtn" class="linkbtn">Clear</button>
        </div>
        <ul id="recentList" class="recent-list"></ul>
      </div>

      <div class="start-foot">
        <span id="versionLabel"></span>
      </div>
    </div>
  </div>

  </div><!-- /#workspace -->

  <div id="statusbar">
    <span id="statusLeft"></span>
    <span id="statusRight"></span>
  </div>
</div>

<!-- Toast notifications -->
<div id="toasts"></div>

<!-- Generic modal host -->
<div id="modalBackdrop" class="modal-backdrop hidden">
  <div id="modal" class="modal" role="dialog" aria-modal="true"></div>
</div>

<script src="formula.js"></script>
<script src="ui.js"></script>
<script src="docs.js"></script>
<script src="sheets.js"></script>
<script src="slides.js"></script>
<script src="app.js"></script>
</body>
</html>
'use strict';
/*
 * OfficeForger — the spreadsheet.
 *
 * Cells hold exactly what was typed. Everything else — the number, the date, the
 * formula result, the displayed string — is derived. That is the rule that keeps
 * round-tripping honest: what you saved is what you typed.
 *
 * Recalculation is a full pass with memoisation and cycle detection. On a grid of
 * this size that is microseconds, and it removes a whole class of stale-value bugs
 * that an incremental dependency graph would otherwise let through.
 */
(function (global) {
  const F = global.Formula;
  const { el, tbtn, sep, spacer, toast, form, confirm, menu, swatchButton, escapeHtml, ICONS } = global.UI;

  const DEF_COL_W = 92;
  const DEF_ROW_H = 22;
  const HEAD_W = 46;
  const MIN_ROWS = 100;
  const MIN_COLS = 26;
  const MAX_ROWS = 20000;
  const MAX_COLS = 300;

  const FORMATS = [
    { value: 'general', label: 'Automatic' },
    { value: 'int', label: 'Number (0)' },
    { value: 'number', label: 'Number (0.00)' },
    { value: 'currency', label: 'Currency' },
    { value: 'percent', label: 'Percent' },
    { value: 'sci', label: 'Scientific' },
    { value: 'date', label: 'Date' },
    { value: 'datetime', label: 'Date & time' },
    { value: 'text', label: 'Plain text' },
  ];

  const key = (c, r) => c + ',' + r;

  // ---- value display --------------------------------------------------------
  function group(s) {
    const neg = s.startsWith('-');
    if (neg) s = s.slice(1);
    const [int, dec] = s.split('.');
    return (neg ? '-' : '') + int.replace(/\B(?=(\d{3})+(?!\d))/g, ',') + (dec ? '.' + dec : '');
  }

  function fmtDate(serial, withTime) {
    const d = F.serialToDate(serial);
    const p2 = (n) => String(n).padStart(2, '0');
    const date = `${p2(d.getUTCMonth() + 1)}/${p2(d.getUTCDate())}/${d.getUTCFullYear()}`;
    if (!withTime) return date;
    const frac = serial - Math.floor(serial);
    const mins = Math.round(frac * 1440);
    let h = Math.floor(mins / 60);
    const m = mins % 60;
    const ampm = h < 12 ? 'AM' : 'PM';
    h = h % 12 || 12;
    return `${date} ${h}:${p2(m)} ${ampm}`;
  }

  function displayValue(v, fmt) {
    if (v === null || v === undefined || v === '') return '';
    if (F.isErr(v)) return v.code;
    if (typeof v === 'boolean') return v ? 'TRUE' : 'FALSE';
    if (typeof v === 'number') {
      if (!isFinite(v)) return '#NUM!';
      switch (fmt) {
        case 'int': return group(Math.round(v).toFixed(0));
        case 'number': return group(v.toFixed(2));
        case 'currency': return (v < 0 ? '-' : '') + '$' + group(Math.abs(v).toFixed(2));
        case 'percent': return group((v * 100).toFixed(2)) + '%';
        case 'sci': return v.toExponential(2);
        case 'date': return fmtDate(v, false);
        case 'datetime': return fmtDate(v, true);
        case 'text': return F.formatNumberPlain(v);
        default: {
          const a = Math.abs(v);
          if (a !== 0 && (a >= 1e12 || a < 1e-9)) return v.toExponential(4).replace(/e([+-])(\d)$/, 'e$10$2');
          return F.formatNumberPlain(v);
        }
      }
    }
    return String(v);
  }

  /** What a bare typed string means: number, percent, currency, date, bool, text. */
  function interpretInput(text) {
    const t = String(text).trim();
    if (t === '') return { v: '' };
    if (t[0] === '=') return { v: t };
    if (/^(TRUE|FALSE)$/i.test(t)) return { v: t.toUpperCase() };

    // Anything the user forces to text with a leading apostrophe stays text.
    if (t[0] === "'") return { v: t, fmt: 'text' };

    const pct = /^-?\$?[\d,]*\.?\d+\s*%$/.test(t);
    const cur = /^-?\$[\d,]*\.?\d+$/.test(t) || /^\$-[\d,]*\.?\d+$/.test(t);
    const plain = /^-?[\d,]*\.?\d+(e[+-]?\d+)?$/i.test(t) && /\d/.test(t);

    if (pct) {
      const n = parseFloat(t.replace(/[$,%\s]/g, ''));
      return { v: String(n / 100), fmt: 'percent' };
    }
    if (cur) {
      const n = parseFloat(t.replace(/[$,]/g, ''));
      return { v: String(n), fmt: 'currency' };
    }
    if (plain) {
      const n = parseFloat(t.replace(/,/g, ''));
      // "1,234" is a number; "1,2,3" is not, so only accept a clean round-trip.
      if (!isNaN(n)) return { v: t.includes(',') ? String(n) : t };
    }

    // Dates: M/D/YYYY and YYYY-MM-DD only. Ambiguous input stays text on purpose.
    let m = /^(\d{1,2})[/](\d{1,2})[/](\d{4})$/.exec(t);
    if (m) {
      const serial = F.dateToSerial(new Date(+m[3], +m[1] - 1, +m[2]));
      return { v: String(serial), fmt: 'date' };
    }
    m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(t);
    if (m) {
      const serial = F.dateToSerial(new Date(+m[1], +m[2] - 1, +m[3]));
      return { v: String(serial), fmt: 'date' };
    }

    return { v: text };
  }

  // ---- sheet model ----------------------------------------------------------
  function newSheet(name) {
    return { name, cells: {}, colW: {}, rowH: {}, rows: MIN_ROWS, cols: MIN_COLS, charts: [] };
  }

  class SheetEditor {
    static get kind() { return 'sheet'; }
    static get ext() { return 'ofsheet'; }
    static get label() { return 'Spreadsheet'; }
    static get icon() { return '▦'; }

    static newData() {
      return { sheets: [newSheet('Sheet1')], active: 0 };
    }

    /** Build a spreadsheet from parsed CSV rows. */
    static fromRows(rows) {
      const data = SheetEditor.newData();
      const sh = data.sheets[0];
      sh.rows = Math.max(MIN_ROWS, rows.length + 20);
      sh.cols = Math.max(MIN_COLS, Math.max(...rows.map((r) => r.length), 1) + 4);
      rows.forEach((row, r) => {
        row.forEach((val, c) => {
          if (val === '' || val === null || val === undefined) return;
          const parsed = interpretInput(val);
          if (parsed.v === '') return;
          sh.cells[key(c, r)] = parsed.fmt ? { v: parsed.v, s: { fmt: parsed.fmt } } : { v: parsed.v };
        });
      });
      return data;
    }

    constructor(host, data, ctx) {
      this.host = host;
      this.ctx = ctx;
      this.data = data && data.sheets && data.sheets.length ? data : SheetEditor.newData();
      this.data.sheets.forEach((s) => {
        s.cells = s.cells || {};
        s.colW = s.colW || {};
        s.rowH = s.rowH || {};
        s.charts = s.charts || [];
        s.rows = Math.max(MIN_ROWS, s.rows || MIN_ROWS);
        s.cols = Math.max(MIN_COLS, s.cols || MIN_COLS);
      });
      this.si = Math.min(this.data.active || 0, this.data.sheets.length - 1);

      this.cur = { c: 0, r: 0 };
      this.anchor = { c: 0, r: 0 };
      this.editing = null;
      this.astCache = new Map();
      this.computed = new Map();
      this.visiting = new Set();
      this.undoStack = [];
      this.redoStack = [];
      this.clip = null;
      this.find = { term: '', matches: [], index: -1 };

      this.build();
    }

    get sheet() { return this.data.sheets[this.si]; }

    // ---- construction -------------------------------------------------------
    build() {
      this.host.appendChild(this.buildToolbar());
      this.host.appendChild(this.buildFormulaBar());

      this.gridWrap = el('div', { class: 'grid-wrap', tabindex: '0' });
      this.host.appendChild(this.gridWrap);

      this.tabsBar = el('div', { class: 'sheet-tabs' });
      this.host.appendChild(this.tabsBar);

      this.gridWrap.addEventListener('mousedown', (e) => this.onGridMouseDown(e));
      this.gridWrap.addEventListener('dblclick', (e) => this.onGridDblClick(e));
      this.gridWrap.addEventListener('contextmenu', (e) => this.onContextMenu(e));
      this.gridWrap.addEventListener('keydown', (e) => this.onKeyDown(e));
      this.gridWrap.addEventListener('copy', (e) => this.onCopy(e, false));
      this.gridWrap.addEventListener('cut', (e) => this.onCopy(e, true));
      this.gridWrap.addEventListener('paste', (e) => this.onPaste(e));

      this.renderGrid();
      this.renderTabs();
    }

    buildToolbar() {
      const bar = el('div', { class: 'toolbar' });

      bar.appendChild(tbtn({ html: ICONS.undo, title: 'Undo (Ctrl+Z)', onClick: () => this.undo() }));
      bar.appendChild(tbtn({ html: ICONS.redo, title: 'Redo (Ctrl+Y)', onClick: () => this.redo() }));
      bar.appendChild(sep());

      this.fmtSel = el('select', {
        class: 'tsel', style: { width: '124px' }, title: 'Number format',
        onchange: (e) => this.styleRange({ fmt: e.target.value }),
      }, FORMATS.map((f) => el('option', { value: f.value, text: f.label })));
      bar.appendChild(this.fmtSel);
      bar.appendChild(tbtn({ html: '$', title: 'Currency', onClick: () => this.styleRange({ fmt: 'currency' }) }));
      bar.appendChild(tbtn({ html: '%', title: 'Percent', onClick: () => this.styleRange({ fmt: 'percent' }) }));
      bar.appendChild(tbtn({ html: ICONS.decimalMore, title: 'More decimal places', onClick: () => this.bumpDecimals(1) }));
      bar.appendChild(tbtn({ html: ICONS.decimalLess, title: 'Fewer decimal places', onClick: () => this.bumpDecimals(-1) }));
      bar.appendChild(sep());

      this.btnBold = tbtn({ html: '<b>B</b>', title: 'Bold (Ctrl+B)', onClick: () => this.toggleStyle('b') });
      this.btnItalic = tbtn({ html: '<i>I</i>', title: 'Italic (Ctrl+I)', onClick: () => this.toggleStyle('i') });
      this.btnUnder = tbtn({ html: '<u>U</u>', title: 'Underline (Ctrl+U)', onClick: () => this.toggleStyle('u') });
      bar.append(this.btnBold, this.btnItalic, this.btnUnder);

      bar.appendChild(swatchButton({
        icon: 'A', title: 'Text colour', color: '#000000',
        allowNone: true, noneLabel: 'Default',
        onPick: (c) => this.styleRange({ fg: c }),
      }));
      bar.appendChild(swatchButton({
        icon: '▮', title: 'Fill colour', color: '#ffe599',
        allowNone: true, noneLabel: 'No fill',
        onPick: (c) => this.styleRange({ bg: c }),
      }));
      bar.appendChild(sep());

      bar.appendChild(tbtn({ html: ICONS.alignLeft, title: 'Align left', onClick: () => this.styleRange({ a: 'left' }) }));
      bar.appendChild(tbtn({ html: ICONS.alignCenter, title: 'Centre', onClick: () => this.styleRange({ a: 'center' }) }));
      bar.appendChild(tbtn({ html: ICONS.alignRight, title: 'Align right', onClick: () => this.styleRange({ a: 'right' }) }));
      bar.appendChild(tbtn({ html: ICONS.clearFormat, title: 'Clear formatting', onClick: () => this.clearFormatting() }));
      bar.appendChild(sep());

      bar.appendChild(tbtn({ html: ICONS.sum, title: 'Sum the range above or to the left', onClick: () => this.autoSum() }));
      bar.appendChild(tbtn({ html: ICONS.sort, title: 'Sort the selected range', onClick: () => this.sortDialog() }));
      bar.appendChild(tbtn({ html: ICONS.chart, title: 'Insert chart from the selection', onClick: () => this.insertChart() }));

      bar.appendChild(spacer());
      bar.appendChild(tbtn({ html: ICONS.find, title: 'Find (Ctrl+F)', onClick: () => this.openFind() }));
      return bar;
    }

    buildFormulaBar() {
      const wrap = el('div', { class: 'sheet-formulabar' });
      this.nameBox = el('input', {
        class: 'namebox', title: 'Go to a cell or range',
        onkeydown: (e) => {
          if (e.key !== 'Enter') return;
          const ref = F.parseA1(this.nameBox.value.trim().toUpperCase());
          if (ref) {
            this.growTo(ref.col, ref.row);
            this.setCursor(ref.col, ref.row, false);
            this.gridWrap.focus();
          } else {
            this.syncBars();
          }
        },
      });
      this.fx = el('input', {
        class: 'fx-input', spellcheck: 'false', placeholder: 'Enter a value or a formula starting with =',
        onkeydown: (e) => {
          if (e.key === 'Enter') {
            e.preventDefault();
            this.commitInput(this.fx.value);
            this.moveCursor(0, 1, false);
            this.gridWrap.focus();
          } else if (e.key === 'Escape') {
            e.preventDefault();
            this.syncBars();
            this.gridWrap.focus();
          }
        },
      });
      wrap.append(this.nameBox, el('div', { class: 'fx-label', text: 'fx' }), this.fx);
      return wrap;
    }

    // ---- grid rendering -----------------------------------------------------
    renderGrid() {
      const sh = this.sheet;
      const scrollTop = this.gridWrap.scrollTop;
      const scrollLeft = this.gridWrap.scrollLeft;

      this.gridWrap.innerHTML = '';
      const table = el('table', { class: 'grid' });

      const colgroup = el('colgroup');
      colgroup.appendChild(el('col', { style: { width: HEAD_W + 'px' } }));
      for (let c = 0; c < sh.cols; c++) {
        colgroup.appendChild(el('col', { style: { width: (sh.colW[c] || DEF_COL_W) + 'px' } }));
      }
      table.appendChild(colgroup);

      const thead = el('thead');
      const hrow = el('tr');
      hrow.appendChild(el('th', { class: 'corner' }));
      for (let c = 0; c < sh.cols; c++) {
        hrow.appendChild(el('th', { text: F.indexToCol(c), dataset: { col: c } }));
      }
      thead.appendChild(hrow);
      table.appendChild(thead);

      const tbody = el('tbody');
      this.tds = [];
      for (let r = 0; r < sh.rows; r++) {
        const tr = el('tr', { style: { height: (sh.rowH[r] || DEF_ROW_H) + 'px' } });
        tr.appendChild(el('th', { class: 'rowhead', text: String(r + 1), dataset: { row: r } }));
        const rowCells = [];
        for (let c = 0; c < sh.cols; c++) {
          const td = el('td', { dataset: { col: c, row: r } });
          tr.appendChild(td);
          rowCells.push(td);
        }
        this.tds.push(rowCells);
        tbody.appendChild(tr);
      }
      table.appendChild(tbody);
      this.table = table;
      this.gridWrap.appendChild(table);

      this.chartLayer = el('div', { style: { position: 'absolute', top: 0, left: 0 } });
      this.gridWrap.appendChild(this.chartLayer);

      this.recalc();
      this.paintSelection();
      this.renderCharts();
      this.gridWrap.scrollTop = scrollTop;
      this.gridWrap.scrollLeft = scrollLeft;
    }

    /** Recompute every cell and write the results into the DOM. */
    recalc() {
      this.computed.clear();
      this.visiting.clear();
      const sh = this.sheet;

      for (let r = 0; r < sh.rows; r++) {
        for (let c = 0; c < sh.cols; c++) {
          const td = this.tds[r] && this.tds[r][c];
          if (!td) continue;
          const cell = sh.cells[key(c, r)];
          if (!cell) {
            if (td.firstChild || td.className) { td.textContent = ''; td.className = ''; td.removeAttribute('style'); }
            continue;
          }
          const value = this.valueAt(this.si, c, r);
          const st = cell.s || {};
          td.textContent = displayValue(value, st.fmt);

          let cls = '';
          if (F.isErr(value)) cls = 'err';
          else if (typeof value === 'number' && !st.a) cls = 'num';
          if (st.a === 'right') cls += (cls ? ' ' : '') + 'num';
          td.className = cls;

          const style = td.style;
          style.cssText = '';
          if (st.b) style.fontWeight = '700';
          if (st.i) style.fontStyle = 'italic';
          if (st.u) style.textDecoration = 'underline';
          if (st.fg) style.color = st.fg;
          if (st.bg) style.background = st.bg;
          if (st.a) style.textAlign = st.a;
        }
      }
      this.ctx.onStatus && this.ctx.onStatus();
    }

    /** The computed value of a cell, memoised, with circular references caught. */
    valueAt(sheetIndex, c, r) {
      const sh = this.data.sheets[sheetIndex];
      if (!sh) return F.ERR.ref();
      if (c < 0 || r < 0) return F.ERR.ref();
      const k = sheetIndex + ':' + key(c, r);
      if (this.computed.has(k)) return this.computed.get(k);

      const cell = sh.cells[key(c, r)];
      const raw = cell ? cell.v : '';
      if (raw === '' || raw === null || raw === undefined) {
        this.computed.set(k, null);
        return null;
      }

      if (typeof raw === 'string' && raw[0] === '=') {
        if (this.visiting.has(k)) {
          // Self-reference or a loop: stop here rather than blow the stack.
          const cyc = F.ERR.cycle();
          this.computed.set(k, cyc);
          return cyc;
        }
        this.visiting.add(k);
        let out;
        try {
          let ast = this.astCache.get(raw);
          if (!ast) {
            ast = F.parse(raw.slice(1));
            this.astCache.set(raw, ast);
          }
          out = F.scalar(F.evaluate(ast, this.evalContext(sheetIndex)));
        } catch (e) {
          out = F.isErr(e) ? e : F.ERR.parse();
        }
        this.visiting.delete(k);
        this.computed.set(k, out);
        return out;
      }

      // A literal. Stored as typed; interpreted here.
      const t = String(raw);
      let out;
      if (/^(TRUE|FALSE)$/i.test(t.trim())) out = /^TRUE$/i.test(t.trim());
      else if (t.trim() !== '' && /^-?\d*\.?\d+(e[+-]?\d+)?$/i.test(t.trim())) out = parseFloat(t.trim());
      else if (t[0] === "'") out = t.slice(1);
      else out = t;
      this.computed.set(k, out);
      return out;
    }

    evalContext(sheetIndex) {
      const self = this;
      const byName = (name) => self.data.sheets.findIndex((s) => s.name.toLowerCase() === String(name).toLowerCase());
      return {
        sheet: self.data.sheets[sheetIndex].name,
        hasSheet: (name) => byName(name) !== -1,
        getValue: (name, c, r) => {
          const idx = name ? byName(name) : sheetIndex;
          if (idx === -1) return F.ERR.ref();
          return self.valueAt(idx, c, r);
        },
      };
    }

    // ---- selection ----------------------------------------------------------
    range() {
      return {
        c1: Math.min(this.cur.c, this.anchor.c),
        c2: Math.max(this.cur.c, this.anchor.c),
        r1: Math.min(this.cur.r, this.anchor.r),
        r2: Math.max(this.cur.r, this.anchor.r),
      };
    }
    forEachInRange(fn) {
      const { c1, c2, r1, r2 } = this.range();
      for (let r = r1; r <= r2; r++) for (let c = c1; c <= c2; c++) fn(c, r);
    }

    paintSelection() {
      if (this.lastPaint) {
        for (const td of this.lastPaint) td.classList.remove('in-range', 'cursor');
      }
      const touched = [];
      const { c1, c2, r1, r2 } = this.range();
      for (let r = r1; r <= r2; r++) {
        for (let c = c1; c <= c2; c++) {
          const td = this.tds[r] && this.tds[r][c];
          if (!td) continue;
          td.classList.add('in-range');
          touched.push(td);
        }
      }
      const cur = this.tds[this.cur.r] && this.tds[this.cur.r][this.cur.c];
      if (cur) {
        cur.classList.add('cursor');
        touched.push(cur);
      }
      this.lastPaint = touched;

      // Header highlighting for the selected columns and rows.
      if (this.lastHeads) for (const th of this.lastHeads) th.classList.remove('selected-head');
      const heads = [];
      const headRow = this.table.tHead.rows[0];
      for (let c = c1; c <= c2; c++) {
        const th = headRow.cells[c + 1];
        if (th) { th.classList.add('selected-head'); heads.push(th); }
      }
      for (let r = r1; r <= r2; r++) {
        const th = this.table.tBodies[0].rows[r] && this.table.tBodies[0].rows[r].cells[0];
        if (th) { th.classList.add('selected-head'); heads.push(th); }
      }
      this.lastHeads = heads;

      this.syncBars();
      this.scrollIntoView();
      this.ctx.onStatus && this.ctx.onStatus();
    }

    setCursor(c, r, extend) {
      this.cur = { c: Math.max(0, c), r: Math.max(0, r) };
      if (!extend) this.anchor = { ...this.cur };
      this.paintSelection();
    }

    moveCursor(dc, dr, extend) {
      let c = this.cur.c + dc;
      let r = this.cur.r + dr;
      if (c < 0) c = 0;
      if (r < 0) r = 0;
      // Walking off the edge grows the sheet, so there is never a hard wall.
      this.growTo(c, r);
      this.setCursor(c, r, extend);
    }

    growTo(c, r) {
      const sh = this.sheet;
      let grew = false;
      if (r >= sh.rows && sh.rows < MAX_ROWS) { sh.rows = Math.min(MAX_ROWS, r + 40); grew = true; }
      if (c >= sh.cols && sh.cols < MAX_COLS) { sh.cols = Math.min(MAX_COLS, c + 8); grew = true; }
      if (grew) this.renderGrid();
      return grew;
    }

    scrollIntoView() {
      const td = this.tds[this.cur.r] && this.tds[this.cur.r][this.cur.c];
      if (!td) return;
      const w = this.gridWrap;
      const headH = this.table.tHead.getBoundingClientRect().height || 22;
      const top = td.offsetTop;
      const left = td.offsetLeft;
      if (top - headH < w.scrollTop) w.scrollTop = Math.max(0, top - headH);
      else if (top + td.offsetHeight > w.scrollTop + w.clientHeight) w.scrollTop = top + td.offsetHeight - w.clientHeight;
      if (left - HEAD_W < w.scrollLeft) w.scrollLeft = Math.max(0, left - HEAD_W);
      else if (left + td.offsetWidth > w.scrollLeft + w.clientWidth) w.scrollLeft = left + td.offsetWidth - w.clientWidth;
    }

    syncBars() {
      const { c1, c2, r1, r2 } = this.range();
      this.nameBox.value = c1 === c2 && r1 === r2
        ? F.a1(this.cur.c, this.cur.r)
        : `${F.a1(c1, r1)}:${F.a1(c2, r2)}`;
      const cell = this.sheet.cells[key(this.cur.c, this.cur.r)];
      if (document.activeElement !== this.fx) this.fx.value = cell ? cell.v : '';
      const st = (cell && cell.s) || {};
      this.btnBold.classList.toggle('on', !!st.b);
      this.btnItalic.classList.toggle('on', !!st.i);
      this.btnUnder.classList.toggle('on', !!st.u);
      this.fmtSel.value = st.fmt || 'general';
    }

    // ---- mutation & undo ----------------------------------------------------
    snapshot() {
      this.undoStack.push(JSON.stringify({ sheets: this.data.sheets, active: this.si }));
      if (this.undoStack.length > 60) this.undoStack.shift();
      this.redoStack.length = 0;
    }

    restore(json) {
      const state = JSON.parse(json);
      this.data.sheets = state.sheets;
      this.si = Math.min(state.active || 0, this.data.sheets.length - 1);
      this.astCache.clear();
      this.cur = { c: Math.min(this.cur.c, this.sheet.cols - 1), r: Math.min(this.cur.r, this.sheet.rows - 1) };
      this.anchor = { ...this.cur };
      this.renderGrid();
      this.renderTabs();
      this.ctx.onChange();
    }

    undo() {
      if (!this.undoStack.length) return;
      this.redoStack.push(JSON.stringify({ sheets: this.data.sheets, active: this.si }));
      this.restore(this.undoStack.pop());
    }
    redo() {
      if (!this.redoStack.length) return;
      this.undoStack.push(JSON.stringify({ sheets: this.data.sheets, active: this.si }));
      this.restore(this.redoStack.pop());
    }

    /** Write a raw value into a cell, keeping any style it already had. */
    setRaw(c, r, raw, fmt) {
      const sh = this.sheet;
      const k = key(c, r);
      const existing = sh.cells[k];
      if (raw === '' || raw === null || raw === undefined) {
        if (existing && existing.s && Object.keys(existing.s).length) existing.v = '';
        else delete sh.cells[k];
      } else {
        const cell = existing || {};
        cell.v = raw;
        if (fmt) cell.s = Object.assign(cell.s || {}, { fmt });
        sh.cells[k] = cell;
      }
    }

    commitInput(text) {
      this.snapshot();
      const parsed = interpretInput(text);
      this.setRaw(this.cur.c, this.cur.r, parsed.v, parsed.fmt);
      this.afterEdit();
    }

    afterEdit() {
      this.astCache.clear();
      this.recalc();
      this.paintSelection();
      this.renderCharts();
      this.ctx.onChange();
    }

    // ---- cell editing -------------------------------------------------------
    beginEdit(seed) {
      if (this.editing) return;
      const td = this.tds[this.cur.r] && this.tds[this.cur.r][this.cur.c];
      if (!td) return;
      const cell = this.sheet.cells[key(this.cur.c, this.cur.r)];
      const input = el('input', { class: 'cell-editor', spellcheck: 'false' });
      input.style.left = td.offsetLeft + 'px';
      input.style.top = td.offsetTop + 'px';
      input.style.width = Math.max(td.offsetWidth, 90) + 'px';
      input.style.height = td.offsetHeight + 'px';
      input.value = seed !== undefined && seed !== null ? seed : (cell ? cell.v : '');

      this.gridWrap.appendChild(input);
      this.editing = { input, c: this.cur.c, r: this.cur.r };
      input.focus();
      if (seed === undefined || seed === null) input.select();
      else input.setSelectionRange(input.value.length, input.value.length);

      input.addEventListener('input', () => { this.fx.value = input.value; });
      input.addEventListener('keydown', (e) => {
        if (e.key === 'Enter') {
          e.preventDefault();
          this.endEdit(true);
          this.moveCursor(0, e.shiftKey ? -1 : 1, false);
        } else if (e.key === 'Tab') {
          e.preventDefault();
          this.endEdit(true);
          this.moveCursor(e.shiftKey ? -1 : 1, 0, false);
        } else if (e.key === 'Escape') {
          e.preventDefault();
          this.endEdit(false);
        }
        e.stopPropagation();
      });
      input.addEventListener('blur', () => { if (this.editing) this.endEdit(true); });
    }

    endEdit(commit) {
      if (!this.editing) return;
      const { input, c, r } = this.editing;
      this.editing = null;
      const value = input.value;
      input.remove();
      this.gridWrap.focus();
      if (!commit) { this.syncBars(); return; }
      this.snapshot();
      const parsed = interpretInput(value);
      this.setRaw(c, r, parsed.v, parsed.fmt);
      this.afterEdit();
    }

    // ---- mouse --------------------------------------------------------------
    onGridMouseDown(e) {
      if (e.button === 2) return; // context menu handles its own selection

      const th = e.target.closest('th');
      if (th) {
        this.onHeaderMouseDown(e, th);
        return;
      }
      const td = e.target.closest('td');
      if (!td) return;

      if (this.editing) this.endEdit(true);

      const c = +td.dataset.col;
      const r = +td.dataset.row;

      // The fill handle lives in the bottom-right corner of the cursor cell.
      const isCursor = c === this.cur.c && r === this.cur.r;
      if (isCursor && e.offsetX > td.clientWidth - 7 && e.offsetY > td.clientHeight - 7) {
        e.preventDefault();
        this.startFillDrag();
        return;
      }

      this.gridWrap.focus();
      this.setCursor(c, r, e.shiftKey);

      if (e.shiftKey) return;
      // Drag to extend the selection.
      const move = (ev) => {
        const over = document.elementFromPoint(ev.clientX, ev.clientY);
        const cell = over && over.closest && over.closest('td');
        if (cell && cell.dataset.col !== undefined) {
          const nc = +cell.dataset.col, nr = +cell.dataset.row;
          if (nc !== this.cur.c || nr !== this.cur.r) this.setCursor(nc, nr, true);
        }
      };
      const up = () => {
        document.removeEventListener('mousemove', move);
        document.removeEventListener('mouseup', up);
      };
      document.addEventListener('mousemove', move);
      document.addEventListener('mouseup', up);
    }

    onHeaderMouseDown(e, th) {
      const isCol = th.dataset.col !== undefined;
      const isRow = th.dataset.row !== undefined;
      if (!isCol && !isRow) return;

      const rect = th.getBoundingClientRect();
      // The last few pixels of a header are the resize grip.
      if (isCol && rect.right - e.clientX < 5) { this.startColResize(+th.dataset.col, e); return; }
      if (isRow && rect.bottom - e.clientY < 5) { this.startRowResize(+th.dataset.row, e); return; }

      this.gridWrap.focus();
      const sh = this.sheet;
      if (isCol) {
        const c = +th.dataset.col;
        this.anchor = { c, r: 0 };
        this.cur = { c, r: sh.rows - 1 };
        if (e.shiftKey) this.anchor = { c: this.anchor.c, r: 0 };
      } else {
        const r = +th.dataset.row;
        this.anchor = { c: 0, r };
        this.cur = { c: sh.cols - 1, r };
      }
      this.paintSelection();
      // Selecting a whole column puts the cursor at its top for typing.
      if (isCol) { this.cur = { c: +th.dataset.col, r: sh.rows - 1 }; }
    }

    startColResize(c, e) {
      const sh = this.sheet;
      const startX = e.clientX;
      const startW = sh.colW[c] || DEF_COL_W;
      const col = this.table.querySelector('colgroup').children[c + 1];
      const move = (ev) => {
        const w = Math.max(28, startW + ev.clientX - startX);
        col.style.width = w + 'px';
      };
      const up = (ev) => {
        document.removeEventListener('mousemove', move);
        document.removeEventListener('mouseup', up);
        const w = Math.max(28, startW + ev.clientX - startX);
        if (w !== startW) {
          this.snapshot();
          sh.colW[c] = w;
          this.ctx.onChange();
        }
      };
      document.addEventListener('mousemove', move);
      document.addEventListener('mouseup', up);
      e.preventDefault();
    }

    startRowResize(r, e) {
      const sh = this.sheet;
      const startY = e.clientY;
      const startH = sh.rowH[r] || DEF_ROW_H;
      const tr = this.table.tBodies[0].rows[r];
      const move = (ev) => { tr.style.height = Math.max(16, startH + ev.clientY - startY) + 'px'; };
      const up = (ev) => {
        document.removeEventListener('mousemove', move);
        document.removeEventListener('mouseup', up);
        const h = Math.max(16, startH + ev.clientY - startY);
        if (h !== startH) {
          this.snapshot();
          sh.rowH[r] = h;
          this.ctx.onChange();
        }
      };
      document.addEventListener('mousemove', move);
      document.addEventListener('mouseup', up);
      e.preventDefault();
    }

    onGridDblClick(e) {
      const td = e.target.closest('td');
      if (!td) return;
      this.setCursor(+td.dataset.col, +td.dataset.row, false);
      this.beginEdit();
    }

    // ---- fill handle --------------------------------------------------------
    startFillDrag() {
      const src = this.range();
      let preview = [];
      const clearPreview = () => {
        for (const td of preview) td.classList.remove('fill-preview');
        preview = [];
      };
      const move = (ev) => {
        const over = document.elementFromPoint(ev.clientX, ev.clientY);
        const cell = over && over.closest && over.closest('td');
        if (!cell || cell.dataset.col === undefined) return;
        clearPreview();
        const c = +cell.dataset.col, r = +cell.dataset.row;
        const target = fillTarget(src, c, r);
        for (let rr = target.r1; rr <= target.r2; rr++) {
          for (let cc = target.c1; cc <= target.c2; cc++) {
            const td = this.tds[rr] && this.tds[rr][cc];
            if (td) { td.classList.add('fill-preview'); preview.push(td); }
          }
        }
        this.pendingFill = target;
      };
      const up = () => {
        document.removeEventListener('mousemove', move);
        document.removeEventListener('mouseup', up);
        clearPreview();
        if (this.pendingFill) {
          this.applyFill(src, this.pendingFill);
          this.pendingFill = null;
        }
      };
      document.addEventListener('mousemove', move);
      document.addEventListener('mouseup', up);
    }

    /**
     * Fill the target area from the source range: formulas shift their relative
     * references, and a run of numbers or dates continues as a series.
     */
    applyFill(src, target) {
      if (target.c1 === src.c1 && target.c2 === src.c2 && target.r1 === src.r1 && target.r2 === src.r2) return;
      this.snapshot();
      const sh = this.sheet;
      const srcH = src.r2 - src.r1 + 1;
      const srcW = src.c2 - src.c1 + 1;

      // Series detection down a single column (or across a single row).
      const vertical = target.r2 > src.r2 || target.r1 < src.r1;
      // A series only makes sense along a single line; a 2-D block is a tiled copy.
      const singleLine = vertical ? srcW === 1 : srcH === 1;
      const step = singleLine ? this.detectStep(src, vertical) : null;
      // The series continues from the FIRST cell of the source, not from whichever
      // cell the modulo happens to land on — otherwise 1,2,3 fills as 4,4,6,6.
      let seriesBase = null;
      if (step !== null) {
        const first = sh.cells[key(src.c1, src.r1)];
        const n = first ? parseFloat(first.v) : NaN;
        seriesBase = isNaN(n) ? null : n;
      }

      for (let r = target.r1; r <= target.r2; r++) {
        for (let c = target.c1; c <= target.c2; c++) {
          if (r >= src.r1 && r <= src.r2 && c >= src.c1 && c <= src.c2) continue;
          const sc = src.c1 + ((((c - src.c1) % srcW) + srcW) % srcW);
          const sr = src.r1 + ((((r - src.r1) % srcH) + srcH) % srcH);
          const source = sh.cells[key(sc, sr)];
          if (!source) { delete sh.cells[key(c, r)]; continue; }

          const clone = { v: source.v };
          if (source.s) clone.s = JSON.parse(JSON.stringify(source.s));

          if (typeof source.v === 'string' && source.v[0] === '=') {
            clone.v = F.offsetFormula(source.v, c - sc, r - sr);
          } else if (seriesBase !== null) {
            const offset = vertical ? r - src.r1 : c - src.c1;
            clone.v = String(Math.round((seriesBase + step * offset) * 1e9) / 1e9);
          }
          sh.cells[key(c, r)] = clone;
        }
      }
      this.cur = { c: target.c2, r: target.r2 };
      this.anchor = { c: target.c1, r: target.r1 };
      this.afterEdit();
    }

    /** The increment of a numeric series in the source range, or null. */
    detectStep(src, vertical) {
      const sh = this.sheet;
      const values = [];
      if (vertical) {
        for (let r = src.r1; r <= src.r2; r++) {
          const cell = sh.cells[key(src.c1, r)];
          const n = cell && typeof cell.v === 'string' && cell.v[0] !== '=' ? parseFloat(cell.v) : NaN;
          values.push(n);
        }
      } else {
        for (let c = src.c1; c <= src.c2; c++) {
          const cell = sh.cells[key(c, src.r1)];
          const n = cell && typeof cell.v === 'string' && cell.v[0] !== '=' ? parseFloat(cell.v) : NaN;
          values.push(n);
        }
      }
      if (values.some(isNaN)) return null;
      // One cell is a copy, not a series — same as Excel and Sheets. Two or more
      // cells with a constant difference is what makes it a series.
      if (values.length < 2) return null;
      const step = values[1] - values[0];
      for (let i = 2; i < values.length; i++) {
        if (Math.abs(values[i] - values[i - 1] - step) > 1e-9) return null;
      }
      return step;
    }

    // ---- keyboard -----------------------------------------------------------
    onKeyDown(e) {
      if (this.editing) return;
      const ctrl = e.ctrlKey || e.metaKey;

      if (ctrl) {
        const k = e.key.toLowerCase();
        if (k === 'b') { e.preventDefault(); this.toggleStyle('b'); return; }
        if (k === 'i') { e.preventDefault(); this.toggleStyle('i'); return; }
        if (k === 'u') { e.preventDefault(); this.toggleStyle('u'); return; }
        if (k === 'z') { e.preventDefault(); this.undo(); return; }
        if (k === 'y') { e.preventDefault(); this.redo(); return; }
        if (k === 'f') { e.preventDefault(); this.openFind(); return; }
        if (k === 'a') {
          e.preventDefault();
          this.anchor = { c: 0, r: 0 };
          this.cur = { c: this.sheet.cols - 1, r: this.sheet.rows - 1 };
          this.paintSelection();
          return;
        }
        if (k === 'arrowdown' || k === 'arrowup' || k === 'arrowleft' || k === 'arrowright') {
          e.preventDefault();
          this.jumpToEdge(k, e.shiftKey);
          return;
        }
        if (k === 'home') { e.preventDefault(); this.setCursor(0, 0, e.shiftKey); return; }
        if (k === ';') {
          e.preventDefault();
          this.snapshot();
          this.setRaw(this.cur.c, this.cur.r, String(F.dateToSerial(new Date())), 'date');
          this.afterEdit();
          return;
        }
        return; // let copy/paste and the rest through
      }

      switch (e.key) {
        case 'ArrowUp': e.preventDefault(); this.moveCursor(0, -1, e.shiftKey); return;
        case 'ArrowDown': e.preventDefault(); this.moveCursor(0, 1, e.shiftKey); return;
        case 'ArrowLeft': e.preventDefault(); this.moveCursor(-1, 0, e.shiftKey); return;
        case 'ArrowRight': e.preventDefault(); this.moveCursor(1, 0, e.shiftKey); return;
        case 'Tab': e.preventDefault(); this.moveCursor(e.shiftKey ? -1 : 1, 0, false); return;
        case 'Enter': e.preventDefault(); this.beginEdit(); return;
        case 'F2': e.preventDefault(); this.beginEdit(); return;
        case 'Home': e.preventDefault(); this.setCursor(0, this.cur.r, e.shiftKey); return;
        case 'End': e.preventDefault(); this.setCursor(this.lastUsedCol(this.cur.r), this.cur.r, e.shiftKey); return;
        case 'PageDown': e.preventDefault(); this.moveCursor(0, 25, e.shiftKey); return;
        case 'PageUp': e.preventDefault(); this.moveCursor(0, -25, e.shiftKey); return;
        case 'Delete':
        case 'Backspace':
          e.preventDefault();
          this.clearRange();
          return;
        case 'Escape':
          if (this.findBar) this.closeFind();
          return;
      }

      // A printable character starts editing with that character.
      if (e.key.length === 1 && !e.altKey) {
        e.preventDefault();
        this.beginEdit(e.key);
      }
    }

    lastUsedCol(r) {
      const sh = this.sheet;
      let last = 0;
      for (let c = 0; c < sh.cols; c++) if (sh.cells[key(c, r)]) last = c;
      return last;
    }

    /** Ctrl+arrow: jump to the end of the current block of filled cells. */
    jumpToEdge(dirKey, extend) {
      const sh = this.sheet;
      const d = { arrowup: [0, -1], arrowdown: [0, 1], arrowleft: [-1, 0], arrowright: [1, 0] }[dirKey];
      let [c, r] = [this.cur.c, this.cur.r];
      const filled = (cc, rr) => {
        const cell = sh.cells[key(cc, rr)];
        return !!(cell && cell.v !== '');
      };
      const limitC = sh.cols - 1, limitR = sh.rows - 1;
      const startFilled = filled(c, r);
      let steps = 0;
      while (steps++ < 20000) {
        const nc = c + d[0], nr = r + d[1];
        if (nc < 0 || nr < 0 || nc > limitC || nr > limitR) break;
        if (startFilled && !filled(nc, nr)) break;
        c = nc; r = nr;
        if (!startFilled && filled(c, r)) break;
      }
      this.setCursor(c, r, extend);
    }

    // ---- clipboard ----------------------------------------------------------
    onCopy(e, cut) {
      const { c1, c2, r1, r2 } = this.range();
      const sh = this.sheet;
      const rows = [];
      const cells = [];
      for (let r = r1; r <= r2; r++) {
        const line = [];
        const cellRow = [];
        for (let c = c1; c <= c2; c++) {
          const value = this.valueAt(this.si, c, r);
          const st = (sh.cells[key(c, r)] || {}).s;
          line.push(displayValue(value, st && st.fmt));
          const cell = sh.cells[key(c, r)];
          cellRow.push(cell ? JSON.parse(JSON.stringify(cell)) : null);
        }
        rows.push(line.join('\t'));
        cells.push(cellRow);
      }
      const text = rows.join('\n');
      e.clipboardData.setData('text/plain', text);
      e.preventDefault();
      // Kept alongside the text so an internal paste can carry formulas and
      // formatting; if the clipboard text changes, we fall back to the text.
      this.clip = { text, cells, c1, r1 };

      if (cut) {
        this.snapshot();
        this.forEachInRange((c, r) => delete sh.cells[key(c, r)]);
        this.afterEdit();
      }
    }

    onPaste(e) {
      const text = e.clipboardData.getData('text/plain');
      e.preventDefault();
      if (!text) return;
      this.snapshot();
      const sh = this.sheet;
      const target = { c: this.cur.c, r: this.cur.r };

      if (this.clip && this.clip.text === text) {
        // Internal paste: formulas shift, styles come along.
        const dc = target.c - this.clip.c1;
        const dr = target.r - this.clip.r1;
        this.clip.cells.forEach((row, ri) => {
          row.forEach((cell, ci) => {
            const c = this.clip.c1 + ci + dc;
            const r = this.clip.r1 + ri + dr;
            if (c < 0 || r < 0) return;
            this.growTo(c, r);
            if (!cell) { delete sh.cells[key(c, r)]; return; }
            const clone = { v: cell.v };
            if (cell.s) clone.s = JSON.parse(JSON.stringify(cell.s));
            if (typeof clone.v === 'string' && clone.v[0] === '=') clone.v = F.offsetFormula(clone.v, dc, dr);
            sh.cells[key(c, r)] = clone;
          });
        });
        const h = this.clip.cells.length, w = this.clip.cells[0] ? this.clip.cells[0].length : 1;
        this.anchor = { ...target };
        this.cur = { c: target.c + w - 1, r: target.r + h - 1 };
      } else {
        // External paste: TSV, or CSV if there are no tabs at all.
        const lines = text.replace(/\r\n?/g, '\n').replace(/\n$/, '').split('\n');
        const rows = text.includes('\t')
          ? lines.map((l) => l.split('\t'))
          : parseCSV(text);
        rows.forEach((row, ri) => {
          row.forEach((val, ci) => {
            const c = target.c + ci, r = target.r + ri;
            this.growTo(c, r);
            const parsed = interpretInput(val);
            this.setRaw(c, r, parsed.v, parsed.fmt);
          });
        });
        this.anchor = { ...target };
        this.cur = {
          c: target.c + Math.max(0, (rows[0] ? rows[0].length : 1) - 1),
          r: target.r + Math.max(0, rows.length - 1),
        };
      }
      this.afterEdit();
    }

    clearRange() {
      this.snapshot();
      const sh = this.sheet;
      let touched = false;
      this.forEachInRange((c, r) => {
        if (sh.cells[key(c, r)]) { delete sh.cells[key(c, r)]; touched = true; }
      });
      if (touched) this.afterEdit();
      else this.undoStack.pop();
    }

    // ---- formatting ---------------------------------------------------------
    styleRange(patch) {
      this.snapshot();
      const sh = this.sheet;
      this.forEachInRange((c, r) => {
        const k = key(c, r);
        const cell = sh.cells[k] || { v: '' };
        cell.s = Object.assign({}, cell.s);
        for (const [prop, value] of Object.entries(patch)) {
          if (value === null || value === undefined || value === false) delete cell.s[prop];
          else cell.s[prop] = value;
        }
        if (!Object.keys(cell.s).length) delete cell.s;
        if (cell.v === '' && !cell.s) delete sh.cells[k];
        else sh.cells[k] = cell;
      });
      this.afterEdit();
    }

    toggleStyle(prop) {
      const cur = this.sheet.cells[key(this.cur.c, this.cur.r)];
      const on = !!(cur && cur.s && cur.s[prop]);
      this.styleRange({ [prop]: on ? null : true });
    }

    clearFormatting() {
      this.snapshot();
      const sh = this.sheet;
      this.forEachInRange((c, r) => {
        const cell = sh.cells[key(c, r)];
        if (!cell) return;
        delete cell.s;
        if (cell.v === '') delete sh.cells[key(c, r)];
      });
      this.afterEdit();
    }

    /** Step the visible decimal places of the selection up or down. */
    bumpDecimals(dir) {
      const cur = this.sheet.cells[key(this.cur.c, this.cur.r)];
      const fmt = (cur && cur.s && cur.s.fmt) || 'general';
      const ladder = ['int', 'general', 'number'];
      let i = ladder.indexOf(fmt);
      if (i === -1) i = 1;
      const next = ladder[Math.max(0, Math.min(ladder.length - 1, i + dir))];
      this.styleRange({ fmt: next });
    }

    // ---- structure ----------------------------------------------------------
    /**
     * Insert or delete whole rows/columns: move every cell that sits after the
     * cut, then rewrite every formula in the workbook so its references still
     * point at the same data. Formulas on other sheets that reference this one
     * are rewritten too — that is the whole reason this walks all sheets.
     */
    spliceLines(kind, at, count, remove) {
      this.snapshot();
      const sh = this.sheet;
      const targetSheet = sh.name;
      const moved = {};
      for (const [k, cell] of Object.entries(sh.cells)) {
        const [c, r] = k.split(',').map(Number);
        let nc = c, nr = r;
        const pos = kind === 'row' ? r : c;
        if (remove) {
          if (pos >= at && pos < at + count) continue; // deleted
          if (pos >= at + count) { if (kind === 'row') nr -= count; else nc -= count; }
        } else if (pos >= at) {
          if (kind === 'row') nr += count; else nc += count;
        }
        moved[key(nc, nr)] = cell;
      }
      sh.cells = moved;

      const sizes = kind === 'row' ? sh.rowH : sh.colW;
      const movedSizes = {};
      for (const [k, v] of Object.entries(sizes)) {
        const pos = Number(k);
        if (remove) {
          if (pos >= at && pos < at + count) continue;
          movedSizes[pos >= at + count ? pos - count : pos] = v;
        } else {
          movedSizes[pos >= at ? pos + count : pos] = v;
        }
      }
      if (kind === 'row') sh.rowH = movedSizes; else sh.colW = movedSizes;

      if (kind === 'row') sh.rows = Math.max(MIN_ROWS, sh.rows + (remove ? -count : count));
      else sh.cols = Math.max(MIN_COLS, sh.cols + (remove ? -count : count));

      // Rewrite references across the whole workbook, not just this sheet.
      const opts = { axis: kind, at, count, remove, targetSheet };
      for (const other of this.data.sheets) {
        for (const cell of Object.values(other.cells)) {
          if (typeof cell.v === 'string' && cell.v[0] === '=') {
            cell.v = F.adjustFormula(cell.v, Object.assign({ formulaSheet: other.name }, opts));
          }
        }
      }

      // Charts point at ranges too, and a chart quietly plotting the wrong
      // columns after an insert is worse than one that visibly moved.
      const shiftPos = (pos) => {
        if (!remove) return pos >= at ? pos + count : pos;
        if (pos < at) return pos;
        if (pos < at + count) return at;
        return pos - count;
      };
      for (const chart of sh.charts) {
        if (kind === 'row') {
          chart.range.r1 = shiftPos(chart.range.r1);
          chart.range.r2 = shiftPos(chart.range.r2);
        } else {
          chart.range.c1 = shiftPos(chart.range.c1);
          chart.range.c2 = shiftPos(chart.range.c2);
        }
      }

      this.cur = { c: Math.min(this.cur.c, sh.cols - 1), r: Math.min(this.cur.r, sh.rows - 1) };
      this.anchor = { ...this.cur };
      this.astCache.clear();
      this.renderGrid();
      this.ctx.onChange();
    }

    onContextMenu(e) {
      e.preventDefault();
      const th = e.target.closest('th');
      const td = e.target.closest('td');

      if (th && th.dataset.col !== undefined) {
        const c = +th.dataset.col;
        const { c1, c2 } = this.range();
        const n = c >= c1 && c <= c2 ? c2 - c1 + 1 : 1;
        const at = c >= c1 && c <= c2 ? c1 : c;
        menu(e.clientX, e.clientY, [
          { label: `Insert ${n} column${n > 1 ? 's' : ''} left`, onClick: () => this.spliceLines('col', at, n, false) },
          { label: `Insert ${n} column${n > 1 ? 's' : ''} right`, onClick: () => this.spliceLines('col', at + n, n, false) },
          '-',
          { label: `Delete column${n > 1 ? 's' : ''}`, danger: true, onClick: () => this.spliceLines('col', at, n, true) },
          { label: 'Clear contents', onClick: () => this.clearRange() },
          '-',
          { label: 'Resize column…', onClick: () => this.resizeDialog('col', at) },
        ]);
        return;
      }
      if (th && th.dataset.row !== undefined) {
        const r = +th.dataset.row;
        const { r1, r2 } = this.range();
        const n = r >= r1 && r <= r2 ? r2 - r1 + 1 : 1;
        const at = r >= r1 && r <= r2 ? r1 : r;
        menu(e.clientX, e.clientY, [
          { label: `Insert ${n} row${n > 1 ? 's' : ''} above`, onClick: () => this.spliceLines('row', at, n, false) },
          { label: `Insert ${n} row${n > 1 ? 's' : ''} below`, onClick: () => this.spliceLines('row', at + n, n, false) },
          '-',
          { label: `Delete row${n > 1 ? 's' : ''}`, danger: true, onClick: () => this.spliceLines('row', at, n, true) },
          { label: 'Clear contents', onClick: () => this.clearRange() },
          '-',
          { label: 'Resize row…', onClick: () => this.resizeDialog('row', at) },
        ]);
        return;
      }
      if (td) {
        const c = +td.dataset.col, r = +td.dataset.row;
        const { c1, c2, r1, r2 } = this.range();
        if (c < c1 || c > c2 || r < r1 || r > r2) this.setCursor(c, r, false);
        menu(e.clientX, e.clientY, [
          { label: 'Cut', hint: 'Ctrl+X', onClick: () => document.execCommand('cut') },
          { label: 'Copy', hint: 'Ctrl+C', onClick: () => document.execCommand('copy') },
          { label: 'Paste', hint: 'Ctrl+V', onClick: () => toast('Press Ctrl+V to paste') },
          '-',
          { label: 'Sort range…', onClick: () => this.sortDialog() },
          { label: 'Insert chart…', onClick: () => this.insertChart() },
          '-',
          { label: 'Clear contents', hint: 'Del', onClick: () => this.clearRange() },
          { label: 'Clear formatting', onClick: () => this.clearFormatting() },
        ]);
      }
    }

    async resizeDialog(kind, at) {
      const sh = this.sheet;
      const current = kind === 'col' ? (sh.colW[at] || DEF_COL_W) : (sh.rowH[at] || DEF_ROW_H);
      const v = await form({
        title: kind === 'col' ? `Resize column ${F.indexToCol(at)}` : `Resize row ${at + 1}`,
        fields: [{ name: 'size', label: 'Size in pixels', type: 'number', value: current, min: 16, max: 800 }],
        okLabel: 'Resize',
      });
      if (!v) return;
      const size = Math.max(16, Math.min(800, parseInt(v.size, 10) || current));
      this.snapshot();
      const { c1, c2, r1, r2 } = this.range();
      if (kind === 'col') for (let c = c1; c <= c2; c++) sh.colW[c] = size;
      else for (let r = r1; r <= r2; r++) sh.rowH[r] = size;
      this.renderGrid();
      this.ctx.onChange();
    }

    // ---- tools --------------------------------------------------------------
    autoSum() {
      const sh = this.sheet;
      const { c, r } = this.cur;
      // Walk up for a run of numbers; if there is none, walk left.
      let top = r - 1;
      while (top >= 0 && sh.cells[key(c, top)] && sh.cells[key(c, top)].v !== '') top--;
      if (top < r - 1) {
        this.snapshot();
        this.setRaw(c, r, `=SUM(${F.a1(c, top + 1)}:${F.a1(c, r - 1)})`);
        this.afterEdit();
        return;
      }
      let left = c - 1;
      while (left >= 0 && sh.cells[key(left, r)] && sh.cells[key(left, r)].v !== '') left--;
      if (left < c - 1) {
        this.snapshot();
        this.setRaw(c, r, `=SUM(${F.a1(left + 1, r)}:${F.a1(c - 1, r)})`);
        this.afterEdit();
        return;
      }
      this.beginEdit('=SUM(');
    }

    async sortDialog() {
      const { c1, c2, r1, r2 } = this.range();
      if (c1 === c2 && r1 === r2) {
        toast('Select the range to sort first', 'err');
        return;
      }
      const cols = [];
      for (let c = c1; c <= c2; c++) cols.push({ value: String(c), label: `Column ${F.indexToCol(c)}` });
      const v = await form({
        title: `Sort ${F.a1(c1, r1)}:${F.a1(c2, r2)}`,
        fields: [
          { name: 'by', label: 'Sort by', type: 'select', options: cols, value: String(c1) },
          { name: 'dir', label: 'Order', type: 'select', options: [{ value: 'asc', label: 'A → Z / smallest first' }, { value: 'desc', label: 'Z → A / largest first' }], value: 'asc' },
          { name: 'header', label: 'First row is a header — leave it in place', type: 'checkbox', value: false },
        ],
        okLabel: 'Sort',
      });
      if (!v) return;
      this.sortRange(c1, c2, r1, r2, parseInt(v.by, 10), v.dir === 'desc', v.header);
    }

    sortRange(c1, c2, r1, r2, byCol, desc, keepHeader) {
      this.snapshot();
      const sh = this.sheet;
      const first = keepHeader ? r1 + 1 : r1;
      const rows = [];
      for (let r = first; r <= r2; r++) {
        const cells = [];
        for (let c = c1; c <= c2; c++) {
          const cell = sh.cells[key(c, r)];
          cells.push(cell ? JSON.parse(JSON.stringify(cell)) : null);
        }
        rows.push({ cells, sortValue: this.valueAt(this.si, byCol, r) });
      }
      rows.sort((a, b) => {
        const av = a.sortValue, bv = b.sortValue;
        // Blanks always sink to the bottom, whichever direction we sort.
        const aEmpty = av === null || av === undefined || av === '';
        const bEmpty = bv === null || bv === undefined || bv === '';
        if (aEmpty && bEmpty) return 0;
        if (aEmpty) return 1;
        if (bEmpty) return -1;
        const an = typeof av === 'number', bn = typeof bv === 'number';
        let cmp;
        if (an && bn) cmp = av - bv;
        else cmp = String(F.toStr(av)).toLowerCase().localeCompare(String(F.toStr(bv)).toLowerCase());
        return desc ? -cmp : cmp;
      });
      rows.forEach((row, i) => {
        const r = first + i;
        row.cells.forEach((cell, ci) => {
          const c = c1 + ci;
          if (cell) sh.cells[key(c, r)] = cell;
          else delete sh.cells[key(c, r)];
        });
      });
      this.afterEdit();
      toast(`Sorted ${rows.length} rows`);
    }

    // ---- charts -------------------------------------------------------------
    async insertChart() {
      const { c1, c2, r1, r2 } = this.range();
      if (c1 === c2 && r1 === r2) {
        toast('Select the data for the chart first', 'err');
        return;
      }
      const v = await form({
        title: 'Insert chart',
        sub: `Data: ${F.a1(c1, r1)}:${F.a1(c2, r2)}`,
        fields: [
          { name: 'type', label: 'Chart type', type: 'select', value: 'column',
            options: [
              { value: 'column', label: 'Column' },
              { value: 'bar', label: 'Bar' },
              { value: 'line', label: 'Line' },
              { value: 'pie', label: 'Pie' },
            ] },
          { name: 'title', label: 'Title', value: '' },
          { name: 'labels', label: 'First column holds the category labels', type: 'checkbox', value: true },
          { name: 'header', label: 'First row holds the series names', type: 'checkbox', value: true },
        ],
        okLabel: 'Insert',
      });
      if (!v) return;
      this.snapshot();
      this.sheet.charts.push({
        id: 'ch' + Date.now().toString(36),
        type: v.type,
        title: v.title,
        labels: !!v.labels,
        header: !!v.header,
        range: { c1, c2, r1, r2 },
        x: this.gridWrap.scrollLeft + 90,
        y: this.gridWrap.scrollTop + 60,
        w: 460,
        h: 290,
      });
      this.renderCharts();
      this.ctx.onChange();
    }

    renderCharts() {
      if (!this.chartLayer) return;
      this.chartLayer.innerHTML = '';
      for (const chart of this.sheet.charts) {
        this.chartLayer.appendChild(this.buildChartBox(chart));
      }
    }

    buildChartBox(chart) {
      const canvas = el('canvas');
      const box = el('div', {
        class: 'chart-box',
        style: { left: chart.x + 'px', top: chart.y + 'px', width: chart.w + 'px', height: chart.h + 'px' },
      });
      const head = el('div', { class: 'chart-head' }, [
        el('span', { text: chart.title || `${chart.type} chart` }),
        el('div', {}, [
          el('button', { text: '✎', title: 'Edit', onclick: () => this.editChart(chart) }),
          el('button', { text: '✕', title: 'Delete', onclick: () => {
            this.snapshot();
            this.sheet.charts = this.sheet.charts.filter((c) => c.id !== chart.id);
            this.renderCharts();
            this.ctx.onChange();
          } }),
        ]),
      ]);
      const grip = el('div', { class: 'chart-resize' });
      box.append(head, canvas, grip);

      // Drag by the header, resize by the corner grip.
      head.addEventListener('mousedown', (e) => {
        if (e.target.tagName === 'BUTTON') return;
        e.preventDefault();
        const sx = e.clientX, sy = e.clientY, ox = chart.x, oy = chart.y;
        const move = (ev) => {
          chart.x = Math.max(0, ox + ev.clientX - sx);
          chart.y = Math.max(0, oy + ev.clientY - sy);
          box.style.left = chart.x + 'px';
          box.style.top = chart.y + 'px';
        };
        const up = () => {
          document.removeEventListener('mousemove', move);
          document.removeEventListener('mouseup', up);
          this.ctx.onChange();
        };
        document.addEventListener('mousemove', move);
        document.addEventListener('mouseup', up);
      });
      grip.addEventListener('mousedown', (e) => {
        e.preventDefault();
        e.stopPropagation();
        const sx = e.clientX, sy = e.clientY, ow = chart.w, oh = chart.h;
        const move = (ev) => {
          chart.w = Math.max(220, ow + ev.clientX - sx);
          chart.h = Math.max(160, oh + ev.clientY - sy);
          box.style.width = chart.w + 'px';
          box.style.height = chart.h + 'px';
          this.drawChart(canvas, chart);
        };
        const up = () => {
          document.removeEventListener('mousemove', move);
          document.removeEventListener('mouseup', up);
          this.ctx.onChange();
        };
        document.addEventListener('mousemove', move);
        document.addEventListener('mouseup', up);
      });

      // Canvas sizing waits for layout so the header height is known.
      requestAnimationFrame(() => this.drawChart(canvas, chart));
      return box;
    }

    async editChart(chart) {
      const v = await form({
        title: 'Chart settings',
        fields: [
          { name: 'type', label: 'Chart type', type: 'select', value: chart.type,
            options: [
              { value: 'column', label: 'Column' }, { value: 'bar', label: 'Bar' },
              { value: 'line', label: 'Line' }, { value: 'pie', label: 'Pie' },
            ] },
          { name: 'title', label: 'Title', value: chart.title || '' },
          { name: 'range', label: 'Data range', value: `${F.a1(chart.range.c1, chart.range.r1)}:${F.a1(chart.range.c2, chart.range.r2)}` },
          { name: 'labels', label: 'First column holds the category labels', type: 'checkbox', value: chart.labels },
          { name: 'header', label: 'First row holds the series names', type: 'checkbox', value: chart.header },
        ],
        okLabel: 'Apply',
      });
      if (!v) return;
      const m = /^([A-Z]+\d+):([A-Z]+\d+)$/i.exec(v.range.trim());
      if (m) {
        const a = F.parseA1(m[1].toUpperCase());
        const b = F.parseA1(m[2].toUpperCase());
        if (a && b) {
          chart.range = {
            c1: Math.min(a.col, b.col), c2: Math.max(a.col, b.col),
            r1: Math.min(a.row, b.row), r2: Math.max(a.row, b.row),
          };
        }
      }
      chart.type = v.type;
      chart.title = v.title;
      chart.labels = v.labels;
      chart.header = v.header;
      this.renderCharts();
      this.ctx.onChange();
    }

    /** Pull the chart's numbers out of the grid at draw time. */
    chartData(chart) {
      const { c1, c2, r1, r2 } = chart.range;
      const startR = chart.header ? r1 + 1 : r1;
      const startC = chart.labels ? c1 + 1 : c1;
      const seriesNames = [];
      for (let c = startC; c <= c2; c++) {
        const v = chart.header ? this.valueAt(this.si, c, r1) : null;
        seriesNames.push(v === null || v === undefined || v === '' ? `Series ${c - startC + 1}` : F.toStr(v));
      }
      const categories = [];
      const series = seriesNames.map(() => []);
      for (let r = startR; r <= r2; r++) {
        const label = chart.labels ? this.valueAt(this.si, c1, r) : r - startR + 1;
        categories.push(F.isErr(label) ? '' : F.toStr(label === null ? '' : label));
        for (let c = startC; c <= c2; c++) {
          const v = this.valueAt(this.si, c, r);
          const n = typeof v === 'number' ? v : (F.isErr(v) ? 0 : parseFloat(F.toStr(v)) || 0);
          series[c - startC].push(n);
        }
      }
      return { categories, seriesNames, series };
    }

    drawChart(canvas, chart) {
      const head = canvas.previousSibling;
      const headH = head ? head.getBoundingClientRect().height : 22;
      const w = chart.w - 2;
      const h = chart.h - headH - 2;
      const dpr = window.devicePixelRatio || 1;
      canvas.width = Math.max(1, Math.round(w * dpr));
      canvas.height = Math.max(1, Math.round(h * dpr));
      canvas.style.width = w + 'px';
      canvas.style.height = h + 'px';
      const g = canvas.getContext('2d');
      g.scale(dpr, dpr);
      drawChartOn(g, w, h, chart, this.chartData(chart));
    }

    // ---- find ---------------------------------------------------------------
    openFind() {
      if (this.findBar) { this.findInput.focus(); this.findInput.select(); return; }
      const input = el('input', {
        class: 'tinput', placeholder: 'Find in sheet', value: this.find.term,
        oninput: () => this.runFind(input.value),
        onkeydown: (e) => {
          if (e.key === 'Enter') { e.preventDefault(); this.stepFind(e.shiftKey ? -1 : 1); }
          if (e.key === 'Escape') { e.preventDefault(); this.closeFind(); }
        },
      });
      const count = el('span', { class: 'count', text: '0 / 0' });
      this.findInput = input;
      this.findCount = count;
      this.findBar = el('div', { class: 'findbar' }, [
        input, count,
        tbtn({ html: '&#8593;', title: 'Previous', onClick: () => this.stepFind(-1) }),
        tbtn({ html: '&#8595;', title: 'Next', onClick: () => this.stepFind(1) }),
        sep(),
        tbtn({ html: '✕', title: 'Close (Esc)', onClick: () => this.closeFind() }),
      ]);
      this.host.appendChild(this.findBar);
      input.focus();
      if (input.value) this.runFind(input.value);
    }

    closeFind() {
      if (!this.findBar) return;
      this.findBar.remove();
      this.findBar = null;
      this.clearFindMarks();
      this.gridWrap.focus();
    }

    clearFindMarks() {
      for (const { c, r } of this.find.matches) {
        const td = this.tds[r] && this.tds[r][c];
        if (td) td.classList.remove('match');
      }
      this.find.matches = [];
      this.find.index = -1;
    }

    runFind(term) {
      this.clearFindMarks();
      this.find.term = term;
      if (!term) { this.findCount.textContent = '0 / 0'; return; }
      const needle = term.toLowerCase();
      const sh = this.sheet;
      const hits = [];
      for (let r = 0; r < sh.rows; r++) {
        for (let c = 0; c < sh.cols; c++) {
          const cell = sh.cells[key(c, r)];
          if (!cell) continue;
          const shown = displayValue(this.valueAt(this.si, c, r), cell.s && cell.s.fmt);
          if (String(shown).toLowerCase().includes(needle) || String(cell.v).toLowerCase().includes(needle)) {
            hits.push({ c, r });
          }
        }
      }
      this.find.matches = hits;
      this.find.index = hits.length ? 0 : -1;
      for (const { c, r } of hits) {
        const td = this.tds[r] && this.tds[r][c];
        if (td) td.classList.add('match');
      }
      this.findCount.textContent = `${hits.length ? 1 : 0} / ${hits.length}`;
      if (hits.length) this.setCursor(hits[0].c, hits[0].r, false);
    }

    stepFind(dir) {
      if (!this.find.matches.length) return;
      this.find.index = (this.find.index + dir + this.find.matches.length) % this.find.matches.length;
      const hit = this.find.matches[this.find.index];
      this.setCursor(hit.c, hit.r, false);
      this.findCount.textContent = `${this.find.index + 1} / ${this.find.matches.length}`;
    }

    // ---- sheet tabs ---------------------------------------------------------
    renderTabs() {
      this.tabsBar.innerHTML = '';
      this.data.sheets.forEach((s, i) => {
        const tab = el('div', {
          class: 'sheet-tab' + (i === this.si ? ' active' : ''),
          text: s.name,
          onmousedown: () => this.switchSheet(i),
          ondblclick: () => this.renameSheet(i),
          oncontextmenu: (e) => {
            e.preventDefault();
            e.stopPropagation();
            menu(e.clientX, e.clientY, [
              { label: 'Rename…', onClick: () => this.renameSheet(i) },
              { label: 'Duplicate', onClick: () => this.duplicateSheet(i) },
              '-',
              { label: 'Delete', danger: true, onClick: () => this.deleteSheet(i) },
            ]);
          },
        });
        this.tabsBar.appendChild(tab);
      });
      this.tabsBar.appendChild(el('button', { class: 'sheet-add', text: '＋', title: 'Add sheet', onclick: () => this.addSheet() }));
    }

    switchSheet(i) {
      if (i === this.si) return;
      if (this.editing) this.endEdit(true);
      this.si = i;
      this.data.active = i;
      this.cur = { c: 0, r: 0 };
      this.anchor = { c: 0, r: 0 };
      this.renderGrid();
      this.renderTabs();
      this.gridWrap.focus();
    }

    addSheet() {
      this.snapshot();
      let n = this.data.sheets.length + 1;
      while (this.data.sheets.some((s) => s.name === 'Sheet' + n)) n++;
      this.data.sheets.push(newSheet('Sheet' + n));
      this.si = this.data.sheets.length - 1;
      this.data.active = this.si;
      this.cur = { c: 0, r: 0 };
      this.anchor = { c: 0, r: 0 };
      this.renderGrid();
      this.renderTabs();
      this.ctx.onChange();
    }

    async renameSheet(i) {
      const v = await form({
        title: 'Rename sheet',
        fields: [{ name: 'name', label: 'Name', value: this.data.sheets[i].name }],
        okLabel: 'Rename',
        note: 'Formulas that reference this sheet by name will need updating.',
      });
      if (!v || !v.name.trim()) return;
      const name = v.name.trim();
      if (this.data.sheets.some((s, j) => j !== i && s.name.toLowerCase() === name.toLowerCase())) {
        toast('A sheet with that name already exists', 'err');
        return;
      }
      this.snapshot();
      this.data.sheets[i].name = name;
      this.astCache.clear();
      this.renderTabs();
      this.recalc();
      this.ctx.onChange();
    }

    duplicateSheet(i) {
      this.snapshot();
      const copy = JSON.parse(JSON.stringify(this.data.sheets[i]));
      let n = 2;
      while (this.data.sheets.some((s) => s.name === `${copy.name} (${n})`)) n++;
      copy.name = `${copy.name} (${n})`;
      copy.charts = (copy.charts || []).map((c) => Object.assign({}, c, { id: 'ch' + Math.random().toString(36).slice(2) }));
      this.data.sheets.splice(i + 1, 0, copy);
      this.si = i + 1;
      this.data.active = this.si;
      this.renderGrid();
      this.renderTabs();
      this.ctx.onChange();
    }

    async deleteSheet(i) {
      if (this.data.sheets.length === 1) {
        toast('A spreadsheet needs at least one sheet', 'err');
        return;
      }
      const ok = await confirm({
        title: `Delete "${this.data.sheets[i].name}"?`,
        message: 'The data on this sheet will be removed. This can be undone with Ctrl+Z.',
        okLabel: 'Delete',
        danger: true,
      });
      if (!ok) return;
      this.snapshot();
      this.data.sheets.splice(i, 1);
      this.si = Math.min(this.si, this.data.sheets.length - 1);
      this.data.active = this.si;
      this.cur = { c: 0, r: 0 };
      this.anchor = { c: 0, r: 0 };
      this.astCache.clear();
      this.renderGrid();
      this.renderTabs();
      this.ctx.onChange();
    }

    // ---- shell interface ----------------------------------------------------
    focus() { this.gridWrap.focus(); }

    serialize() {
      this.data.active = this.si;
      return this.data;
    }

    command(name) {
      switch (name) {
        case 'find': this.openFind(); return true;
        case 'insert-chart': this.insertChart(); return true;
        case 'zoom-in': case 'zoom-out': case 'zoom-reset': return false;
        default: return false;
      }
    }

    status() {
      const { c1, c2, r1, r2 } = this.range();
      const cells = (c2 - c1 + 1) * (r2 - r1 + 1);
      let sum = 0, count = 0, numeric = 0;
      this.forEachInRange((c, r) => {
        const v = this.valueAt(this.si, c, r);
        if (v === null || v === '' || v === undefined) return;
        count++;
        if (typeof v === 'number') { sum += v; numeric++; }
      });
      const left = cells > 1
        ? `${cells} cells · ${count} filled` + (numeric ? ` · Sum ${F.formatNumberPlain(Math.round(sum * 1e6) / 1e6)} · Average ${F.formatNumberPlain(Math.round((sum / numeric) * 1e6) / 1e6)}` : '')
        : `${this.sheet.name} · ${F.a1(this.cur.c, this.cur.r)}`;
      return { left, right: `Spreadsheet · ${this.data.sheets.length} sheet${this.data.sheets.length > 1 ? 's' : ''}` };
    }

    /** CSV of the active sheet, only as far as there is data. */
    toCSV() {
      const sh = this.sheet;
      let maxC = 0, maxR = 0;
      for (const k of Object.keys(sh.cells)) {
        const [c, r] = k.split(',').map(Number);
        if (sh.cells[k].v !== '') {
          if (c > maxC) maxC = c;
          if (r > maxR) maxR = r;
        }
      }
      const lines = [];
      for (let r = 0; r <= maxR; r++) {
        const row = [];
        for (let c = 0; c <= maxC; c++) {
          const cell = sh.cells[key(c, r)];
          const text = cell ? displayValue(this.valueAt(this.si, c, r), cell.s && cell.s.fmt) : '';
          row.push(/[",\n]/.test(text) ? '"' + text.replace(/"/g, '""') + '"' : text);
        }
        lines.push(row.join(','));
      }
      return lines.join('\r\n');
    }

    toPlainText() { return this.toCSV(); }

    toPrintHTML(title) {
      const sh = this.sheet;
      let maxC = 0, maxR = 0;
      for (const k of Object.keys(sh.cells)) {
        const [c, r] = k.split(',').map(Number);
        if (sh.cells[k].v !== '') {
          if (c > maxC) maxC = c;
          if (r > maxR) maxR = r;
        }
      }
      let body = '<table>';
      for (let r = 0; r <= maxR; r++) {
        body += '<tr>';
        for (let c = 0; c <= maxC; c++) {
          const cell = sh.cells[key(c, r)];
          const value = cell ? this.valueAt(this.si, c, r) : null;
          const st = (cell && cell.s) || {};
          const css = [
            st.b ? 'font-weight:700' : '',
            st.i ? 'font-style:italic' : '',
            st.u ? 'text-decoration:underline' : '',
            st.fg ? 'color:' + st.fg : '',
            st.bg ? 'background:' + st.bg : '',
            'text-align:' + (st.a || (typeof value === 'number' ? 'right' : 'left')),
          ].filter(Boolean).join(';');
          body += `<td style="${css}">${escapeHtml(displayValue(value, st.fmt))}</td>`;
        }
        body += '</tr>';
      }
      body += '</table>';
      return `<!doctype html><html><head><meta charset="utf-8"><title>${escapeHtml(title || 'Spreadsheet')}</title>
<style>
  @page { size: Letter landscape; margin: .5in; }
  body { font-family: "Segoe UI", Arial, sans-serif; font-size: 9.5pt; margin: 0; }
  h1 { font-size: 13pt; margin: 0 0 10px; }
  table { border-collapse: collapse; width: 100%; }
  td { border: 1px solid #ccd2dd; padding: 3px 6px; }
</style></head><body><h1>${escapeHtml(title || sh.name)}</h1>${body}</body></html>`;
    }

    destroy() {}
  }

  // ---- fill geometry --------------------------------------------------------
  /** Extend a source range towards (c,r), locking to one axis like a spreadsheet. */
  function fillTarget(src, c, r) {
    const downBy = r - src.r2;
    const upBy = src.r1 - r;
    const rightBy = c - src.c2;
    const leftBy = src.c1 - c;
    const vertical = Math.max(downBy, upBy) >= Math.max(rightBy, leftBy);
    if (vertical) {
      return {
        c1: src.c1, c2: src.c2,
        r1: Math.min(src.r1, r), r2: Math.max(src.r2, r),
      };
    }
    return {
      c1: Math.min(src.c1, c), c2: Math.max(src.c2, c),
      r1: src.r1, r2: src.r2,
    };
  }

  // ---- CSV ------------------------------------------------------------------
  function parseCSV(text) {
    const rows = [];
    let row = [];
    let field = '';
    let inQuotes = false;
    const src = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
    for (let i = 0; i < src.length; i++) {
      const ch = src[i];
      if (inQuotes) {
        if (ch === '"') {
          if (src[i + 1] === '"') { field += '"'; i++; }
          else inQuotes = false;
        } else field += ch;
        continue;
      }
      if (ch === '"') { inQuotes = true; continue; }
      if (ch === ',') { row.push(field); field = ''; continue; }
      if (ch === '\n') { row.push(field); rows.push(row); row = []; field = ''; continue; }
      field += ch;
    }
    if (field !== '' || row.length) { row.push(field); rows.push(row); }
    return rows;
  }

  // ---- chart drawing --------------------------------------------------------
  const PALETTE = ['#3c78d8', '#e8710a', '#0f9d58', '#a142f4', '#d93025', '#12a4af', '#f4b400', '#8d6e63'];

  function drawChartOn(g, w, h, chart, data) {
    g.clearRect(0, 0, w, h);
    g.fillStyle = '#fff';
    g.fillRect(0, 0, w, h);
    g.font = '11px "Segoe UI", Arial, sans-serif';
    g.textBaseline = 'middle';

    const { categories, seriesNames, series } = data;
    if (!series.length || !categories.length) {
      g.fillStyle = '#8b93a5';
      g.textAlign = 'center';
      g.fillText('No data in range', w / 2, h / 2);
      return;
    }

    if (chart.type === 'pie') return drawPie(g, w, h, categories, series[0]);

    const horizontal = chart.type === 'bar';
    const legendH = seriesNames.length > 1 ? 18 : 0;
    const pad = { top: 12, right: 14, bottom: 26 + legendH, left: 46 };

    let min = 0, max = 0;
    for (const s of series) for (const v of s) { if (v < min) min = v; if (v > max) max = v; }
    if (min === max) max = min + 1;
    // Round the axis out to a friendly interval.
    const span = max - min;
    const stepRaw = span / 5;
    const mag = Math.pow(10, Math.floor(Math.log10(stepRaw || 1)));
    const step = Math.ceil(stepRaw / mag) * mag;
    max = Math.ceil(max / step) * step;
    min = Math.floor(min / step) * step;

    const plotW = w - pad.left - pad.right;
    const plotH = h - pad.top - pad.bottom;
    const valueAxis = horizontal ? plotW : plotH;
    const toPos = (v) => ((v - min) / (max - min)) * valueAxis;

    // Grid lines and value labels.
    g.strokeStyle = '#e4e7ee';
    g.fillStyle = '#8b93a5';
    g.lineWidth = 1;
    for (let v = min; v <= max + 1e-9; v += step) {
      const p = toPos(v);
      g.beginPath();
      if (horizontal) {
        const x = pad.left + p;
        g.moveTo(x, pad.top);
        g.lineTo(x, pad.top + plotH);
        g.textAlign = 'center';
        g.fillText(shortNum(v), x, pad.top + plotH + 11);
      } else {
        const y = pad.top + plotH - p;
        g.moveTo(pad.left, y);
        g.lineTo(pad.left + plotW, y);
        g.textAlign = 'right';
        g.fillText(shortNum(v), pad.left - 6, y);
      }
      g.stroke();
    }

    const n = categories.length;
    const slot = (horizontal ? plotH : plotW) / n;

    if (chart.type === 'line') {
      series.forEach((s, si) => {
        g.strokeStyle = PALETTE[si % PALETTE.length];
        g.lineWidth = 2;
        g.beginPath();
        s.forEach((v, i) => {
          const x = pad.left + slot * (i + 0.5);
          const y = pad.top + plotH - toPos(v);
          if (i === 0) g.moveTo(x, y); else g.lineTo(x, y);
        });
        g.stroke();
        g.fillStyle = PALETTE[si % PALETTE.length];
        s.forEach((v, i) => {
          const x = pad.left + slot * (i + 0.5);
          const y = pad.top + plotH - toPos(v);
          g.beginPath();
          g.arc(x, y, 2.6, 0, Math.PI * 2);
          g.fill();
        });
      });
    } else {
      const groupPad = slot * 0.18;
      const barW = (slot - groupPad * 2) / series.length;
      series.forEach((s, si) => {
        g.fillStyle = PALETTE[si % PALETTE.length];
        s.forEach((v, i) => {
          if (horizontal) {
            const y = pad.top + slot * i + groupPad + barW * si;
            const x0 = pad.left + toPos(Math.min(0, v));
            const len = Math.abs(toPos(v) - toPos(0));
            g.fillRect(x0, y, len, Math.max(1, barW - 1));
          } else {
            const x = pad.left + slot * i + groupPad + barW * si;
            const yZero = pad.top + plotH - toPos(0);
            const yVal = pad.top + plotH - toPos(v);
            g.fillRect(x, Math.min(yZero, yVal), Math.max(1, barW - 1), Math.abs(yZero - yVal));
          }
        });
      });
    }

    // Category labels, thinned out when they would collide.
    g.fillStyle = '#5a6274';
    const every = Math.ceil((n * 46) / (horizontal ? plotH : plotW));
    categories.forEach((cat, i) => {
      if (i % every !== 0) return;
      const label = String(cat).length > 11 ? String(cat).slice(0, 10) + '…' : String(cat);
      if (horizontal) {
        g.textAlign = 'right';
        g.fillText(label, pad.left - 6, pad.top + slot * (i + 0.5));
      } else {
        g.textAlign = 'center';
        g.fillText(label, pad.left + slot * (i + 0.5), pad.top + plotH + 11);
      }
    });

    if (legendH) {
      let x = pad.left;
      const y = h - 10;
      g.textAlign = 'left';
      seriesNames.forEach((name, si) => {
        g.fillStyle = PALETTE[si % PALETTE.length];
        g.fillRect(x, y - 4, 9, 9);
        g.fillStyle = '#5a6274';
        const label = String(name).length > 14 ? String(name).slice(0, 13) + '…' : String(name);
        g.fillText(label, x + 13, y);
        x += 13 + g.measureText(label).width + 16;
      });
    }
  }

  function drawPie(g, w, h, categories, values) {
    const total = values.reduce((s, v) => s + Math.abs(v), 0);
    const cx = w * 0.36, cy = h / 2;
    const radius = Math.min(w * 0.32, h * 0.40);
    if (!total) {
      g.fillStyle = '#8b93a5';
      g.textAlign = 'center';
      g.fillText('No data in range', w / 2, h / 2);
      return;
    }
    let angle = -Math.PI / 2;
    values.forEach((v, i) => {
      const slice = (Math.abs(v) / total) * Math.PI * 2;
      g.beginPath();
      g.moveTo(cx, cy);
      g.arc(cx, cy, radius, angle, angle + slice);
      g.closePath();
      g.fillStyle = PALETTE[i % PALETTE.length];
      g.fill();
      angle += slice;
    });
    // Legend down the right-hand side.
    g.textAlign = 'left';
    const startY = cy - Math.min(values.length, 9) * 8;
    values.slice(0, 9).forEach((v, i) => {
      const y = startY + i * 16;
      g.fillStyle = PALETTE[i % PALETTE.length];
      g.fillRect(w * 0.68, y - 4, 9, 9);
      g.fillStyle = '#5a6274';
      const pct = ((Math.abs(v) / total) * 100).toFixed(0) + '%';
      const name = String(categories[i] || '').length > 12 ? String(categories[i]).slice(0, 11) + '…' : String(categories[i] || '');
      g.fillText(`${name} ${pct}`, w * 0.68 + 13, y);
    });
  }

  function shortNum(v) {
    const a = Math.abs(v);
    if (a >= 1e9) return (v / 1e9).toFixed(1) + 'B';
    if (a >= 1e6) return (v / 1e6).toFixed(1) + 'M';
    if (a >= 1e4) return (v / 1e3).toFixed(0) + 'K';
    return F.formatNumberPlain(Math.round(v * 1000) / 1000);
  }

  global.SheetEditor = SheetEditor;
  global.parseCSV = parseCSV;
  global.sheetDisplayValue = displayValue;
})(window);
'use strict';
/*
 * OfficeForger — the presentation editor.
 *
 * A deck is a list of slides; a slide is a list of absolutely-positioned elements
 * on a fixed 960x540 stage. Everything — the editing stage, the rail thumbnails,
 * present mode and the exported HTML — renders from that one model through
 * renderSlide(), so what you edit is exactly what you present and what you print.
 */
(function (global) {
  const { el, tbtn, sep, spacer, toast, form, confirm, menu, swatchButton, escapeHtml, ICONS } = global.UI;

  const W = 960;
  const H = 540;

  const THEMES = {
    plain: { bg: '#ffffff', ink: '#1a1f2b', accent: '#2f6fd0', font: 'Segoe UI, Arial, sans-serif' },
    slate: { bg: '#1e2530', ink: '#f2f5fa', accent: '#5aa9ff', font: 'Segoe UI, Arial, sans-serif' },
    forge: { bg: '#fbf7f1', ink: '#2a2118', accent: '#b0651a', font: 'Georgia, serif' },
    ocean: { bg: '#0e2f3f', ink: '#eaf6fb', accent: '#39c0c8', font: 'Segoe UI, Arial, sans-serif' },
  };

  const uid = () => 's' + Math.random().toString(36).slice(2, 9);

  function textEl(props) {
    return Object.assign({
      id: uid(), type: 'text', x: 80, y: 200, w: 800, h: 90,
      text: 'Text', size: 24, bold: false, italic: false, align: 'left',
      color: null, font: null, valign: 'top',
    }, props);
  }

  function newSlide(layout, theme) {
    const slide = { id: uid(), bg: null, elements: [] };
    if (layout === 'title') {
      slide.elements.push(textEl({ y: 190, h: 110, text: 'Presentation title', size: 54, bold: true, align: 'center' }));
      slide.elements.push(textEl({ y: 310, h: 60, text: 'Subtitle', size: 24, align: 'center' }));
    } else if (layout === 'titleContent') {
      slide.elements.push(textEl({ y: 56, h: 72, text: 'Slide title', size: 38, bold: true }));
      slide.elements.push(textEl({ y: 152, h: 320, text: '• First point\n• Second point\n• Third point', size: 24 }));
    } else if (layout === 'twoColumn') {
      slide.elements.push(textEl({ y: 56, h: 72, text: 'Slide title', size: 38, bold: true }));
      slide.elements.push(textEl({ x: 80, y: 152, w: 380, h: 320, text: '• Left column', size: 22 }));
      slide.elements.push(textEl({ x: 500, y: 152, w: 380, h: 320, text: '• Right column', size: 22 }));
    } else if (layout === 'section') {
      slide.elements.push(textEl({ y: 230, h: 90, text: 'Section', size: 46, bold: true, align: 'center' }));
    }
    return slide;
  }

  /**
   * Draw a slide into `host`. The same function backs the editing stage, the rail
   * thumbnails, present mode and export, so those can never drift apart.
   */
  function renderSlide(host, slide, theme, opts) {
    opts = opts || {};
    host.innerHTML = '';
    host.style.background = slide.bg || theme.bg;
    host.style.fontFamily = theme.font;

    for (const e of slide.elements) {
      const node = el('div', {
        class: 'el ' + e.type,
        dataset: { id: e.id },
        style: { left: e.x + 'px', top: e.y + 'px', width: e.w + 'px', height: e.h + 'px' },
      });

      if (e.type === 'text') {
        Object.assign(node.style, {
          fontSize: e.size + 'px',
          fontWeight: e.bold ? '700' : '400',
          fontStyle: e.italic ? 'italic' : 'normal',
          textDecoration: e.underline ? 'underline' : 'none',
          textAlign: e.align || 'left',
          color: e.color || theme.ink,
          fontFamily: e.font || theme.font,
          lineHeight: '1.25',
          whiteSpace: 'pre-wrap',
          wordBreak: 'break-word',
          display: 'flex',
          flexDirection: 'column',
          justifyContent: e.valign === 'middle' ? 'center' : e.valign === 'bottom' ? 'flex-end' : 'flex-start',
        });
        node.textContent = e.text;
      } else if (e.type === 'image') {
        const img = el('img', {
          src: e.src,
          style: { width: '100%', height: '100%', objectFit: e.fit || 'contain', display: 'block' },
          draggable: 'false',
        });
        node.appendChild(img);
      } else if (e.type === 'shape') {
        const fill = e.fill === null ? 'transparent' : (e.fill || theme.accent);
        if (e.shape === 'ellipse') {
          Object.assign(node.style, { background: fill, borderRadius: '50%' });
        } else if (e.shape === 'line') {
          Object.assign(node.style, {
            background: 'transparent',
            borderTop: `${e.stroke || 3}px solid ${e.strokeColor || theme.accent}`,
            height: '0px',
          });
        } else {
          Object.assign(node.style, { background: fill, borderRadius: (e.radius || 0) + 'px' });
        }
        if (e.strokeColor && e.shape !== 'line') {
          node.style.border = `${e.stroke || 2}px solid ${e.strokeColor}`;
        }
      }
      host.appendChild(node);
    }
  }

  class SlideEditor {
    static get kind() { return 'slide'; }
    static get ext() { return 'ofslide'; }
    static get label() { return 'Presentation'; }
    static get icon() { return '▭'; }

    static newData() {
      return {
        theme: 'plain',
        slides: [newSlide('title'), newSlide('titleContent')],
        active: 0,
      };
    }

    constructor(host, data, ctx) {
      this.host = host;
      this.ctx = ctx;
      this.data = data && data.slides && data.slides.length ? data : SlideEditor.newData();
      this.data.theme = this.data.theme in THEMES ? this.data.theme : 'plain';
      this.i = Math.min(this.data.active || 0, this.data.slides.length - 1);
      this.selected = null;
      this.editingEl = null;
      this.undoStack = [];
      this.redoStack = [];
      this.build();
    }

    get theme() { return THEMES[this.data.theme]; }
    get slide() { return this.data.slides[this.i]; }

    // ---- construction -------------------------------------------------------
    build() {
      this.host.appendChild(this.buildToolbar());

      const body = el('div', { class: 'slide-body' });
      this.rail = el('div', { class: 'slide-rail' });
      this.stageWrap = el('div', { class: 'slide-stage-wrap' });
      // The stage is always 960x540 in its own coordinates and is scaled to fit.
      // A scaled element still occupies its unscaled box, so it goes inside a
      // holder sized to the SCALED dimensions — otherwise scaling past 1 makes it
      // overflow its container and the left edge gets clipped away.
      this.stageHolder = el('div', { class: 'slide-stage-holder' });
      this.stage = el('div', { class: 'slide-stage' });
      this.stageHolder.appendChild(this.stage);
      this.stageWrap.appendChild(this.stageHolder);
      body.append(this.rail, this.stageWrap);
      this.host.appendChild(body);

      this.stage.addEventListener('mousedown', (e) => this.onStageMouseDown(e));
      this.stage.addEventListener('dblclick', (e) => this.onStageDblClick(e));
      this.stage.addEventListener('contextmenu', (e) => this.onStageContextMenu(e));
      this.host.setAttribute('tabindex', '0');
      this.host.addEventListener('keydown', (e) => this.onKeyDown(e));

      this.resizeObserver = new ResizeObserver(() => this.fitStage());
      this.resizeObserver.observe(this.stageWrap);

      this.renderAll();
    }

    buildToolbar() {
      const bar = el('div', { class: 'toolbar' });

      bar.appendChild(tbtn({ html: ICONS.undo, title: 'Undo (Ctrl+Z)', onClick: () => this.undo() }));
      bar.appendChild(tbtn({ html: ICONS.redo, title: 'Redo (Ctrl+Y)', onClick: () => this.redo() }));
      bar.appendChild(sep());

      bar.appendChild(tbtn({ html: ICONS.newSlide + '<span>Slide</span>', wide: true, title: 'New slide (Ctrl+M)', onClick: () => this.addSlide('titleContent') }));
      const layoutSel = el('select', {
        class: 'tsel', style: { width: '126px' }, title: 'Add a slide with this layout',
        onchange: (e) => { this.addSlide(e.target.value); e.target.value = ''; },
      }, [
        el('option', { value: '', text: 'Layout…' }),
        el('option', { value: 'title', text: 'Title slide' }),
        el('option', { value: 'titleContent', text: 'Title and body' }),
        el('option', { value: 'twoColumn', text: 'Two columns' }),
        el('option', { value: 'section', text: 'Section header' }),
        el('option', { value: 'blank', text: 'Blank' }),
      ]);
      bar.appendChild(layoutSel);
      bar.appendChild(sep());

      bar.appendChild(tbtn({ html: ICONS.textBox, title: 'Text box', onClick: () => this.addElement('text') }));
      bar.appendChild(tbtn({ html: ICONS.rect, title: 'Rectangle', onClick: () => this.addElement('rect') }));
      bar.appendChild(tbtn({ html: ICONS.ellipse, title: 'Ellipse', onClick: () => this.addElement('ellipse') }));
      bar.appendChild(tbtn({ html: ICONS.line, title: 'Line', onClick: () => this.addElement('line') }));
      bar.appendChild(tbtn({ html: ICONS.image, title: 'Image', onClick: () => this.addImage() }));
      bar.appendChild(sep());

      this.btnBold = tbtn({ html: '<b>B</b>', title: 'Bold', onClick: () => this.toggleProp('bold') });
      this.btnItalic = tbtn({ html: '<i>I</i>', title: 'Italic', onClick: () => this.toggleProp('italic') });
      bar.append(this.btnBold, this.btnItalic);
      this.sizeSel = el('select', {
        class: 'tsel w-size', title: 'Text size',
        onchange: (e) => this.setProp('size', parseInt(e.target.value, 10)),
      }, [10, 12, 14, 16, 18, 20, 24, 28, 32, 40, 48, 54, 66, 80].map((s) => el('option', { value: s, text: s })));
      bar.appendChild(this.sizeSel);
      bar.appendChild(tbtn({ html: ICONS.alignLeft, title: 'Align left', onClick: () => this.setProp('align', 'left') }));
      bar.appendChild(tbtn({ html: ICONS.alignCenter, title: 'Centre', onClick: () => this.setProp('align', 'center') }));
      bar.appendChild(tbtn({ html: ICONS.alignRight, title: 'Align right', onClick: () => this.setProp('align', 'right') }));
      bar.appendChild(swatchButton({
        icon: 'A', title: 'Colour', color: '#000000', allowNone: true, noneLabel: 'Theme colour',
        onPick: (c) => this.setColor(c),
      }));
      bar.appendChild(sep());

      bar.appendChild(tbtn({ html: ICONS.toFront, title: 'Bring to front', onClick: () => this.reorderElement(1) }));
      bar.appendChild(tbtn({ html: ICONS.toBack, title: 'Send to back', onClick: () => this.reorderElement(-1) }));
      bar.appendChild(sep());

      const themeSel = el('select', {
        class: 'tsel', style: { width: '104px' }, title: 'Theme',
        onchange: (e) => {
          this.snapshot();
          this.data.theme = e.target.value;
          this.renderAll();
          this.ctx.onChange();
        },
      }, Object.keys(THEMES).map((t) => el('option', {
        value: t,
        text: t[0].toUpperCase() + t.slice(1),
        selected: t === this.data.theme,
      })));
      this.themeSel = themeSel;
      bar.appendChild(themeSel);
      bar.appendChild(swatchButton({
        icon: ICONS.background, title: 'Slide background', color: '#ffffff', allowNone: true, noneLabel: 'Theme background',
        onPick: (c) => {
          this.snapshot();
          this.slide.bg = c;
          this.renderAll();
          this.ctx.onChange();
        },
      }));

      bar.appendChild(spacer());
      bar.appendChild(tbtn({ html: ICONS.play + '<span>Present</span>', wide: true, title: 'Present (F5)', onClick: () => this.present() }));
      return bar;
    }

    // ---- rendering ----------------------------------------------------------
    renderAll() {
      this.renderRail();
      this.renderStage();
      this.fitStage();
      this.ctx.onStatus && this.ctx.onStatus();
    }

    renderStage() {
      renderSlide(this.stage, this.slide, this.theme);
      if (this.selected) {
        const node = this.stage.querySelector(`[data-id="${this.selected}"]`);
        if (node) this.decorate(node);
        else this.selected = null;
      }
      this.syncToolbar();
    }

    decorate(node) {
      node.classList.add('selected');
      for (const pos of ['nw', 'ne', 'sw', 'se']) {
        node.appendChild(el('div', { class: 'handle ' + pos, dataset: { handle: pos } }));
      }
    }

    renderRail() {
      this.rail.innerHTML = '';
      this.data.slides.forEach((slide, i) => {
        const inner = el('div', { class: 'thumb-inner' });
        renderSlide(inner, slide, this.theme);
        const thumb = el('div', { class: 'thumb' + (i === this.i ? ' active' : ''), draggable: 'true' }, [inner]);

        thumb.addEventListener('mousedown', () => this.goTo(i));
        thumb.addEventListener('contextmenu', (e) => {
          e.preventDefault();
          menu(e.clientX, e.clientY, [
            { label: 'New slide after', onClick: () => this.addSlide('titleContent', i + 1) },
            { label: 'Duplicate', onClick: () => this.duplicateSlide(i) },
            '-',
            { label: 'Move up', onClick: () => this.moveSlide(i, i - 1) },
            { label: 'Move down', onClick: () => this.moveSlide(i, i + 1) },
            '-',
            { label: 'Delete slide', danger: true, onClick: () => this.deleteSlide(i) },
          ]);
        });
        thumb.addEventListener('dragstart', (e) => {
          this.dragFrom = i;
          thumb.classList.add('dragging');
          e.dataTransfer.effectAllowed = 'move';
          e.dataTransfer.setData('text/plain', String(i));
        });
        thumb.addEventListener('dragend', () => thumb.classList.remove('dragging'));
        thumb.addEventListener('dragover', (e) => { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; });
        thumb.addEventListener('drop', (e) => {
          e.preventDefault();
          if (this.dragFrom !== undefined && this.dragFrom !== i) this.moveSlide(this.dragFrom, i);
          this.dragFrom = undefined;
        });

        const row = el('div', { class: 'thumb-item' }, [
          el('div', { class: 'thumb-num', text: String(i + 1) }),
          thumb,
        ]);
        this.rail.appendChild(row);
      });

      // Scale each thumbnail's full-size render down to the rail width.
      requestAnimationFrame(() => {
        for (const t of this.rail.querySelectorAll('.thumb')) {
          const scale = t.clientWidth / W;
          const inner = t.querySelector('.thumb-inner');
          if (inner) inner.style.transform = `scale(${scale})`;
        }
      });
    }

    fitStage() {
      const avail = this.stageWrap.clientWidth - 44;
      const availH = this.stageWrap.clientHeight - 44;
      const scale = Math.max(0.2, Math.min(1.6, Math.min(avail / W, availH / H)));
      this.stage.style.transform = `scale(${scale})`;
      this.stageHolder.style.width = W * scale + 'px';
      this.stageHolder.style.height = H * scale + 'px';
      this.scale = scale;
    }

    syncToolbar() {
      const e = this.element(this.selected);
      const isText = e && e.type === 'text';
      this.btnBold.classList.toggle('on', !!(isText && e.bold));
      this.btnItalic.classList.toggle('on', !!(isText && e.italic));
      if (isText) this.sizeSel.value = String(e.size);
      this.themeSel.value = this.data.theme;
    }

    element(id) {
      if (!id) return null;
      return this.slide.elements.find((e) => e.id === id) || null;
    }

    // ---- undo ---------------------------------------------------------------
    snapshot() {
      this.undoStack.push(JSON.stringify({ slides: this.data.slides, theme: this.data.theme, active: this.i }));
      if (this.undoStack.length > 60) this.undoStack.shift();
      this.redoStack.length = 0;
    }
    restore(json) {
      const s = JSON.parse(json);
      this.data.slides = s.slides;
      this.data.theme = s.theme;
      this.i = Math.min(s.active || 0, this.data.slides.length - 1);
      this.selected = null;
      this.renderAll();
      this.ctx.onChange();
    }
    undo() {
      if (!this.undoStack.length) return;
      this.redoStack.push(JSON.stringify({ slides: this.data.slides, theme: this.data.theme, active: this.i }));
      this.restore(this.undoStack.pop());
    }
    redo() {
      if (!this.redoStack.length) return;
      this.undoStack.push(JSON.stringify({ slides: this.data.slides, theme: this.data.theme, active: this.i }));
      this.restore(this.redoStack.pop());
    }

    // ---- slides -------------------------------------------------------------
    goTo(i) {
      if (i < 0 || i >= this.data.slides.length) return;
      if (this.editingEl) this.endTextEdit();
      this.i = i;
      this.data.active = i;
      this.selected = null;
      this.renderAll();
      this.host.focus();
    }

    addSlide(layout, at) {
      if (!layout) return;
      this.snapshot();
      const index = at === undefined ? this.i + 1 : at;
      this.data.slides.splice(index, 0, newSlide(layout, this.theme));
      this.i = index;
      this.data.active = this.i;
      this.selected = null;
      this.renderAll();
      this.ctx.onChange();
    }

    duplicateSlide(i) {
      this.snapshot();
      const copy = JSON.parse(JSON.stringify(this.data.slides[i]));
      copy.id = uid();
      copy.elements.forEach((e) => { e.id = uid(); });
      this.data.slides.splice(i + 1, 0, copy);
      this.i = i + 1;
      this.renderAll();
      this.ctx.onChange();
    }

    async deleteSlide(i) {
      if (this.data.slides.length === 1) {
        toast('A presentation needs at least one slide', 'err');
        return;
      }
      this.snapshot();
      this.data.slides.splice(i, 1);
      this.i = Math.min(this.i, this.data.slides.length - 1);
      this.selected = null;
      this.renderAll();
      this.ctx.onChange();
    }

    moveSlide(from, to) {
      if (to < 0 || to >= this.data.slides.length || from === to) return;
      this.snapshot();
      const [s] = this.data.slides.splice(from, 1);
      this.data.slides.splice(to, 0, s);
      this.i = to;
      this.renderAll();
      this.ctx.onChange();
    }

    // ---- elements -----------------------------------------------------------
    addElement(kind) {
      this.snapshot();
      let e;
      if (kind === 'text') {
        e = textEl({ x: 140, y: 220, w: 480, h: 80, text: 'New text box', size: 28 });
      } else if (kind === 'line') {
        e = { id: uid(), type: 'shape', shape: 'line', x: 180, y: 280, w: 600, h: 0, stroke: 4, strokeColor: null };
      } else {
        e = {
          id: uid(), type: 'shape', shape: kind === 'ellipse' ? 'ellipse' : 'rect',
          x: 340, y: 190, w: 280, h: 170, fill: null, radius: kind === 'rect' ? 8 : 0,
        };
      }
      this.slide.elements.push(e);
      this.selected = e.id;
      this.renderAll();
      this.ctx.onChange();
    }

    async addImage() {
      const p = await window.forge.importDialog({
        title: 'Insert image',
        filters: [{ name: 'Images', extensions: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg'] }],
      });
      if (!p) return;
      const file = await window.forge.readBinary(p);
      const ext = p.split('.').pop().toLowerCase();
      const mime = ext === 'svg' ? 'image/svg+xml' : ext === 'jpg' ? 'image/jpeg' : 'image/' + ext;
      const src = `data:${mime};base64,${file.base64}`;

      // Size the frame to the image's own aspect ratio before it lands.
      const probe = new Image();
      probe.onload = () => {
        const ratio = probe.width / probe.height || 1.5;
        let w = Math.min(600, probe.width);
        let h = w / ratio;
        if (h > 420) { h = 420; w = h * ratio; }
        this.snapshot();
        const e = { id: uid(), type: 'image', src, x: (W - w) / 2, y: (H - h) / 2, w: Math.round(w), h: Math.round(h), fit: 'contain' };
        this.slide.elements.push(e);
        this.selected = e.id;
        this.renderAll();
        this.ctx.onChange();
      };
      probe.onerror = () => toast('That image could not be read', 'err');
      probe.src = src;
    }

    reorderElement(dir) {
      const e = this.element(this.selected);
      if (!e) return;
      this.snapshot();
      const list = this.slide.elements;
      const i = list.indexOf(e);
      list.splice(i, 1);
      if (dir > 0) list.push(e);
      else list.unshift(e);
      this.renderAll();
      this.ctx.onChange();
    }

    setProp(prop, value) {
      const e = this.element(this.selected);
      if (!e) { toast('Select something first'); return; }
      this.snapshot();
      e[prop] = value;
      this.renderAll();
      this.ctx.onChange();
    }
    toggleProp(prop) {
      const e = this.element(this.selected);
      if (!e) { toast('Select something first'); return; }
      this.setProp(prop, !e[prop]);
    }
    setColor(c) {
      const e = this.element(this.selected);
      if (!e) { toast('Select something first'); return; }
      this.snapshot();
      if (e.type === 'text') e.color = c;
      else if (e.shape === 'line') e.strokeColor = c;
      else e.fill = c;
      this.renderAll();
      this.ctx.onChange();
    }

    deleteSelected() {
      const e = this.element(this.selected);
      if (!e) return;
      this.snapshot();
      this.slide.elements = this.slide.elements.filter((x) => x.id !== e.id);
      this.selected = null;
      this.renderAll();
      this.ctx.onChange();
    }

    // ---- stage interaction --------------------------------------------------
    onStageMouseDown(e) {
      if (this.editingEl && !this.editingEl.contains(e.target)) this.endTextEdit();

      const handle = e.target.dataset && e.target.dataset.handle;
      if (handle) { this.startResize(e, handle); return; }

      const node = e.target.closest('.el');
      if (!node) {
        this.selected = null;
        this.renderStage();
        this.host.focus();
        return;
      }
      if (this.editingEl === node) return; // clicking inside the text being edited

      this.selected = node.dataset.id;
      this.renderStage();
      this.host.focus();
      this.startMove(e);
    }

    startMove(ev) {
      const e = this.element(this.selected);
      if (!e) return;
      const scale = this.scale || 1;
      const sx = ev.clientX, sy = ev.clientY;
      const ox = e.x, oy = e.y;
      let moved = false;
      const node = this.stage.querySelector(`[data-id="${e.id}"]`);

      const move = (mv) => {
        const dx = (mv.clientX - sx) / scale;
        const dy = (mv.clientY - sy) / scale;
        if (!moved && Math.abs(dx) + Math.abs(dy) < 2) return;
        if (!moved) { moved = true; this.snapshot(); }
        // Shift constrains to one axis, as in every other design tool.
        e.x = Math.round(mv.shiftKey && Math.abs(dx) < Math.abs(dy) ? ox : ox + dx);
        e.y = Math.round(mv.shiftKey && Math.abs(dy) < Math.abs(dx) ? oy : oy + dy);
        node.style.left = e.x + 'px';
        node.style.top = e.y + 'px';
      };
      const up = () => {
        document.removeEventListener('mousemove', move);
        document.removeEventListener('mouseup', up);
        if (moved) { this.renderRail(); this.ctx.onChange(); }
      };
      document.addEventListener('mousemove', move);
      document.addEventListener('mouseup', up);
      ev.preventDefault();
    }

    startResize(ev, handle) {
      const e = this.element(this.selected);
      if (!e) return;
      ev.preventDefault();
      ev.stopPropagation();
      const scale = this.scale || 1;
      const sx = ev.clientX, sy = ev.clientY;
      const o = { x: e.x, y: e.y, w: e.w, h: e.h };
      const node = this.stage.querySelector(`[data-id="${e.id}"]`);
      let started = false;

      const move = (mv) => {
        const dx = (mv.clientX - sx) / scale;
        const dy = (mv.clientY - sy) / scale;
        if (!started) { started = true; this.snapshot(); }
        let { x, y, w, h } = o;
        if (handle.includes('e')) w = Math.max(20, o.w + dx);
        if (handle.includes('s')) h = Math.max(e.type === 'shape' && e.shape === 'line' ? 0 : 20, o.h + dy);
        if (handle.includes('w')) { w = Math.max(20, o.w - dx); x = o.x + (o.w - w); }
        if (handle.includes('n')) { h = Math.max(20, o.h - dy); y = o.y + (o.h - h); }
        Object.assign(e, { x: Math.round(x), y: Math.round(y), w: Math.round(w), h: Math.round(h) });
        Object.assign(node.style, { left: e.x + 'px', top: e.y + 'px', width: e.w + 'px', height: e.h + 'px' });
      };
      const up = () => {
        document.removeEventListener('mousemove', move);
        document.removeEventListener('mouseup', up);
        if (started) { this.renderRail(); this.ctx.onChange(); }
      };
      document.addEventListener('mousemove', move);
      document.addEventListener('mouseup', up);
    }

    onStageDblClick(e) {
      const node = e.target.closest('.el');
      if (!node) return;
      const model = this.element(node.dataset.id);
      if (!model || model.type !== 'text') return;
      this.beginTextEdit(node, model);
    }

    beginTextEdit(node, model) {
      this.editingEl = node;
      node.setAttribute('contenteditable', 'plaintext-only');
      node.focus();
      // Put the caret where the user clicked rather than at the start.
      const sel = window.getSelection();
      const range = document.createRange();
      range.selectNodeContents(node);
      range.collapse(false);
      sel.removeAllRanges();
      sel.addRange(range);

      const finish = () => this.endTextEdit();
      node.addEventListener('blur', finish, { once: true });
      node.addEventListener('keydown', (ev) => {
        ev.stopPropagation();
        if (ev.key === 'Escape') { ev.preventDefault(); node.blur(); }
      });
      this.editingModel = model;
    }

    endTextEdit() {
      if (!this.editingEl) return;
      const node = this.editingEl;
      const model = this.editingModel;
      this.editingEl = null;
      this.editingModel = null;
      node.removeAttribute('contenteditable');
      const text = node.innerText.replace(/\n$/, '');
      if (model && text !== model.text) {
        this.snapshot();
        model.text = text;
        this.ctx.onChange();
      }
      this.renderAll();
      this.host.focus();
    }

    onStageContextMenu(e) {
      e.preventDefault();
      const node = e.target.closest('.el');
      if (node) {
        this.selected = node.dataset.id;
        this.renderStage();
        menu(e.clientX, e.clientY, [
          { label: 'Bring to front', onClick: () => this.reorderElement(1) },
          { label: 'Send to back', onClick: () => this.reorderElement(-1) },
          '-',
          { label: 'Duplicate', onClick: () => this.duplicateElement() },
          { label: 'Delete', danger: true, hint: 'Del', onClick: () => this.deleteSelected() },
        ]);
        return;
      }
      menu(e.clientX, e.clientY, [
        { label: 'Add text box', onClick: () => this.addElement('text') },
        { label: 'Add rectangle', onClick: () => this.addElement('rect') },
        { label: 'Add image…', onClick: () => this.addImage() },
        '-',
        { label: 'New slide', hint: 'Ctrl+M', onClick: () => this.addSlide('titleContent') },
      ]);
    }

    duplicateElement() {
      const e = this.element(this.selected);
      if (!e) return;
      this.snapshot();
      const copy = JSON.parse(JSON.stringify(e));
      copy.id = uid();
      copy.x += 20;
      copy.y += 20;
      this.slide.elements.push(copy);
      this.selected = copy.id;
      this.renderAll();
      this.ctx.onChange();
    }

    // ---- keyboard -----------------------------------------------------------
    onKeyDown(e) {
      if (this.editingEl) return;
      const ctrl = e.ctrlKey || e.metaKey;

      if (ctrl) {
        const k = e.key.toLowerCase();
        if (k === 'z') { e.preventDefault(); this.undo(); return; }
        if (k === 'y') { e.preventDefault(); this.redo(); return; }
        if (k === 'd') { e.preventDefault(); this.duplicateElement(); return; }
        if (k === 'm') { e.preventDefault(); this.addSlide('titleContent'); return; }
        return;
      }

      if (e.key === 'Delete' || e.key === 'Backspace') {
        if (this.selected) { e.preventDefault(); this.deleteSelected(); }
        return;
      }
      if (e.key === 'Escape') { this.selected = null; this.renderStage(); return; }
      if (e.key === 'F5') { e.preventDefault(); this.present(); return; }
      if (e.key === 'Enter' && this.selected) {
        const node = this.stage.querySelector(`[data-id="${this.selected}"]`);
        const model = this.element(this.selected);
        if (node && model && model.type === 'text') { e.preventDefault(); this.beginTextEdit(node, model); }
        return;
      }

      const nudge = { ArrowUp: [0, -1], ArrowDown: [0, 1], ArrowLeft: [-1, 0], ArrowRight: [1, 0] }[e.key];
      if (nudge) {
        e.preventDefault();
        if (this.selected) {
          const el2 = this.element(this.selected);
          const step = e.shiftKey ? 10 : 1;
          this.snapshot();
          el2.x += nudge[0] * step;
          el2.y += nudge[1] * step;
          this.renderStage();
          this.renderRail();
          this.ctx.onChange();
        } else {
          // Nothing selected: arrows move between slides.
          if (nudge[1] === 1) this.goTo(this.i + 1);
          else if (nudge[1] === -1) this.goTo(this.i - 1);
        }
        return;
      }
      if (e.key === 'PageDown') { e.preventDefault(); this.goTo(this.i + 1); }
      if (e.key === 'PageUp') { e.preventDefault(); this.goTo(this.i - 1); }
    }

    // ---- present mode -------------------------------------------------------
    present(fromIndex) {
      let index = fromIndex === undefined ? this.i : fromIndex;
      const overlay = el('div', { class: 'present-overlay' });
      const stage = el('div', { class: 'present-stage' });
      overlay.appendChild(stage);

      const counter = el('span', { text: '' });
      const hud = el('div', { class: 'present-hud' }, [
        counter,
        el('button', { text: 'Exit  (Esc)', onclick: () => close() }),
      ]);

      const fit = () => {
        const scale = Math.min(window.innerWidth / W, window.innerHeight / H);
        stage.style.transform = `scale(${scale})`;
      };
      const show = () => {
        index = Math.max(0, Math.min(this.data.slides.length - 1, index));
        renderSlide(stage, this.data.slides[index], this.theme);
        counter.textContent = `${index + 1} / ${this.data.slides.length}`;
      };
      const close = () => {
        document.removeEventListener('keydown', onKey, true);
        window.removeEventListener('resize', fit);
        overlay.remove();
        hud.remove();
        if (document.fullscreenElement) document.exitFullscreen().catch(() => {});
        this.i = index;
        this.renderAll();
        this.host.focus();
      };
      const onKey = (e) => {
        e.stopPropagation();
        if (['ArrowRight', 'ArrowDown', ' ', 'PageDown', 'Enter'].includes(e.key)) { e.preventDefault(); index++; show(); }
        else if (['ArrowLeft', 'ArrowUp', 'PageUp', 'Backspace'].includes(e.key)) { e.preventDefault(); index--; show(); }
        else if (e.key === 'Home') { index = 0; show(); }
        else if (e.key === 'End') { index = this.data.slides.length - 1; show(); }
        else if (e.key === 'Escape') { e.preventDefault(); close(); }
      };

      overlay.addEventListener('click', (e) => {
        if (e.target === overlay || e.target === stage) { index++; show(); }
      });
      overlay.addEventListener('contextmenu', (e) => { e.preventDefault(); index--; show(); });

      document.body.append(overlay, hud);
      document.addEventListener('keydown', onKey, true);
      window.addEventListener('resize', fit);
      document.documentElement.requestFullscreen().catch(() => {});
      fit();
      show();
    }

    // ---- shell interface ----------------------------------------------------
    focus() { this.host.focus(); }

    serialize() {
      this.data.active = this.i;
      return this.data;
    }

    command(name) {
      switch (name) {
        case 'present': this.present(); return true;
        case 'insert-slide': this.addSlide('titleContent'); return true;
        case 'insert-image': this.addImage(); return true;
        default: return false;
      }
    }

    status() {
      const e = this.element(this.selected);
      return {
        left: `Slide ${this.i + 1} of ${this.data.slides.length}` +
          (e ? ` · ${e.type === 'text' ? 'Text box' : e.type === 'image' ? 'Image' : 'Shape'} ${e.w}×${e.h}` : ''),
        right: `Presentation · ${this.data.theme}`,
      };
    }

    toPlainText() {
      return this.data.slides
        .map((s, i) => `--- Slide ${i + 1} ---\n` +
          s.elements.filter((e) => e.type === 'text').map((e) => e.text).join('\n'))
        .join('\n\n');
    }

    /** One slide per printed page, at slide aspect ratio. */
    toPrintHTML(title) {
      const theme = this.theme;
      const slides = this.data.slides.map((slide) => {
        const inner = slide.elements.map((e) => {
          const base = `position:absolute;left:${e.x}px;top:${e.y}px;width:${e.w}px;height:${e.h}px;`;
          if (e.type === 'text') {
            return `<div style="${base}font-size:${e.size}px;font-weight:${e.bold ? 700 : 400};font-style:${e.italic ? 'italic' : 'normal'};text-align:${e.align || 'left'};color:${e.color || theme.ink};font-family:${e.font || theme.font};line-height:1.25;white-space:pre-wrap;word-break:break-word;display:flex;flex-direction:column;justify-content:${e.valign === 'middle' ? 'center' : e.valign === 'bottom' ? 'flex-end' : 'flex-start'};padding:6px 8px;box-sizing:border-box;">${escapeHtml(e.text)}</div>`;
          }
          if (e.type === 'image') {
            return `<div style="${base}"><img src="${e.src}" style="width:100%;height:100%;object-fit:${e.fit || 'contain'}" /></div>`;
          }
          if (e.shape === 'line') {
            return `<div style="${base}height:0;border-top:${e.stroke || 3}px solid ${e.strokeColor || theme.accent};"></div>`;
          }
          const fill = e.fill === null ? 'transparent' : (e.fill || theme.accent);
          const radius = e.shape === 'ellipse' ? '50%' : (e.radius || 0) + 'px';
          const border = e.strokeColor ? `border:${e.stroke || 2}px solid ${e.strokeColor};` : '';
          return `<div style="${base}background:${fill};border-radius:${radius};${border}box-sizing:border-box;"></div>`;
        }).join('');
        return `<div class="slide" style="background:${slide.bg || theme.bg}">${inner}</div>`;
      }).join('');

      return `<!doctype html><html><head><meta charset="utf-8"><title>${escapeHtml(title || 'Presentation')}</title>
<style>
  @page { size: ${W}px ${H}px; margin: 0; }
  body { margin: 0; font-family: ${theme.font}; background: #fff; }
  .slide { position: relative; width: ${W}px; height: ${H}px; overflow: hidden; break-after: page; page-break-after: always; }
  .slide:last-child { break-after: auto; page-break-after: auto; }
</style></head><body>${slides}</body></html>`;
    }

    destroy() {
      if (this.resizeObserver) this.resizeObserver.disconnect();
    }
  }

  global.SlideEditor = SlideEditor;
  global.renderSlide = renderSlide;
})(window);
/* OfficeForger — application chrome and the three editors.
   One stylesheet, organised: tokens, shell, start screen, shared controls,
   then documents, spreadsheets, presentations, then modals and print. */

/* ---------------------------------------------------------------- tokens -- */
:root {
  --bg: #eef0f4;
  --panel: #ffffff;
  --panel-2: #f7f8fa;
  --line: #dcdfe6;
  --line-soft: #e9ebf0;
  --ink: #1f2430;
  --ink-2: #5a6274;
  --ink-3: #8b93a5;
  --accent: #2f6fd0;
  --accent-soft: #e6efff;
  --doc: #2b6cb0;
  --sheet: #17794a;
  --slide: #b0651a;
  --danger: #c0392b;
  --shadow: 0 1px 3px rgba(20, 25, 40, .10), 0 6px 20px rgba(20, 25, 40, .07);
  --radius: 7px;
  --ui: -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: "Cascadia Mono", "Consolas", "SF Mono", "DejaVu Sans Mono", monospace;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  font-family: var(--ui);
  font-size: 13px;
  color: var(--ink);
  background: var(--bg);
  -webkit-user-select: none;
  user-select: none;
}

button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
.hidden { display: none !important; }

::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #c3c8d4; border: 3px solid transparent; background-clip: content-box; border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: #a9b0c0; background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* ----------------------------------------------------------------- shell -- */
#app { display: flex; flex-direction: column; height: 100vh; }

#tabstrip {
  display: flex;
  align-items: stretch;
  gap: 2px;
  padding: 5px 6px 0;
  background: linear-gradient(#e3e6ed, #dde1e9);
  border-bottom: 1px solid var(--line);
  min-height: 34px;
  flex: none;
}
#tabs { display: flex; gap: 2px; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
#tabs::-webkit-scrollbar { height: 0; }
.tabstrip-spacer { flex: 1; }

.tab {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 0 8px 0 10px;
  height: 29px;
  max-width: 230px;
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: 7px 7px 0 0;
  background: rgba(255, 255, 255, .45);
  color: var(--ink-2);
  cursor: default;
  white-space: nowrap;
  flex: none;
}
.tab:hover { background: rgba(255, 255, 255, .75); }
.tab.active {
  background: var(--panel);
  border-color: var(--line);
  color: var(--ink);
  font-weight: 600;
}
.tab .tab-kind { font-size: 12px; line-height: 1; }
.tab .tab-kind.doc { color: var(--doc); }
.tab .tab-kind.sheet { color: var(--sheet); }
.tab .tab-kind.slide { color: var(--slide); }
.tab .tab-name { overflow: hidden; text-overflow: ellipsis; }
.tab .tab-dot { color: var(--accent); font-size: 15px; line-height: 0; }
.tab .tab-close {
  border: 0; background: none; padding: 0 2px; border-radius: 4px;
  color: var(--ink-3); cursor: pointer; font-size: 14px; line-height: 1;
}
.tab .tab-close:hover { background: rgba(0, 0, 0, .09); color: var(--ink); }

.tabstrip-btn {
  border: 0; background: none; color: var(--ink-2);
  padding: 0 9px; margin-bottom: 4px; border-radius: 6px;
  cursor: pointer; font-size: 15px; line-height: 1;
}
.tabstrip-btn:hover { background: rgba(255, 255, 255, .8); color: var(--ink); }

#workspace { flex: 1; position: relative; overflow: hidden; background: var(--bg); }
.editor-host { position: absolute; inset: 0; display: flex; flex-direction: column; }
.editor-host.inactive { display: none; }

#statusbar {
  flex: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  height: 24px;
  padding: 0 12px;
  background: var(--panel-2);
  border-top: 1px solid var(--line);
  color: var(--ink-2);
  font-size: 11.5px;
}
#statusbar span { display: flex; gap: 16px; align-items: center; }

/* ----------------------------------------------------------- start screen -- */
.start { position: absolute; inset: 0; overflow: auto; z-index: 5; background: var(--bg); }
.start.hidden { display: none; }
.start-inner { max-width: 880px; margin: 0 auto; padding: 46px 32px 40px; }

.start-brand { display: flex; gap: 18px; align-items: flex-start; margin-bottom: 30px; }
.start-logo {
  width: 52px; height: 52px; flex: none; border-radius: 12px;
  background: linear-gradient(140deg, #33405c, #1d2536);
  color: #fff; font-weight: 700; font-size: 19px; letter-spacing: .5px;
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow);
}
.start h1 { margin: 2px 0 5px; font-size: 25px; letter-spacing: -.3px; }
.start-sub { margin: 0; color: var(--ink-2); max-width: 60ch; line-height: 1.5; }

.start-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 24px; }
.start-card {
  display: flex; flex-direction: column; gap: 3px;
  padding: 18px 16px 15px; text-align: left; cursor: pointer;
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 1px 2px rgba(20, 25, 40, .05);
  transition: transform .08s ease, box-shadow .12s ease, border-color .12s ease;
}
.start-card:hover { transform: translateY(-2px); box-shadow: var(--shadow); border-color: #c6ccda; }
.card-icon { font-size: 26px; line-height: 1; margin-bottom: 8px; }
.card-icon.doc { color: var(--doc); }
.card-icon.sheet { color: var(--sheet); }
.card-icon.slide { color: var(--slide); }
.card-title { font-weight: 650; font-size: 14px; }
.card-sub { color: var(--ink-2); font-size: 12px; }
.card-key { color: var(--ink-3); font-size: 11px; margin-top: 7px; font-family: var(--mono); }

.start-row { display: flex; align-items: center; gap: 14px; margin-bottom: 32px; }
.start-hint { color: var(--ink-3); }

.start-recent-head { display: flex; justify-content: space-between; align-items: baseline; border-bottom: 1px solid var(--line); padding-bottom: 6px; }
.start-recent h2 { font-size: 12px; text-transform: uppercase; letter-spacing: .8px; color: var(--ink-2); margin: 0; }
.linkbtn { border: 0; background: none; color: var(--accent); cursor: pointer; padding: 2px 4px; border-radius: 4px; }
.linkbtn:hover { background: var(--accent-soft); }
.recent-list { list-style: none; margin: 6px 0 0; padding: 0; }
.recent-list li {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 7px; cursor: default;
}
.recent-list li:hover { background: rgba(255, 255, 255, .8); }
.recent-list .rk { width: 16px; text-align: center; }
.recent-list .rk.doc { color: var(--doc); }
.recent-list .rk.sheet { color: var(--sheet); }
.recent-list .rk.slide { color: var(--slide); }
.recent-list .rn { font-weight: 550; }
.recent-list .rp { color: var(--ink-3); font-size: 11.5px; margin-left: auto; max-width: 46ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.recent-empty { color: var(--ink-3); padding: 12px 10px; }
.start-foot { margin-top: 36px; color: var(--ink-3); font-size: 11.5px; }

/* ------------------------------------------------------- shared controls -- */
.toolbar {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px;
  padding: 5px 8px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}
.tb-sep { width: 1px; align-self: stretch; margin: 3px 5px; background: var(--line); }
.tb-spacer { flex: 1; }

.tbtn {
  min-width: 27px; height: 27px;
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  padding: 0 6px;
  border: 1px solid transparent; border-radius: 5px;
  background: none; color: var(--ink); cursor: pointer;
  font-size: 13px; line-height: 1; white-space: nowrap;
}
.tbtn:hover { background: var(--panel-2); border-color: var(--line-soft); }
.tbtn:active { background: #e8ebf1; }
.tbtn.on { background: var(--accent-soft); border-color: #bfd6f7; color: #1b4f9e; }
.tbtn[disabled] { opacity: .4; cursor: default; }
.tbtn[disabled]:hover { background: none; border-color: transparent; }
.tbtn.wide { padding: 0 10px; }
.tbtn b { font-weight: 700; }
.tbtn i { font-style: italic; font-family: Georgia, serif; }
.tbtn u { text-decoration: underline; }
.tbtn s { text-decoration: line-through; }

select.tsel, input.tinput {
  height: 27px;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--panel);
  padding: 0 6px;
  cursor: pointer;
}
select.tsel:focus, input.tinput:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
input.tinput { cursor: text; -webkit-user-select: text; user-select: text; }
.tsel.w-font { width: 128px; }
.tsel.w-size { width: 62px; }
.tsel.w-style { width: 108px; }

.swatch-wrap { position: relative; display: inline-flex; }
.swatch-btn { flex-direction: column; gap: 1px; padding: 0 5px; }
.swatch-bar { width: 15px; height: 3px; border-radius: 1px; background: #000; }
.palette {
  position: absolute; top: 30px; left: 0; z-index: 60;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: var(--shadow); padding: 8px;
  display: grid; grid-template-columns: repeat(10, 18px); gap: 4px;
}
.palette .sw { width: 18px; height: 18px; border-radius: 3px; border: 1px solid rgba(0, 0, 0, .16); cursor: pointer; }
.palette .sw:hover { transform: scale(1.16); }
.palette .sw-none {
  grid-column: 1 / -1; height: 22px; border-radius: 4px; border: 1px solid var(--line);
  background: var(--panel-2); cursor: pointer; font-size: 11.5px;
}

.btn {
  height: 30px; padding: 0 14px; border-radius: 6px;
  border: 1px solid var(--line); background: var(--panel);
  cursor: pointer; font-weight: 550;
}
.btn:hover { background: var(--panel-2); }
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-primary:hover { background: #2a63bc; }
.btn-danger { color: var(--danger); }

/* find & replace bar, shared by documents and spreadsheets */
.findbar {
  position: absolute; top: 8px; right: 18px; z-index: 40;
  display: flex; align-items: center; gap: 6px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 8px; box-shadow: var(--shadow); padding: 7px 9px;
}
.findbar input { width: 168px; }
.findbar .count { color: var(--ink-3); min-width: 62px; text-align: center; font-variant-numeric: tabular-nums; }
::highlight(forge-find) { background: #ffe58a; color: #000; }
::highlight(forge-find-active) { background: #ffb01f; color: #000; }

/* ------------------------------------------------------------- documents -- */
.doc-scroll { flex: 1; overflow: auto; padding: 26px 0 60px; position: relative; }
.doc-zoom { transform-origin: top center; transition: transform .08s ease; }
.page {
  width: 8.5in;
  min-height: 11in;
  margin: 0 auto 22px;
  padding: 1in;
  background: #fff;
  box-shadow: var(--shadow);
  border-radius: 2px;
  outline: none;
  -webkit-user-select: text;
  user-select: text;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 11pt;
  line-height: 1.5;
  color: #14181f;
  cursor: text;
}
.page:focus-visible { box-shadow: var(--shadow), 0 0 0 2px var(--accent-soft); }
.page > *:first-child { margin-top: 0; }
.page h1 { font-size: 22pt; font-weight: 700; margin: 0 0 .35em; line-height: 1.22; }
.page h2 { font-size: 16pt; font-weight: 700; margin: 1em 0 .3em; line-height: 1.25; }
.page h3 { font-size: 13pt; font-weight: 700; margin: 1em 0 .3em; }
.page h4 { font-size: 11.5pt; font-weight: 700; margin: 1em 0 .3em; }
.page p { margin: 0 0 .55em; }
.page ul, .page ol { margin: 0 0 .6em; padding-left: 1.9em; }
.page li { margin-bottom: .18em; }
.page blockquote {
  margin: .7em 0; padding: .1em 0 .1em 1em;
  border-left: 3px solid #c9d2e0; color: #47526a; font-style: italic;
}
.page a { color: #1a56b0; }
.page img { max-width: 100%; height: auto; }
.page hr { border: 0; border-top: 1px solid #ccd2dd; margin: 1.1em 0; }
.page table { border-collapse: collapse; margin: .7em 0; width: 100%; }
.page table td, .page table th { border: 1px solid #b9c0ce; padding: 5px 8px; vertical-align: top; min-width: 24px; }
.page table th { background: #f0f2f6; font-weight: 650; }
.page pre {
  font-family: var(--mono); font-size: 10pt; background: #f4f5f8;
  border: 1px solid #e2e5ec; border-radius: 5px; padding: 9px 11px; overflow-x: auto;
}
.page code { font-family: var(--mono); font-size: .92em; background: #f1f3f7; padding: 1px 4px; border-radius: 3px; }
.page .pagebreak {
  height: 0; border-top: 2px dashed #b9c0ce; margin: 1.4em 0;
  position: relative;
}
.page .pagebreak::after {
  content: "Page break"; position: absolute; right: 0; top: -8px;
  background: #fff; padding: 0 6px; font: 9pt var(--ui); color: var(--ink-3);
}

/* ---------------------------------------------------------- spreadsheets -- */
.sheet-formulabar {
  flex: none; display: flex; align-items: stretch; gap: 0;
  background: var(--panel); border-bottom: 1px solid var(--line);
  padding: 4px 8px 5px;
}
.namebox {
  width: 88px; height: 26px; text-align: center; font-weight: 600;
  border: 1px solid var(--line); border-radius: 5px 0 0 5px; border-right: none;
  background: var(--panel-2);
  -webkit-user-select: text; user-select: text;
}
.fx-label {
  display: flex; align-items: center; padding: 0 9px;
  border: 1px solid var(--line); border-right: none;
  background: var(--panel-2); color: var(--ink-2);
  font-style: italic; font-family: Georgia, serif;
}
.fx-input {
  flex: 1; height: 26px; padding: 0 9px;
  border: 1px solid var(--line); border-radius: 0 5px 5px 0;
  font-family: var(--mono); font-size: 12.5px;
  -webkit-user-select: text; user-select: text;
}
.fx-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }

.grid-wrap { flex: 1; overflow: auto; position: relative; background: #fff; }
table.grid {
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
  font-size: 12.5px;
  background: #fff;
}
table.grid th, table.grid td {
  border-right: 1px solid #e4e7ee;
  border-bottom: 1px solid #e4e7ee;
  height: 22px;
  padding: 0 4px;
  overflow: hidden;
  white-space: nowrap;
  font-weight: 400;
  vertical-align: middle;
}
/* Headers stay put while the grid scrolls under them. */
table.grid thead th {
  position: sticky; top: 0; z-index: 3;
  background: #f2f4f8; color: var(--ink-2);
  text-align: center; font-weight: 600; font-size: 11.5px;
  border-bottom: 1px solid #ccd2dd;
  cursor: default;
}
table.grid tbody th.rowhead {
  position: sticky; left: 0; z-index: 2;
  background: #f2f4f8; color: var(--ink-2);
  text-align: center; font-weight: 600; font-size: 11.5px;
  border-right: 1px solid #ccd2dd;
  width: 46px; min-width: 46px;
  cursor: default;
}
table.grid thead th.corner { position: sticky; left: 0; z-index: 4; width: 46px; min-width: 46px; }
table.grid th.selected-head { background: #dbe6f8; color: #1b4f9e; }

table.grid td {
  cursor: cell;
  -webkit-user-select: none; user-select: none;
  text-overflow: clip;
}
table.grid td.num { text-align: right; font-variant-numeric: tabular-nums; }
table.grid td.err { color: var(--danger); }
table.grid td.in-range { background: rgba(47, 111, 208, .10); }
table.grid td.cursor {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  position: relative;
  z-index: 1;
}
table.grid td.cursor::after {
  content: ""; position: absolute; right: -3px; bottom: -3px;
  width: 6px; height: 6px; background: var(--accent);
  border: 1px solid #fff; border-radius: 1px; cursor: crosshair;
}
table.grid td.fill-preview { outline: 1px dashed var(--accent); outline-offset: -1px; }
table.grid td.match { box-shadow: inset 0 0 0 2px #ffb01f; }

.cell-editor {
  position: absolute; z-index: 20;
  border: 2px solid var(--accent);
  padding: 0 3px;
  font: inherit; font-size: 12.5px;
  background: #fff;
  outline: none;
  min-width: 40px;
  -webkit-user-select: text; user-select: text;
}

.sheet-tabs {
  flex: none; display: flex; align-items: center; gap: 3px;
  padding: 4px 8px; background: var(--panel-2); border-top: 1px solid var(--line);
  overflow-x: auto;
}
.sheet-tab {
  padding: 3px 11px; border-radius: 5px 5px 0 0;
  border: 1px solid transparent; border-bottom: none;
  background: rgba(0, 0, 0, .035); color: var(--ink-2);
  cursor: default; white-space: nowrap;
}
.sheet-tab:hover { background: rgba(0, 0, 0, .06); }
.sheet-tab.active { background: #fff; border-color: var(--line); color: var(--sheet); font-weight: 650; }
.sheet-add { border: 0; background: none; cursor: pointer; color: var(--ink-2); padding: 2px 8px; border-radius: 5px; font-size: 15px; }
.sheet-add:hover { background: rgba(0, 0, 0, .06); }

/* floating charts over the grid */
.chart-box {
  position: absolute; z-index: 10;
  background: #fff; border: 1px solid var(--line); border-radius: 8px;
  box-shadow: var(--shadow); overflow: hidden;
}
.chart-box.sel { outline: 2px solid var(--accent); outline-offset: -1px; }
.chart-box .chart-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 3px 6px; background: var(--panel-2); border-bottom: 1px solid var(--line-soft);
  cursor: move; font-size: 11.5px; color: var(--ink-2);
}
.chart-box .chart-head button { border: 0; background: none; cursor: pointer; color: var(--ink-3); padding: 0 4px; }
.chart-box .chart-head button:hover { color: var(--danger); }
.chart-box canvas { display: block; }
.chart-box .chart-resize {
  position: absolute; right: 0; bottom: 0; width: 14px; height: 14px;
  cursor: nwse-resize; background: linear-gradient(135deg, transparent 50%, #c3c8d4 50%);
}

/* --------------------------------------------------------- presentations -- */
.slide-body { flex: 1; display: flex; overflow: hidden; }
.slide-rail {
  width: 176px; flex: none; overflow-y: auto;
  background: var(--panel-2); border-right: 1px solid var(--line);
  padding: 9px 8px 20px;
}
.thumb-item { display: flex; gap: 7px; margin-bottom: 9px; align-items: flex-start; }
.thumb-num { width: 14px; text-align: right; color: var(--ink-3); font-size: 11px; padding-top: 2px; }
.thumb {
  flex: 1; aspect-ratio: 16 / 9; border-radius: 4px; overflow: hidden;
  border: 2px solid transparent; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .12);
  cursor: default; position: relative;
}
.thumb.active { border-color: var(--accent); }
.thumb.dragging { opacity: .45; }
.thumb-inner { position: absolute; top: 0; left: 0; width: 960px; height: 540px; transform-origin: top left; }

.slide-stage-wrap { flex: 1; overflow: auto; display: flex; align-items: flex-start; justify-content: center; padding: 22px; }
.slide-stage-holder { flex: none; position: relative; }
.slide-stage {
  width: 960px; height: 540px; position: absolute; top: 0; left: 0;
  background: #fff; box-shadow: var(--shadow); overflow: hidden;
  transform-origin: top left;
}
.el {
  position: absolute; box-sizing: border-box;
  -webkit-user-select: none; user-select: none;
}
.el.text { padding: 6px 8px; overflow: hidden; }
.el.text[contenteditable="true"] { -webkit-user-select: text; user-select: text; cursor: text; outline: none; }
.el.selected { outline: 2px solid var(--accent); outline-offset: 1px; }
.el .handle {
  position: absolute; width: 9px; height: 9px; background: #fff;
  border: 1.5px solid var(--accent); border-radius: 2px; z-index: 5;
}
.el .handle.nw { left: -6px; top: -6px; cursor: nwse-resize; }
.el .handle.ne { right: -6px; top: -6px; cursor: nesw-resize; }
.el .handle.sw { left: -6px; bottom: -6px; cursor: nesw-resize; }
.el .handle.se { right: -6px; bottom: -6px; cursor: nwse-resize; }

.present-overlay {
  position: fixed; inset: 0; z-index: 900; background: #000;
  display: flex; align-items: center; justify-content: center;
}
.present-stage { width: 960px; height: 540px; position: relative; background: #fff; transform-origin: center; }
.present-hud {
  position: fixed; bottom: 14px; right: 18px; z-index: 901;
  color: rgba(255, 255, 255, .6); font-size: 12px;
  display: flex; gap: 14px; align-items: center;
}
.present-hud button { background: rgba(255, 255, 255, .14); border: 0; color: #fff; border-radius: 5px; padding: 4px 10px; cursor: pointer; }

/* ------------------------------------------------------- modals & toasts -- */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 800;
  background: rgba(18, 22, 32, .38);
  display: flex; align-items: center; justify-content: center;
}
.modal {
  background: var(--panel); border-radius: 11px; box-shadow: 0 18px 48px rgba(15, 20, 32, .3);
  min-width: 340px; max-width: 560px; max-height: 82vh; overflow: auto;
  padding: 20px 22px 18px;
}
.modal h3 { margin: 0 0 4px; font-size: 15.5px; }
/* pre-line so a message can use \n to list things without building DOM for it */
.modal .modal-sub { color: var(--ink-2); margin: 0 0 14px; white-space: pre-line; line-height: 1.5; }
.modal label { display: block; margin: 11px 0 4px; font-weight: 550; }
.modal input[type=text], .modal input[type=number], .modal select, .modal textarea {
  width: 100%; height: 31px; padding: 0 9px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--panel);
  -webkit-user-select: text; user-select: text;
}
.modal textarea { height: 92px; padding: 7px 9px; resize: vertical; font-family: var(--mono); font-size: 12px; }
.modal input:focus, .modal select:focus, .modal textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.modal .row { display: flex; gap: 10px; }
.modal .row > * { flex: 1; }
.modal .actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; }
.modal .check { display: flex; align-items: center; gap: 7px; margin-top: 10px; font-weight: 400; }
.modal .check input { width: auto; height: auto; }
.modal .keys { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; align-items: baseline; }
.modal .keys kbd {
  font-family: var(--mono); font-size: 11.5px; background: var(--panel-2);
  border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 4px; padding: 1px 6px; white-space: nowrap;
}
.modal .keys .grp { grid-column: 1 / -1; margin-top: 12px; font-weight: 650; color: var(--ink-2); font-size: 11px; text-transform: uppercase; letter-spacing: .7px; }

#toasts { position: fixed; bottom: 34px; left: 50%; transform: translateX(-50%); z-index: 950; display: flex; flex-direction: column; gap: 8px; align-items: center; pointer-events: none; }
.toast {
  background: #222836; color: #fff; padding: 9px 16px; border-radius: 20px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .28); font-size: 12.5px;
  animation: toast-in .16s ease;
}
.toast.err { background: #8d2b20; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* context menu (spreadsheet rows/columns, slide rail) */
.ctxmenu {
  position: fixed; z-index: 700; min-width: 190px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 8px; box-shadow: var(--shadow); padding: 5px;
}
.ctxmenu button {
  display: flex; justify-content: space-between; gap: 20px; width: 100%;
  border: 0; background: none; text-align: left; padding: 6px 10px;
  border-radius: 5px; cursor: pointer;
}
.ctxmenu button:hover { background: var(--accent-soft); }
.ctxmenu button.danger { color: var(--danger); }
.ctxmenu button.danger:hover { background: #fdecea; }
.ctxmenu .sep { height: 1px; background: var(--line-soft); margin: 5px 4px; }
.ctxmenu .hint { color: var(--ink-3); font-size: 11px; font-family: var(--mono); }

/* drag-and-drop file target */
.drop-veil {
  position: fixed; inset: 0; z-index: 990;
  background: rgba(47, 111, 208, .12);
  border: 3px dashed var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px; font-weight: 600; color: #1b4f9e;
  pointer-events: none;
}
'use strict';
/*
 * OfficeForger — small shared UI kit.
 *
 * Everything the three editors need in common and nothing they don't: element
 * building, modals, toasts, context menus and the colour palette. No framework;
 * the app is small enough that one of these files is cheaper than a dependency.
 */
(function (global) {
  // ---- element building -----------------------------------------------------
  function el(tag, props, children) {
    const node = document.createElement(tag);
    if (props) {
      for (const [k, v] of Object.entries(props)) {
        if (v === null || v === undefined || v === false) continue;
        if (k === 'class') node.className = v;
        else if (k === 'style' && typeof v === 'object') Object.assign(node.style, v);
        else if (k === 'text') node.textContent = v;
        else if (k === 'html') node.innerHTML = v;
        else if (k === 'dataset') Object.assign(node.dataset, v);
        else if (k.startsWith('on') && typeof v === 'function') node.addEventListener(k.slice(2), v);
        else if (k in node && k !== 'list' && typeof v !== 'object') node[k] = v;
        else node.setAttribute(k, v);
      }
    }
    for (const c of [].concat(children === undefined ? [] : children)) {
      if (c === null || c === undefined || c === false) continue;
      node.appendChild(typeof c === 'string' || typeof c === 'number' ? document.createTextNode(String(c)) : c);
    }
    return node;
  }

  /** A toolbar button. `active` is re-read by refresh loops, so keep it cheap. */
  function tbtn(opts) {
    const b = el('button', {
      class: 'tbtn' + (opts.wide ? ' wide' : '') + (opts.class ? ' ' + opts.class : ''),
      title: opts.title || '',
      type: 'button',
      html: opts.html,
      text: opts.html ? undefined : opts.label,
      onclick: opts.onClick,
    });
    // Toolbar clicks must never steal focus — the editor's selection has to survive.
    b.addEventListener('mousedown', (e) => e.preventDefault());
    return b;
  }

  const sep = () => el('div', { class: 'tb-sep' });
  const spacer = () => el('div', { class: 'tb-spacer' });

  // ---- icons ----------------------------------------------------------------
  /*
   * Inline SVG rather than unicode glyphs. The obvious characters for these —
   * ⬱ ⬲ ⇥ ⌫ — either render as arrows that mean nothing to a reader or fall back
   * to a different font per platform and stop lining up. Drawing them removes
   * both problems, and they inherit the button's colour through currentColor.
   */
  const svg = (body, opts) =>
    `<svg viewBox="0 0 16 16" width="15" height="15" aria-hidden="true"${opts || ''}>${body}</svg>`;
  const stroked = (d, width) =>
    svg(`<path d="${d}" fill="none" stroke="currentColor" stroke-width="${width || 1.6}" stroke-linecap="round" stroke-linejoin="round"/>`);

  const ICONS = {
    undo: stroked('M3 8h7a3.5 3.5 0 0 1 0 7H6M5.5 5L2.5 8l3 3'),
    redo: stroked('M13 8H6a3.5 3.5 0 0 0 0 7h4M10.5 5l3 3-3 3'),

    alignLeft: stroked('M2 3.5h12M2 6.8h7M2 10.1h12M2 13.4h7'),
    alignCenter: stroked('M2 3.5h12M4.5 6.8h7M2 10.1h12M4.5 13.4h7'),
    alignRight: stroked('M2 3.5h12M7 6.8h7M2 10.1h12M7 13.4h7'),
    justify: stroked('M2 3.5h12M2 6.8h12M2 10.1h12M2 13.4h12'),

    bulletList: svg(
      '<g fill="currentColor"><circle cx="2.6" cy="4" r="1.3"/><circle cx="2.6" cy="8" r="1.3"/><circle cx="2.6" cy="12" r="1.3"/></g>' +
      '<path d="M6.2 4h8M6.2 8h8M6.2 12h8" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>'),
    numberList: svg(
      '<g fill="currentColor" font-size="5.6" font-family="sans-serif"><text x="0" y="6">1</text><text x="0" y="10.4">2</text><text x="0" y="14.8">3</text></g>' +
      '<path d="M6.2 4.2h8M6.2 8.6h8M6.2 13h8" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>'),

    indent: svg(
      '<path d="M6.5 3.5h8.5M6.5 8h8.5M6.5 12.5h8.5M1 3.5h2.5M1 12.5h2.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>' +
      '<path d="M1 5.6L4 8l-3 2.4z" fill="currentColor"/>'),
    outdent: svg(
      '<path d="M6.5 3.5h8.5M6.5 8h8.5M6.5 12.5h8.5M1 3.5h2.5M1 12.5h2.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>' +
      '<path d="M4 5.6L1 8l3 2.4z" fill="currentColor"/>'),

    link: svg(
      '<g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">' +
      '<path d="M6.6 9.4a3 3 0 0 0 4.3 0l1.9-2a3 3 0 0 0-4.2-4.2l-1 1"/>' +
      '<path d="M9.4 6.6a3 3 0 0 0-4.3 0l-1.9 2a3 3 0 0 0 4.2 4.2l1-1"/></g>'),
    image: svg(
      '<rect x="1.4" y="2.8" width="13.2" height="10.4" rx="1.6" fill="none" stroke="currentColor" stroke-width="1.4"/>' +
      '<circle cx="5.4" cy="6.4" r="1.2" fill="currentColor"/>' +
      '<path d="M2.4 12.4l3.6-4 2.6 2.6L11 8.2l3.2 4.2" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/>'),
    table: svg(
      '<g fill="none" stroke="currentColor" stroke-width="1.3">' +
      '<rect x="1.5" y="2.5" width="13" height="11" rx="1.2"/>' +
      '<path d="M1.5 6.2h13M1.5 9.9h13M6 2.5v11M10.4 2.5v11"/></g>'),
    rule: stroked('M2 8h12', 1.8),
    pageBreak: svg(
      '<g fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round">' +
      '<path d="M3.5 1.8h9v4.2h-9zM3.5 10h9v4.2h-9z"/></g>' +
      '<path d="M1 8h2.5M5.5 8h2.5M10 8h2.5M14.5 8h.5" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>'),
    clearFormat: svg(
      '<text x="0.5" y="12.5" font-size="11.5" font-family="Georgia, serif" fill="currentColor">A</text>' +
      '<path d="M8.5 3.5l6 9" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>'),
    find: svg('<g fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round">' +
      '<circle cx="6.8" cy="6.8" r="4.6"/><path d="M10.3 10.3L14.4 14.4"/></g>'),

    sort: stroked('M4 13.5V2.5M1.4 5L4 2.5 6.6 5M12 2.5v11M9.4 11l2.6 2.5 2.6-2.5', 1.5),
    chart: svg('<g fill="currentColor"><rect x="1.8" y="8" width="3.2" height="6.2" rx=".6"/>' +
      '<rect x="6.4" y="4" width="3.2" height="10.2" rx=".6"/>' +
      '<rect x="11" y="6.2" width="3.2" height="8" rx=".6"/></g>'),
    sum: svg('<text x="1.5" y="13" font-size="13" font-family="Georgia, serif" fill="currentColor">Σ</text>'),

    textBox: svg('<text x="3.2" y="13" font-size="13" font-family="Georgia, serif" fill="currentColor">T</text>'),
    rect: svg('<rect x="1.8" y="4" width="12.4" height="8" rx="1.4" fill="none" stroke="currentColor" stroke-width="1.5"/>'),
    ellipse: svg('<ellipse cx="8" cy="8" rx="6.2" ry="4.6" fill="none" stroke="currentColor" stroke-width="1.5"/>'),
    line: stroked('M2.5 13.5L13.5 2.5', 1.8),
    toFront: svg('<rect x="1.6" y="1.6" width="8.4" height="8.4" rx="1.2" fill="none" stroke="currentColor" stroke-width="1.4"/>' +
      '<rect x="6" y="6" width="8.4" height="8.4" rx="1.2" fill="currentColor"/>'),
    toBack: svg('<rect x="6" y="6" width="8.4" height="8.4" rx="1.2" fill="none" stroke="currentColor" stroke-width="1.4"/>' +
      '<rect x="1.6" y="1.6" width="8.4" height="8.4" rx="1.2" fill="currentColor"/>'),
    play: svg('<path d="M4 2.8l9.2 5.2L4 13.2z" fill="currentColor"/>'),
    newSlide: svg('<rect x="1.2" y="3.2" width="9" height="9.6" rx="1.2" fill="none" stroke="currentColor" stroke-width="1.4"/>' +
      '<path d="M13 5.5v6M10 8.5h6" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>'),
    background: svg('<rect x="1.6" y="2.6" width="12.8" height="10.8" rx="1.4" fill="currentColor" opacity=".28"/>' +
      '<rect x="1.6" y="2.6" width="12.8" height="10.8" rx="1.4" fill="none" stroke="currentColor" stroke-width="1.4"/>'),

    decimalMore: svg('<g fill="currentColor" font-size="7" font-family="sans-serif"><text x="0" y="12">.00</text></g>' +
      '<path d="M12.5 4.2v5M10 6.7h5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>'),
    decimalLess: svg('<g fill="currentColor" font-size="7" font-family="sans-serif"><text x="0" y="12">.0</text></g>' +
      '<path d="M9.5 6.7h5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>'),
  };

  // ---- toasts ---------------------------------------------------------------
  function toast(message, kind) {
    const host = document.getElementById('toasts');
    const t = el('div', { class: 'toast' + (kind === 'err' ? ' err' : ''), text: message });
    host.appendChild(t);
    setTimeout(() => {
      t.style.transition = 'opacity .25s ease';
      t.style.opacity = '0';
      setTimeout(() => t.remove(), 260);
    }, kind === 'err' ? 4200 : 2200);
  }

  // ---- modal ----------------------------------------------------------------
  let modalCloser = null;

  /**
   * modal({title, sub, body, actions}) — body is a DOM node or a function that
   * receives the content element. Returns a close() function. Esc always closes.
   */
  function modal(opts) {
    closeModal();
    const backdrop = document.getElementById('modalBackdrop');
    const box = document.getElementById('modal');
    box.innerHTML = '';

    if (opts.title) box.appendChild(el('h3', { text: opts.title }));
    if (opts.sub) box.appendChild(el('p', { class: 'modal-sub', text: opts.sub }));

    const content = el('div');
    box.appendChild(content);
    if (typeof opts.body === 'function') opts.body(content);
    else if (opts.body) content.appendChild(opts.body);

    if (opts.actions) {
      const row = el('div', { class: 'actions' });
      for (const a of opts.actions) {
        row.appendChild(
          el('button', {
            class: 'btn' + (a.primary ? ' btn-primary' : '') + (a.danger ? ' btn-danger' : ''),
            text: a.label,
            onclick: () => a.onClick && a.onClick(),
          })
        );
      }
      box.appendChild(row);
    }

    backdrop.classList.remove('hidden');

    const onKey = (e) => {
      if (e.key === 'Escape') { e.preventDefault(); closeModal(); }
      else if (e.key === 'Enter' && opts.actions && !(e.target.tagName === 'TEXTAREA')) {
        const primary = opts.actions.find((a) => a.primary);
        if (primary && primary.onClick) { e.preventDefault(); primary.onClick(); }
      }
    };
    const onBackdrop = (e) => { if (e.target === backdrop) closeModal(); };
    document.addEventListener('keydown', onKey, true);
    backdrop.addEventListener('mousedown', onBackdrop);

    modalCloser = () => {
      document.removeEventListener('keydown', onKey, true);
      backdrop.removeEventListener('mousedown', onBackdrop);
      backdrop.classList.add('hidden');
      box.innerHTML = '';
      modalCloser = null;
      if (opts.onClose) opts.onClose();
    };

    // Focus the first field so the dialog is usable without reaching for a mouse.
    const first = box.querySelector('input, select, textarea');
    if (first) { first.focus(); if (first.select) first.select(); }

    return closeModal;
  }

  function closeModal() {
    if (modalCloser) modalCloser();
  }

  /**
   * A form dialog. fields: [{name, label, type, value, options, placeholder, min, max}].
   * Resolves with the values object, or null if cancelled.
   */
  function form(opts) {
    return new Promise((resolve) => {
      let settled = false;
      const inputs = {};
      const done = (v) => {
        if (settled) return;
        settled = true;
        closeModal();
        resolve(v);
      };
      modal({
        title: opts.title,
        sub: opts.sub,
        body: (host) => {
          for (const f of opts.fields || []) {
            if (f.type === 'checkbox') {
              const input = el('input', { type: 'checkbox', checked: !!f.value });
              inputs[f.name] = input;
              host.appendChild(el('label', { class: 'check' }, [input, f.label]));
              continue;
            }
            host.appendChild(el('label', { text: f.label }));
            let input;
            if (f.type === 'select') {
              input = el('select', {}, (f.options || []).map((o) =>
                el('option', {
                  value: typeof o === 'string' ? o : o.value,
                  text: typeof o === 'string' ? o : o.label,
                  selected: (typeof o === 'string' ? o : o.value) === f.value,
                })
              ));
            } else if (f.type === 'textarea') {
              input = el('textarea', { placeholder: f.placeholder || '' });
              input.value = f.value === undefined ? '' : f.value;
            } else {
              input = el('input', {
                type: f.type || 'text',
                placeholder: f.placeholder || '',
                min: f.min,
                max: f.max,
              });
              input.value = f.value === undefined ? '' : f.value;
            }
            inputs[f.name] = input;
            host.appendChild(input);
          }
          if (opts.note) host.appendChild(el('p', { class: 'modal-sub', style: { marginTop: '12px' }, text: opts.note }));
        },
        actions: [
          { label: opts.cancelLabel || 'Cancel', onClick: () => done(null) },
          {
            label: opts.okLabel || 'OK',
            primary: true,
            onClick: () => {
              const out = {};
              for (const [k, input] of Object.entries(inputs)) {
                out[k] = input.type === 'checkbox' ? input.checked : input.value;
              }
              done(out);
            },
          },
        ],
        onClose: () => done(null),
      });
    });
  }

  function confirm(opts) {
    return new Promise((resolve) => {
      let settled = false;
      const done = (v) => {
        if (settled) return;
        settled = true;
        closeModal();
        resolve(v);
      };
      modal({
        title: opts.title,
        sub: opts.message,
        actions: [
          { label: opts.cancelLabel || 'Cancel', onClick: () => done(false) },
          { label: opts.okLabel || 'OK', primary: true, danger: opts.danger, onClick: () => done(true) },
        ],
        onClose: () => done(false),
      });
    });
  }

  // ---- context menu ---------------------------------------------------------
  let openMenu = null;
  function menu(x, y, items) {
    closeMenu();
    const m = el('div', { class: 'ctxmenu' });
    for (const it of items) {
      if (it === '-') { m.appendChild(el('div', { class: 'sep' })); continue; }
      m.appendChild(
        el('button', { class: it.danger ? 'danger' : '', onclick: () => { closeMenu(); it.onClick && it.onClick(); } }, [
          el('span', { text: it.label }),
          it.hint ? el('span', { class: 'hint', text: it.hint }) : null,
        ])
      );
    }
    document.body.appendChild(m);
    // Keep the menu on screen when it opens near an edge.
    const r = m.getBoundingClientRect();
    m.style.left = Math.min(x, window.innerWidth - r.width - 8) + 'px';
    m.style.top = Math.min(y, window.innerHeight - r.height - 8) + 'px';

    const away = (e) => { if (!m.contains(e.target)) closeMenu(); };
    const key = (e) => { if (e.key === 'Escape') closeMenu(); };
    setTimeout(() => {
      document.addEventListener('mousedown', away, true);
      document.addEventListener('keydown', key, true);
    }, 0);
    openMenu = () => {
      document.removeEventListener('mousedown', away, true);
      document.removeEventListener('keydown', key, true);
      m.remove();
      openMenu = null;
    };
  }
  function closeMenu() { if (openMenu) openMenu(); }

  // ---- colour palette -------------------------------------------------------
  const COLORS = [
    '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc', '#d9d9d9', '#efefef', '#f3f3f3', '#ffffff',
    '#980000', '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#0000ff', '#9900ff', '#ff00ff',
    '#e6b8af', '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#c9daf8', '#cfe2f3', '#d9d2e9', '#ead1dc',
    '#dd7e6b', '#ea9999', '#f9cb9c', '#ffe599', '#b6d7a8', '#a2c4c9', '#a4c2f4', '#9fc5e8', '#b4a7d6', '#d5a6bd',
    '#cc4125', '#e06666', '#f6b26b', '#ffd966', '#93c47d', '#76a5af', '#6d9eeb', '#6fa8dc', '#8e7cc3', '#c27ba0',
    '#a61c00', '#cc0000', '#e69138', '#f1c232', '#6aa84f', '#45818e', '#3c78d8', '#3d85c6', '#674ea7', '#a64d79',
    '#85200c', '#990000', '#b45f06', '#bf9000', '#38761d', '#134f5c', '#1155cc', '#0b5394', '#351c75', '#741b47',
  ];

  /**
   * A colour picker anchored under `anchor`. onPick receives a CSS colour, or
   * null when the user chooses "None".
   */
  function palette(anchor, onPick, opts) {
    closeMenu();
    const wrap = anchor.closest('.swatch-wrap') || anchor.parentElement;
    const existing = wrap.querySelector('.palette');
    if (existing) { existing.remove(); return; }

    const p = el('div', { class: 'palette' });
    if (opts && opts.allowNone) {
      p.appendChild(el('button', { class: 'sw-none', text: opts.noneLabel || 'None', onclick: () => { p.remove(); onPick(null); } }));
    }
    for (const c of COLORS) {
      p.appendChild(el('div', {
        class: 'sw',
        style: { background: c },
        title: c,
        onmousedown: (e) => { e.preventDefault(); p.remove(); onPick(c); },
      }));
    }
    wrap.appendChild(p);
    const away = (e) => {
      if (!p.contains(e.target) && e.target !== anchor) {
        p.remove();
        document.removeEventListener('mousedown', away, true);
      }
    };
    setTimeout(() => document.addEventListener('mousedown', away, true), 0);
  }

  /** A toolbar colour button: an icon over a coloured bar. */
  function swatchButton(opts) {
    const bar = el('div', { class: 'swatch-bar', style: { background: opts.color || '#000' } });
    const btn = el('button', { class: 'tbtn swatch-btn', title: opts.title, type: 'button' }, [
      el('span', { html: opts.icon, style: { fontSize: '11px', lineHeight: '1' } }),
      bar,
    ]);
    btn.addEventListener('mousedown', (e) => e.preventDefault());
    btn.addEventListener('click', () => palette(btn, (c) => {
      if (c) bar.style.background = c;
      opts.onPick(c);
    }, { allowNone: opts.allowNone, noneLabel: opts.noneLabel }));
    const wrap = el('div', { class: 'swatch-wrap' }, [btn]);
    wrap.setColor = (c) => { bar.style.background = c || 'transparent'; };
    return wrap;
  }

  // ---- misc -----------------------------------------------------------------
  function debounce(fn, ms) {
    let t = null;
    return function (...args) {
      clearTimeout(t);
      t = setTimeout(() => fn.apply(this, args), ms);
    };
  }

  function escapeHtml(s) {
    return String(s).replace(/[&<>"']/g, (c) =>
      ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
  }

  /** Bytes -> "12.3 KB", for the status bar. */
  function fileSize(n) {
    if (n < 1024) return n + ' B';
    if (n < 1024 * 1024) return (n / 1024).toFixed(1) + ' KB';
    return (n / 1048576).toFixed(1) + ' MB';
  }

  global.UI = {
    el, tbtn, sep, spacer, toast, modal, closeModal, form, confirm,
    menu, closeMenu, palette, swatchButton, COLORS, ICONS,
    debounce, escapeHtml, fileSize,
  };
})(window);
A. HISTORY OF THE SOFTWARE
==========================

Python was created in the early 1990s by Guido van Rossum at Stichting
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
as a successor of a language called ABC.  Guido remains Python's
principal author, although it includes many contributions from others.

In 1995, Guido continued his work on Python at the Corporation for
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
in Reston, Virginia where he released several versions of the
software.

In May 2000, Guido and the Python core development team moved to
BeOpen.com to form the BeOpen PythonLabs team.  In October of the same
year, the PythonLabs team moved to Digital Creations, which became
Zope Corporation.  In 2001, the Python Software Foundation (PSF, see
https://www.python.org/psf/) was formed, a non-profit organization
created specifically to own Python-related Intellectual Property.
Zope Corporation was a sponsoring member of the PSF.

All Python releases are Open Source (see http://www.opensource.org for
the Open Source Definition).  Historically, most, but not all, Python
releases have also been GPL-compatible; the table below summarizes
the various releases.

    Release         Derived     Year        Owner       GPL-
                    from                                compatible? (1)

    0.9.0 thru 1.2              1991-1995   CWI         yes
    1.3 thru 1.5.2  1.2         1995-1999   CNRI        yes
    1.6             1.5.2       2000        CNRI        no
    2.0             1.6         2000        BeOpen.com  no
    1.6.1           1.6         2001        CNRI        yes (2)
    2.1             2.0+1.6.1   2001        PSF         no
    2.0.1           2.0+1.6.1   2001        PSF         yes
    2.1.1           2.1+2.0.1   2001        PSF         yes
    2.1.2           2.1.1       2002        PSF         yes
    2.1.3           2.1.2       2002        PSF         yes
    2.2 and above   2.1.1       2001-now    PSF         yes

Footnotes:

(1) GPL-compatible doesn't mean that we're distributing Python under
    the GPL.  All Python licenses, unlike the GPL, let you distribute
    a modified version without making your changes open source.  The
    GPL-compatible licenses make it possible to combine Python with
    other software that is released under the GPL; the others don't.

(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
    because its license has a choice of law clause.  According to
    CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
    is "not incompatible" with the GPL.

Thanks to the many outside volunteers who have worked under Guido's
direction to make these releases possible.


B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
===============================================================

PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------

1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.

2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation;
All Rights Reserved" are retained in Python alone or in any derivative version
prepared by Licensee.

3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.

4. PSF is making Python available to Licensee on an "AS IS"
basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.

5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.

6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.

7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee.  This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.

8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.


BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
-------------------------------------------

BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1

1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
Individual or Organization ("Licensee") accessing and otherwise using
this software in source or binary form and its associated
documentation ("the Software").

2. Subject to the terms and conditions of this BeOpen Python License
Agreement, BeOpen hereby grants Licensee a non-exclusive,
royalty-free, world-wide license to reproduce, analyze, test, perform
and/or display publicly, prepare derivative works, distribute, and
otherwise use the Software alone or in any derivative version,
provided, however, that the BeOpen Python License is retained in the
Software, alone or in any derivative version prepared by Licensee.

3. BeOpen is making the Software available to Licensee on an "AS IS"
basis.  BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.

4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.

5. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.

6. This License Agreement shall be governed by and interpreted in all
respects by the law of the State of California, excluding conflict of
law provisions.  Nothing in this License Agreement shall be deemed to
create any relationship of agency, partnership, or joint venture
between BeOpen and Licensee.  This License Agreement does not grant
permission to use BeOpen trademarks or trade names in a trademark
sense to endorse or promote products or services of Licensee, or any
third party.  As an exception, the "BeOpen Python" logos available at
http://www.pythonlabs.com/logos.html may be used according to the
permissions granted on that web page.

7. By copying, installing or otherwise using the software, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.


CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
---------------------------------------

1. This LICENSE AGREEMENT is between the Corporation for National
Research Initiatives, having an office at 1895 Preston White Drive,
Reston, VA 20191 ("CNRI"), and the Individual or Organization
("Licensee") accessing and otherwise using Python 1.6.1 software in
source or binary form and its associated documentation.

2. Subject to the terms and conditions of this License Agreement, CNRI
hereby grants Licensee a nonexclusive, royalty-free, world-wide
license to reproduce, analyze, test, perform and/or display publicly,
prepare derivative works, distribute, and otherwise use Python 1.6.1
alone or in any derivative version, provided, however, that CNRI's
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
1995-2001 Corporation for National Research Initiatives; All Rights
Reserved" are retained in Python 1.6.1 alone or in any derivative
version prepared by Licensee.  Alternately, in lieu of CNRI's License
Agreement, Licensee may substitute the following text (omitting the
quotes): "Python 1.6.1 is made available subject to the terms and
conditions in CNRI's License Agreement.  This Agreement together with
Python 1.6.1 may be located on the Internet using the following
unique, persistent identifier (known as a handle): 1895.22/1013.  This
Agreement may also be obtained from a proxy server on the Internet
using the following URL: http://hdl.handle.net/1895.22/1013".

3. In the event Licensee prepares a derivative work that is based on
or incorporates Python 1.6.1 or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python 1.6.1.

4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
basis.  CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.

5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.

6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.

7. This License Agreement shall be governed by the federal
intellectual property law of the United States, including without
limitation the federal copyright law, and, to the extent such
U.S. federal law does not apply, by the law of the Commonwealth of
Virginia, excluding Virginia's conflict of law provisions.
Notwithstanding the foregoing, with regard to derivative works based
on Python 1.6.1 that incorporate non-separable material that was
previously distributed under the GNU General Public License (GPL), the
law of the Commonwealth of Virginia shall govern this License
Agreement only as to issues arising under or with respect to
Paragraphs 4, 5, and 7 of this License Agreement.  Nothing in this
License Agreement shall be deemed to create any relationship of
agency, partnership, or joint venture between CNRI and Licensee.  This
License Agreement does not grant permission to use CNRI trademarks or
trade name in a trademark sense to endorse or promote products or
services of Licensee, or any third party.

8. By clicking on the "ACCEPT" button where indicated, or by copying,
installing or otherwise using Python 1.6.1, Licensee agrees to be
bound by the terms and conditions of this License Agreement.

        ACCEPT


CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
--------------------------------------------------

Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
The Netherlands.  All rights reserved.

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// Port of python's argparse module, version 3.9.0:
// https://github.com/python/cpython/blob/v3.9.0rc1/Lib/argparse.py

'use strict'

// Copyright (C) 2010-2020 Python Software Foundation.
// Copyright (C) 2020 argparse.js authors

/*
 * Command-line parsing library
 *
 * This module is an optparse-inspired command-line parsing library that:
 *
 *     - handles both optional and positional arguments
 *     - produces highly informative usage messages
 *     - supports parsers that dispatch to sub-parsers
 *
 * The following is a simple usage example that sums integers from the
 * command-line and writes the result to a file::
 *
 *     parser = argparse.ArgumentParser(
 *         description='sum the integers at the command line')
 *     parser.add_argument(
 *         'integers', metavar='int', nargs='+', type=int,
 *         help='an integer to be summed')
 *     parser.add_argument(
 *         '--log', default=sys.stdout, type=argparse.FileType('w'),
 *         help='the file where the sum should be written')
 *     args = parser.parse_args()
 *     args.log.write('%s' % sum(args.integers))
 *     args.log.close()
 *
 * The module contains the following public classes:
 *
 *     - ArgumentParser -- The main entry point for command-line parsing. As the
 *         example above shows, the add_argument() method is used to populate
 *         the parser with actions for optional and positional arguments. Then
 *         the parse_args() method is invoked to convert the args at the
 *         command-line into an object with attributes.
 *
 *     - ArgumentError -- The exception raised by ArgumentParser objects when
 *         there are errors with the parser's actions. Errors raised while
 *         parsing the command-line are caught by ArgumentParser and emitted
 *         as command-line messages.
 *
 *     - FileType -- A factory for defining types of files to be created. As the
 *         example above shows, instances of FileType are typically passed as
 *         the type= argument of add_argument() calls.
 *
 *     - Action -- The base class for parser actions. Typically actions are
 *         selected by passing strings like 'store_true' or 'append_const' to
 *         the action= argument of add_argument(). However, for greater
 *         customization of ArgumentParser actions, subclasses of Action may
 *         be defined and passed as the action= argument.
 *
 *     - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
 *         ArgumentDefaultsHelpFormatter -- Formatter classes which
 *         may be passed as the formatter_class= argument to the
 *         ArgumentParser constructor. HelpFormatter is the default,
 *         RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
 *         not to change the formatting for help text, and
 *         ArgumentDefaultsHelpFormatter adds information about argument defaults
 *         to the help.
 *
 * All other classes in this module are considered implementation details.
 * (Also note that HelpFormatter and RawDescriptionHelpFormatter are only
 * considered public as object names -- the API of the formatter objects is
 * still considered an implementation detail.)
 */

const SUPPRESS = '==SUPPRESS=='

const OPTIONAL = '?'
const ZERO_OR_MORE = '*'
const ONE_OR_MORE = '+'
const PARSER = 'A...'
const REMAINDER = '...'
const _UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'


// ==================================
// Utility functions used for porting
// ==================================
const assert = require('assert')
const util = require('util')
const fs = require('fs')
const sub = require('./lib/sub')
const path = require('path')
const repr = util.inspect

function get_argv() {
    // omit first argument (which is assumed to be interpreter - `node`, `coffee`, `ts-node`, etc.)
    return process.argv.slice(1)
}

function get_terminal_size() {
    return {
        columns: +process.env.COLUMNS || process.stdout.columns || 80
    }
}

function hasattr(object, name) {
    return Object.prototype.hasOwnProperty.call(object, name)
}

function getattr(object, name, value) {
    return hasattr(object, name) ? object[name] : value
}

function setattr(object, name, value) {
    object[name] = value
}

function setdefault(object, name, value) {
    if (!hasattr(object, name)) object[name] = value
    return object[name]
}

function delattr(object, name) {
    delete object[name]
}

function range(from, to, step=1) {
    // range(10) is equivalent to range(0, 10)
    if (arguments.length === 1) [ to, from ] = [ from, 0 ]
    if (typeof from !== 'number' || typeof to !== 'number' || typeof step !== 'number') {
        throw new TypeError('argument cannot be interpreted as an integer')
    }
    if (step === 0) throw new TypeError('range() arg 3 must not be zero')

    let result = []
    if (step > 0) {
        for (let i = from; i < to; i += step) result.push(i)
    } else {
        for (let i = from; i > to; i += step) result.push(i)
    }
    return result
}

function splitlines(str, keepends = false) {
    let result
    if (!keepends) {
        result = str.split(/\r\n|[\n\r\v\f\x1c\x1d\x1e\x85\u2028\u2029]/)
    } else {
        result = []
        let parts = str.split(/(\r\n|[\n\r\v\f\x1c\x1d\x1e\x85\u2028\u2029])/)
        for (let i = 0; i < parts.length; i += 2) {
            result.push(parts[i] + (i + 1 < parts.length ? parts[i + 1] : ''))
        }
    }
    if (!result[result.length - 1]) result.pop()
    return result
}

function _string_lstrip(string, prefix_chars) {
    let idx = 0
    while (idx < string.length && prefix_chars.includes(string[idx])) idx++
    return idx ? string.slice(idx) : string
}

function _string_split(string, sep, maxsplit) {
    let result = string.split(sep)
    if (result.length > maxsplit) {
        result = result.slice(0, maxsplit).concat([ result.slice(maxsplit).join(sep) ])
    }
    return result
}

function _array_equal(array1, array2) {
    if (array1.length !== array2.length) return false
    for (let i = 0; i < array1.length; i++) {
        if (array1[i] !== array2[i]) return false
    }
    return true
}

function _array_remove(array, item) {
    let idx = array.indexOf(item)
    if (idx === -1) throw new TypeError(sub('%r not in list', item))
    array.splice(idx, 1)
}

// normalize choices to array;
// this isn't required in python because `in` and `map` operators work with anything,
// but in js dealing with multiple types here is too clunky
function _choices_to_array(choices) {
    if (choices === undefined) {
        return []
    } else if (Array.isArray(choices)) {
        return choices
    } else if (choices !== null && typeof choices[Symbol.iterator] === 'function') {
        return Array.from(choices)
    } else if (typeof choices === 'object' && choices !== null) {
        return Object.keys(choices)
    } else {
        throw new Error(sub('invalid choices value: %r', choices))
    }
}

// decorator that allows a class to be called without new
function _callable(cls) {
    let result = { // object is needed for inferred class name
        [cls.name]: function (...args) {
            let this_class = new.target === result || !new.target
            return Reflect.construct(cls, args, this_class ? cls : new.target)
        }
    }
    result[cls.name].prototype = cls.prototype
    // fix default tag for toString, e.g. [object Action] instead of [object Object]
    cls.prototype[Symbol.toStringTag] = cls.name
    return result[cls.name]
}

function _alias(object, from, to) {
    try {
        let name = object.constructor.name
        Object.defineProperty(object, from, {
            value: util.deprecate(object[to], sub('%s.%s() is renamed to %s.%s()',
                name, from, name, to)),
            enumerable: false
        })
    } catch {}
}

// decorator that allows snake_case class methods to be called with camelCase and vice versa
function _camelcase_alias(_class) {
    for (let name of Object.getOwnPropertyNames(_class.prototype)) {
        let camelcase = name.replace(/\w_[a-z]/g, s => s[0] + s[2].toUpperCase())
        if (camelcase !== name) _alias(_class.prototype, camelcase, name)
    }
    return _class
}

function _to_legacy_name(key) {
    key = key.replace(/\w_[a-z]/g, s => s[0] + s[2].toUpperCase())
    if (key === 'default') key = 'defaultValue'
    if (key === 'const') key = 'constant'
    return key
}

function _to_new_name(key) {
    if (key === 'defaultValue') key = 'default'
    if (key === 'constant') key = 'const'
    key = key.replace(/[A-Z]/g, c => '_' + c.toLowerCase())
    return key
}

// parse options
let no_default = Symbol('no_default_value')
function _parse_opts(args, descriptor) {
    function get_name() {
        let stack = new Error().stack.split('\n')
            .map(x => x.match(/^    at (.*) \(.*\)$/))
            .filter(Boolean)
            .map(m => m[1])
            .map(fn => fn.match(/[^ .]*$/)[0])

        if (stack.length && stack[0] === get_name.name) stack.shift()
        if (stack.length && stack[0] === _parse_opts.name) stack.shift()
        return stack.length ? stack[0] : ''
    }

    args = Array.from(args)
    let kwargs = {}
    let result = []
    let last_opt = args.length && args[args.length - 1]

    if (typeof last_opt === 'object' && last_opt !== null && !Array.isArray(last_opt) &&
        (!last_opt.constructor || last_opt.constructor.name === 'Object')) {
        kwargs = Object.assign({}, args.pop())
    }

    // LEGACY (v1 compatibility): camelcase
    let renames = []
    for (let key of Object.keys(descriptor)) {
        let old_name = _to_legacy_name(key)
        if (old_name !== key && (old_name in kwargs)) {
            if (key in kwargs) {
                // default and defaultValue specified at the same time, happens often in old tests
                //throw new TypeError(sub('%s() got multiple values for argument %r', get_name(), key))
            } else {
                kwargs[key] = kwargs[old_name]
            }
            renames.push([ old_name, key ])
            delete kwargs[old_name]
        }
    }
    if (renames.length) {
        let name = get_name()
        deprecate('camelcase_' + name, sub('%s(): following options are renamed: %s',
            name, renames.map(([ a, b ]) => sub('%r -> %r', a, b))))
    }
    // end

    let missing_positionals = []
    let positional_count = args.length

    for (let [ key, def ] of Object.entries(descriptor)) {
        if (key[0] === '*') {
            if (key.length > 0 && key[1] === '*') {
                // LEGACY (v1 compatibility): camelcase
                let renames = []
                for (let key of Object.keys(kwargs)) {
                    let new_name = _to_new_name(key)
                    if (new_name !== key && (key in kwargs)) {
                        if (new_name in kwargs) {
                            // default and defaultValue specified at the same time, happens often in old tests
                            //throw new TypeError(sub('%s() got multiple values for argument %r', get_name(), new_name))
                        } else {
                            kwargs[new_name] = kwargs[key]
                        }
                        renames.push([ key, new_name ])
                        delete kwargs[key]
                    }
                }
                if (renames.length) {
                    let name = get_name()
                    deprecate('camelcase_' + name, sub('%s(): following options are renamed: %s',
                        name, renames.map(([ a, b ]) => sub('%r -> %r', a, b))))
                }
                // end
                result.push(kwargs)
                kwargs = {}
            } else {
                result.push(args)
                args = []
            }
        } else if (key in kwargs && args.length > 0) {
            throw new TypeError(sub('%s() got multiple values for argument %r', get_name(), key))
        } else if (key in kwargs) {
            result.push(kwargs[key])
            delete kwargs[key]
        } else if (args.length > 0) {
            result.push(args.shift())
        } else if (def !== no_default) {
            result.push(def)
        } else {
            missing_positionals.push(key)
        }
    }

    if (Object.keys(kwargs).length) {
        throw new TypeError(sub('%s() got an unexpected keyword argument %r',
            get_name(), Object.keys(kwargs)[0]))
    }

    if (args.length) {
        let from = Object.entries(descriptor).filter(([ k, v ]) => k[0] !== '*' && v !== no_default).length
        let to = Object.entries(descriptor).filter(([ k ]) => k[0] !== '*').length
        throw new TypeError(sub('%s() takes %s positional argument%s but %s %s given',
            get_name(),
            from === to ? sub('from %s to %s', from, to) : to,
            from === to && to === 1 ? '' : 's',
            positional_count,
            positional_count === 1 ? 'was' : 'were'))
    }

    if (missing_positionals.length) {
        let strs = missing_positionals.map(repr)
        if (strs.length > 1) strs[strs.length - 1] = 'and ' + strs[strs.length - 1]
        let str_joined = strs.join(strs.length === 2 ? '' : ', ')
        throw new TypeError(sub('%s() missing %i required positional argument%s: %s',
            get_name(), strs.length, strs.length === 1 ? '' : 's', str_joined))
    }

    return result
}

let _deprecations = {}
function deprecate(id, string) {
    _deprecations[id] = _deprecations[id] || util.deprecate(() => {}, string)
    _deprecations[id]()
}


// =============================
// Utility functions and classes
// =============================
function _AttributeHolder(cls = Object) {
    /*
     *  Abstract base class that provides __repr__.
     *
     *  The __repr__ method returns a string in the format::
     *      ClassName(attr=name, attr=name, ...)
     *  The attributes are determined either by a class-level attribute,
     *  '_kwarg_names', or by inspecting the instance __dict__.
     */

    return class _AttributeHolder extends cls {
        [util.inspect.custom]() {
            let type_name = this.constructor.name
            let arg_strings = []
            let star_args = {}
            for (let arg of this._get_args()) {
                arg_strings.push(repr(arg))
            }
            for (let [ name, value ] of this._get_kwargs()) {
                if (/^[a-z_][a-z0-9_$]*$/i.test(name)) {
                    arg_strings.push(sub('%s=%r', name, value))
                } else {
                    star_args[name] = value
                }
            }
            if (Object.keys(star_args).length) {
                arg_strings.push(sub('**%s', repr(star_args)))
            }
            return sub('%s(%s)', type_name, arg_strings.join(', '))
        }

        toString() {
            return this[util.inspect.custom]()
        }

        _get_kwargs() {
            return Object.entries(this)
        }

        _get_args() {
            return []
        }
    }
}


function _copy_items(items) {
    if (items === undefined) {
        return []
    }
    return items.slice(0)
}


// ===============
// Formatting Help
// ===============
const HelpFormatter = _camelcase_alias(_callable(class HelpFormatter {
    /*
     *  Formatter for generating usage messages and argument help strings.
     *
     *  Only the name of this class is considered a public API. All the methods
     *  provided by the class are considered an implementation detail.
     */

    constructor() {
        let [
            prog,
            indent_increment,
            max_help_position,
            width
        ] = _parse_opts(arguments, {
            prog: no_default,
            indent_increment: 2,
            max_help_position: 24,
            width: undefined
        })

        // default setting for width
        if (width === undefined) {
            width = get_terminal_size().columns
            width -= 2
        }

        this._prog = prog
        this._indent_increment = indent_increment
        this._max_help_position = Math.min(max_help_position,
                                      Math.max(width - 20, indent_increment * 2))
        this._width = width

        this._current_indent = 0
        this._level = 0
        this._action_max_length = 0

        this._root_section = this._Section(this, undefined)
        this._current_section = this._root_section

        this._whitespace_matcher = /[ \t\n\r\f\v]+/g // equivalent to python /\s+/ with ASCII flag
        this._long_break_matcher = /\n\n\n+/g
    }

    // ===============================
    // Section and indentation methods
    // ===============================
    _indent() {
        this._current_indent += this._indent_increment
        this._level += 1
    }

    _dedent() {
        this._current_indent -= this._indent_increment
        assert(this._current_indent >= 0, 'Indent decreased below 0.')
        this._level -= 1
    }

    _add_item(func, args) {
        this._current_section.items.push([ func, args ])
    }

    // ========================
    // Message building methods
    // ========================
    start_section(heading) {
        this._indent()
        let section = this._Section(this, this._current_section, heading)
        this._add_item(section.format_help.bind(section), [])
        this._current_section = section
    }

    end_section() {
        this._current_section = this._current_section.parent
        this._dedent()
    }

    add_text(text) {
        if (text !== SUPPRESS && text !== undefined) {
            this._add_item(this._format_text.bind(this), [text])
        }
    }

    add_usage(usage, actions, groups, prefix = undefined) {
        if (usage !== SUPPRESS) {
            let args = [ usage, actions, groups, prefix ]
            this._add_item(this._format_usage.bind(this), args)
        }
    }

    add_argument(action) {
        if (action.help !== SUPPRESS) {

            // find all invocations
            let invocations = [this._format_action_invocation(action)]
            for (let subaction of this._iter_indented_subactions(action)) {
                invocations.push(this._format_action_invocation(subaction))
            }

            // update the maximum item length
            let invocation_length = Math.max(...invocations.map(invocation => invocation.length))
            let action_length = invocation_length + this._current_indent
            this._action_max_length = Math.max(this._action_max_length,
                                               action_length)

            // add the item to the list
            this._add_item(this._format_action.bind(this), [action])
        }
    }

    add_arguments(actions) {
        for (let action of actions) {
            this.add_argument(action)
        }
    }

    // =======================
    // Help-formatting methods
    // =======================
    format_help() {
        let help = this._root_section.format_help()
        if (help) {
            help = help.replace(this._long_break_matcher, '\n\n')
            help = help.replace(/^\n+|\n+$/g, '') + '\n'
        }
        return help
    }

    _join_parts(part_strings) {
        return part_strings.filter(part => part && part !== SUPPRESS).join('')
    }

    _format_usage(usage, actions, groups, prefix) {
        if (prefix === undefined) {
            prefix = 'usage: '
        }

        // if usage is specified, use that
        if (usage !== undefined) {
            usage = sub(usage, { prog: this._prog })

        // if no optionals or positionals are available, usage is just prog
        } else if (usage === undefined && !actions.length) {
            usage = sub('%(prog)s', { prog: this._prog })

        // if optionals and positionals are available, calculate usage
        } else if (usage === undefined) {
            let prog = sub('%(prog)s', { prog: this._prog })

            // split optionals from positionals
            let optionals = []
            let positionals = []
            for (let action of actions) {
                if (action.option_strings.length) {
                    optionals.push(action)
                } else {
                    positionals.push(action)
                }
            }

            // build full usage string
            let action_usage = this._format_actions_usage([].concat(optionals).concat(positionals), groups)
            usage = [ prog, action_usage ].map(String).join(' ')

            // wrap the usage parts if it's too long
            let text_width = this._width - this._current_indent
            if (prefix.length + usage.length > text_width) {

                // break usage into wrappable parts
                let part_regexp = /\(.*?\)+(?=\s|$)|\[.*?\]+(?=\s|$)|\S+/g
                let opt_usage = this._format_actions_usage(optionals, groups)
                let pos_usage = this._format_actions_usage(positionals, groups)
                let opt_parts = opt_usage.match(part_regexp) || []
                let pos_parts = pos_usage.match(part_regexp) || []
                assert(opt_parts.join(' ') === opt_usage)
                assert(pos_parts.join(' ') === pos_usage)

                // helper for wrapping lines
                let get_lines = (parts, indent, prefix = undefined) => {
                    let lines = []
                    let line = []
                    let line_len
                    if (prefix !== undefined) {
                        line_len = prefix.length - 1
                    } else {
                        line_len = indent.length - 1
                    }
                    for (let part of parts) {
                        if (line_len + 1 + part.length > text_width && line) {
                            lines.push(indent + line.join(' '))
                            line = []
                            line_len = indent.length - 1
                        }
                        line.push(part)
                        line_len += part.length + 1
                    }
                    if (line.length) {
                        lines.push(indent + line.join(' '))
                    }
                    if (prefix !== undefined) {
                        lines[0] = lines[0].slice(indent.length)
                    }
                    return lines
                }

                let lines

                // if prog is short, follow it with optionals or positionals
                if (prefix.length + prog.length <= 0.75 * text_width) {
                    let indent = ' '.repeat(prefix.length + prog.length + 1)
                    if (opt_parts.length) {
                        lines = get_lines([prog].concat(opt_parts), indent, prefix)
                        lines = lines.concat(get_lines(pos_parts, indent))
                    } else if (pos_parts.length) {
                        lines = get_lines([prog].concat(pos_parts), indent, prefix)
                    } else {
                        lines = [prog]
                    }

                // if prog is long, put it on its own line
                } else {
                    let indent = ' '.repeat(prefix.length)
                    let parts = [].concat(opt_parts).concat(pos_parts)
                    lines = get_lines(parts, indent)
                    if (lines.length > 1) {
                        lines = []
                        lines = lines.concat(get_lines(opt_parts, indent))
                        lines = lines.concat(get_lines(pos_parts, indent))
                    }
                    lines = [prog].concat(lines)
                }

                // join lines into usage
                usage = lines.join('\n')
            }
        }

        // prefix with 'usage:'
        return sub('%s%s\n\n', prefix, usage)
    }

    _format_actions_usage(actions, groups) {
        // find group indices and identify actions in groups
        let group_actions = new Set()
        let inserts = {}
        for (let group of groups) {
            let start = actions.indexOf(group._group_actions[0])
            if (start === -1) {
                continue
            } else {
                let end = start + group._group_actions.length
                if (_array_equal(actions.slice(start, end), group._group_actions)) {
                    for (let action of group._group_actions) {
                        group_actions.add(action)
                    }
                    if (!group.required) {
                        if (start in inserts) {
                            inserts[start] += ' ['
                        } else {
                            inserts[start] = '['
                        }
                        if (end in inserts) {
                            inserts[end] += ']'
                        } else {
                            inserts[end] = ']'
                        }
                    } else {
                        if (start in inserts) {
                            inserts[start] += ' ('
                        } else {
                            inserts[start] = '('
                        }
                        if (end in inserts) {
                            inserts[end] += ')'
                        } else {
                            inserts[end] = ')'
                        }
                    }
                    for (let i of range(start + 1, end)) {
                        inserts[i] = '|'
                    }
                }
            }
        }

        // collect all actions format strings
        let parts = []
        for (let [ i, action ] of Object.entries(actions)) {

            // suppressed arguments are marked with None
            // remove | separators for suppressed arguments
            if (action.help === SUPPRESS) {
                parts.push(undefined)
                if (inserts[+i] === '|') {
                    delete inserts[+i]
                } else if (inserts[+i + 1] === '|') {
                    delete inserts[+i + 1]
                }

            // produce all arg strings
            } else if (!action.option_strings.length) {
                let default_value = this._get_default_metavar_for_positional(action)
                let part = this._format_args(action, default_value)

                // if it's in a group, strip the outer []
                if (group_actions.has(action)) {
                    if (part[0] === '[' && part[part.length - 1] === ']') {
                        part = part.slice(1, -1)
                    }
                }

                // add the action string to the list
                parts.push(part)

            // produce the first way to invoke the option in brackets
            } else {
                let option_string = action.option_strings[0]
                let part

                // if the Optional doesn't take a value, format is:
                //    -s or --long
                if (action.nargs === 0) {
                    part = action.format_usage()

                // if the Optional takes a value, format is:
                //    -s ARGS or --long ARGS
                } else {
                    let default_value = this._get_default_metavar_for_optional(action)
                    let args_string = this._format_args(action, default_value)
                    part = sub('%s %s', option_string, args_string)
                }

                // make it look optional if it's not required or in a group
                if (!action.required && !group_actions.has(action)) {
                    part = sub('[%s]', part)
                }

                // add the action string to the list
                parts.push(part)
            }
        }

        // insert things at the necessary indices
        for (let i of Object.keys(inserts).map(Number).sort((a, b) => b - a)) {
            parts.splice(+i, 0, inserts[+i])
        }

        // join all the action items with spaces
        let text = parts.filter(Boolean).join(' ')

        // clean up separators for mutually exclusive groups
        text = text.replace(/([\[(]) /g, '$1')
        text = text.replace(/ ([\])])/g, '$1')
        text = text.replace(/[\[(] *[\])]/g, '')
        text = text.replace(/\(([^|]*)\)/g, '$1', text)
        text = text.trim()

        // return the text
        return text
    }

    _format_text(text) {
        if (text.includes('%(prog)')) {
            text = sub(text, { prog: this._prog })
        }
        let text_width = Math.max(this._width - this._current_indent, 11)
        let indent = ' '.repeat(this._current_indent)
        return this._fill_text(text, text_width, indent) + '\n\n'
    }

    _format_action(action) {
        // determine the required width and the entry label
        let help_position = Math.min(this._action_max_length + 2,
                                     this._max_help_position)
        let help_width = Math.max(this._width - help_position, 11)
        let action_width = help_position - this._current_indent - 2
        let action_header = this._format_action_invocation(action)
        let indent_first

        // no help; start on same line and add a final newline
        if (!action.help) {
            let tup = [ this._current_indent, '', action_header ]
            action_header = sub('%*s%s\n', ...tup)

        // short action name; start on the same line and pad two spaces
        } else if (action_header.length <= action_width) {
            let tup = [ this._current_indent, '', action_width, action_header ]
            action_header = sub('%*s%-*s  ', ...tup)
            indent_first = 0

        // long action name; start on the next line
        } else {
            let tup = [ this._current_indent, '', action_header ]
            action_header = sub('%*s%s\n', ...tup)
            indent_first = help_position
        }

        // collect the pieces of the action help
        let parts = [action_header]

        // if there was help for the action, add lines of help text
        if (action.help) {
            let help_text = this._expand_help(action)
            let help_lines = this._split_lines(help_text, help_width)
            parts.push(sub('%*s%s\n', indent_first, '', help_lines[0]))
            for (let line of help_lines.slice(1)) {
                parts.push(sub('%*s%s\n', help_position, '', line))
            }

        // or add a newline if the description doesn't end with one
        } else if (!action_header.endsWith('\n')) {
            parts.push('\n')
        }

        // if there are any sub-actions, add their help as well
        for (let subaction of this._iter_indented_subactions(action)) {
            parts.push(this._format_action(subaction))
        }

        // return a single string
        return this._join_parts(parts)
    }

    _format_action_invocation(action) {
        if (!action.option_strings.length) {
            let default_value = this._get_default_metavar_for_positional(action)
            let metavar = this._metavar_formatter(action, default_value)(1)[0]
            return metavar

        } else {
            let parts = []

            // if the Optional doesn't take a value, format is:
            //    -s, --long
            if (action.nargs === 0) {
                parts = parts.concat(action.option_strings)

            // if the Optional takes a value, format is:
            //    -s ARGS, --long ARGS
            } else {
                let default_value = this._get_default_metavar_for_optional(action)
                let args_string = this._format_args(action, default_value)
                for (let option_string of action.option_strings) {
                    parts.push(sub('%s %s', option_string, args_string))
                }
            }

            return parts.join(', ')
        }
    }

    _metavar_formatter(action, default_metavar) {
        let result
        if (action.metavar !== undefined) {
            result = action.metavar
        } else if (action.choices !== undefined) {
            let choice_strs = _choices_to_array(action.choices).map(String)
            result = sub('{%s}', choice_strs.join(','))
        } else {
            result = default_metavar
        }

        function format(tuple_size) {
            if (Array.isArray(result)) {
                return result
            } else {
                return Array(tuple_size).fill(result)
            }
        }
        return format
    }

    _format_args(action, default_metavar) {
        let get_metavar = this._metavar_formatter(action, default_metavar)
        let result
        if (action.nargs === undefined) {
            result = sub('%s', ...get_metavar(1))
        } else if (action.nargs === OPTIONAL) {
            result = sub('[%s]', ...get_metavar(1))
        } else if (action.nargs === ZERO_OR_MORE) {
            let metavar = get_metavar(1)
            if (metavar.length === 2) {
                result = sub('[%s [%s ...]]', ...metavar)
            } else {
                result = sub('[%s ...]', ...metavar)
            }
        } else if (action.nargs === ONE_OR_MORE) {
            result = sub('%s [%s ...]', ...get_metavar(2))
        } else if (action.nargs === REMAINDER) {
            result = '...'
        } else if (action.nargs === PARSER) {
            result = sub('%s ...', ...get_metavar(1))
        } else if (action.nargs === SUPPRESS) {
            result = ''
        } else {
            let formats
            try {
                formats = range(action.nargs).map(() => '%s')
            } catch (err) {
                throw new TypeError('invalid nargs value')
            }
            result = sub(formats.join(' '), ...get_metavar(action.nargs))
        }
        return result
    }

    _expand_help(action) {
        let params = Object.assign({ prog: this._prog }, action)
        for (let name of Object.keys(params)) {
            if (params[name] === SUPPRESS) {
                delete params[name]
            }
        }
        for (let name of Object.keys(params)) {
            if (params[name] && params[name].name) {
                params[name] = params[name].name
            }
        }
        if (params.choices !== undefined) {
            let choices_str = _choices_to_array(params.choices).map(String).join(', ')
            params.choices = choices_str
        }
        // LEGACY (v1 compatibility): camelcase
        for (let key of Object.keys(params)) {
            let old_name = _to_legacy_name(key)
            if (old_name !== key) {
                params[old_name] = params[key]
            }
        }
        // end
        return sub(this._get_help_string(action), params)
    }

    * _iter_indented_subactions(action) {
        if (typeof action._get_subactions === 'function') {
            this._indent()
            yield* action._get_subactions()
            this._dedent()
        }
    }

    _split_lines(text, width) {
        text = text.replace(this._whitespace_matcher, ' ').trim()
        // The textwrap module is used only for formatting help.
        // Delay its import for speeding up the common usage of argparse.
        let textwrap = require('./lib/textwrap')
        return textwrap.wrap(text, { width })
    }

    _fill_text(text, width, indent) {
        text = text.replace(this._whitespace_matcher, ' ').trim()
        let textwrap = require('./lib/textwrap')
        return textwrap.fill(text, { width,
                                     initial_indent: indent,
                                     subsequent_indent: indent })
    }

    _get_help_string(action) {
        return action.help
    }

    _get_default_metavar_for_optional(action) {
        return action.dest.toUpperCase()
    }

    _get_default_metavar_for_positional(action) {
        return action.dest
    }
}))

HelpFormatter.prototype._Section = _callable(class _Section {

    constructor(formatter, parent, heading = undefined) {
        this.formatter = formatter
        this.parent = parent
        this.heading = heading
        this.items = []
    }

    format_help() {
        // format the indented section
        if (this.parent !== undefined) {
            this.formatter._indent()
        }
        let item_help = this.formatter._join_parts(this.items.map(([ func, args ]) => func.apply(null, args)))
        if (this.parent !== undefined) {
            this.formatter._dedent()
        }

        // return nothing if the section was empty
        if (!item_help) {
            return ''
        }

        // add the heading if the section was non-empty
        let heading
        if (this.heading !== SUPPRESS && this.heading !== undefined) {
            let current_indent = this.formatter._current_indent
            heading = sub('%*s%s:\n', current_indent, '', this.heading)
        } else {
            heading = ''
        }

        // join the section-initial newline, the heading and the help
        return this.formatter._join_parts(['\n', heading, item_help, '\n'])
    }
})


const RawDescriptionHelpFormatter = _camelcase_alias(_callable(class RawDescriptionHelpFormatter extends HelpFormatter {
    /*
     *  Help message formatter which retains any formatting in descriptions.
     *
     *  Only the name of this class is considered a public API. All the methods
     *  provided by the class are considered an implementation detail.
     */

    _fill_text(text, width, indent) {
        return splitlines(text, true).map(line => indent + line).join('')
    }
}))


const RawTextHelpFormatter = _camelcase_alias(_callable(class RawTextHelpFormatter extends RawDescriptionHelpFormatter {
    /*
     *  Help message formatter which retains formatting of all help text.
     *
     *  Only the name of this class is considered a public API. All the methods
     *  provided by the class are considered an implementation detail.
     */

    _split_lines(text/*, width*/) {
        return splitlines(text)
    }
}))


const ArgumentDefaultsHelpFormatter = _camelcase_alias(_callable(class ArgumentDefaultsHelpFormatter extends HelpFormatter {
    /*
     *  Help message formatter which adds default values to argument help.
     *
     *  Only the name of this class is considered a public API. All the methods
     *  provided by the class are considered an implementation detail.
     */

    _get_help_string(action) {
        let help = action.help
        // LEGACY (v1 compatibility): additional check for defaultValue needed
        if (!action.help.includes('%(default)') && !action.help.includes('%(defaultValue)')) {
            if (action.default !== SUPPRESS) {
                let defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
                if (action.option_strings.length || defaulting_nargs.includes(action.nargs)) {
                    help += ' (default: %(default)s)'
                }
            }
        }
        return help
    }
}))


const MetavarTypeHelpFormatter = _camelcase_alias(_callable(class MetavarTypeHelpFormatter extends HelpFormatter {
    /*
     *  Help message formatter which uses the argument 'type' as the default
     *  metavar value (instead of the argument 'dest')
     *
     *  Only the name of this class is considered a public API. All the methods
     *  provided by the class are considered an implementation detail.
     */

    _get_default_metavar_for_optional(action) {
        return typeof action.type === 'function' ? action.type.name : action.type
    }

    _get_default_metavar_for_positional(action) {
        return typeof action.type === 'function' ? action.type.name : action.type
    }
}))


// =====================
// Options and Arguments
// =====================
function _get_action_name(argument) {
    if (argument === undefined) {
        return undefined
    } else if (argument.option_strings.length) {
        return argument.option_strings.join('/')
    } else if (![ undefined, SUPPRESS ].includes(argument.metavar)) {
        return argument.metavar
    } else if (![ undefined, SUPPRESS ].includes(argument.dest)) {
        return argument.dest
    } else {
        return undefined
    }
}


const ArgumentError = _callable(class ArgumentError extends Error {
    /*
     *  An error from creating or using an argument (optional or positional).
     *
     *  The string value of this exception is the message, augmented with
     *  information about the argument that caused it.
     */

    constructor(argument, message) {
        super()
        this.name = 'ArgumentError'
        this._argument_name = _get_action_name(argument)
        this._message = message
        this.message = this.str()
    }

    str() {
        let format
        if (this._argument_name === undefined) {
            format = '%(message)s'
        } else {
            format = 'argument %(argument_name)s: %(message)s'
        }
        return sub(format, { message: this._message,
                             argument_name: this._argument_name })
    }
})


const ArgumentTypeError = _callable(class ArgumentTypeError extends Error {
    /*
     * An error from trying to convert a command line string to a type.
     */

    constructor(message) {
        super(message)
        this.name = 'ArgumentTypeError'
    }
})


// ==============
// Action classes
// ==============
const Action = _camelcase_alias(_callable(class Action extends _AttributeHolder(Function) {
    /*
     *  Information about how to convert command line strings to Python objects.
     *
     *  Action objects are used by an ArgumentParser to represent the information
     *  needed to parse a single argument from one or more strings from the
     *  command line. The keyword arguments to the Action constructor are also
     *  all attributes of Action instances.
     *
     *  Keyword Arguments:
     *
     *      - option_strings -- A list of command-line option strings which
     *          should be associated with this action.
     *
     *      - dest -- The name of the attribute to hold the created object(s)
     *
     *      - nargs -- The number of command-line arguments that should be
     *          consumed. By default, one argument will be consumed and a single
     *          value will be produced.  Other values include:
     *              - N (an integer) consumes N arguments (and produces a list)
     *              - '?' consumes zero or one arguments
     *              - '*' consumes zero or more arguments (and produces a list)
     *              - '+' consumes one or more arguments (and produces a list)
     *          Note that the difference between the default and nargs=1 is that
     *          with the default, a single value will be produced, while with
     *          nargs=1, a list containing a single value will be produced.
     *
     *      - const -- The value to be produced if the option is specified and the
     *          option uses an action that takes no values.
     *
     *      - default -- The value to be produced if the option is not specified.
     *
     *      - type -- A callable that accepts a single string argument, and
     *          returns the converted value.  The standard Python types str, int,
     *          float, and complex are useful examples of such callables.  If None,
     *          str is used.
     *
     *      - choices -- A container of values that should be allowed. If not None,
     *          after a command-line argument has been converted to the appropriate
     *          type, an exception will be raised if it is not a member of this
     *          collection.
     *
     *      - required -- True if the action must always be specified at the
     *          command line. This is only meaningful for optional command-line
     *          arguments.
     *
     *      - help -- The help string describing the argument.
     *
     *      - metavar -- The name to be used for the option's argument with the
     *          help string. If None, the 'dest' value will be used as the name.
     */

    constructor() {
        let [
            option_strings,
            dest,
            nargs,
            const_value,
            default_value,
            type,
            choices,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            nargs: undefined,
            const: undefined,
            default: undefined,
            type: undefined,
            choices: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        // when this class is called as a function, redirect it to .call() method of itself
        super('return arguments.callee.call.apply(arguments.callee, arguments)')

        this.option_strings = option_strings
        this.dest = dest
        this.nargs = nargs
        this.const = const_value
        this.default = default_value
        this.type = type
        this.choices = choices
        this.required = required
        this.help = help
        this.metavar = metavar
    }

    _get_kwargs() {
        let names = [
            'option_strings',
            'dest',
            'nargs',
            'const',
            'default',
            'type',
            'choices',
            'help',
            'metavar'
        ]
        return names.map(name => [ name, getattr(this, name) ])
    }

    format_usage() {
        return this.option_strings[0]
    }

    call(/*parser, namespace, values, option_string = undefined*/) {
        throw new Error('.call() not defined')
    }
}))


const BooleanOptionalAction = _camelcase_alias(_callable(class BooleanOptionalAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            default_value,
            type,
            choices,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            default: undefined,
            type: undefined,
            choices: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        let _option_strings = []
        for (let option_string of option_strings) {
            _option_strings.push(option_string)

            if (option_string.startsWith('--')) {
                option_string = '--no-' + option_string.slice(2)
                _option_strings.push(option_string)
            }
        }

        if (help !== undefined && default_value !== undefined) {
            help += ` (default: ${default_value})`
        }

        super({
            option_strings: _option_strings,
            dest,
            nargs: 0,
            default: default_value,
            type,
            choices,
            required,
            help,
            metavar
        })
    }

    call(parser, namespace, values, option_string = undefined) {
        if (this.option_strings.includes(option_string)) {
            setattr(namespace, this.dest, !option_string.startsWith('--no-'))
        }
    }

    format_usage() {
        return this.option_strings.join(' | ')
    }
}))


const _StoreAction = _callable(class _StoreAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            nargs,
            const_value,
            default_value,
            type,
            choices,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            nargs: undefined,
            const: undefined,
            default: undefined,
            type: undefined,
            choices: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        if (nargs === 0) {
            throw new TypeError('nargs for store actions must be != 0; if you ' +
                        'have nothing to store, actions such as store ' +
                        'true or store const may be more appropriate')
        }
        if (const_value !== undefined && nargs !== OPTIONAL) {
            throw new TypeError(sub('nargs must be %r to supply const', OPTIONAL))
        }
        super({
            option_strings,
            dest,
            nargs,
            const: const_value,
            default: default_value,
            type,
            choices,
            required,
            help,
            metavar
        })
    }

    call(parser, namespace, values/*, option_string = undefined*/) {
        setattr(namespace, this.dest, values)
    }
})


const _StoreConstAction = _callable(class _StoreConstAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            const_value,
            default_value,
            required,
            help
            //, metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            const: no_default,
            default: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        super({
            option_strings,
            dest,
            nargs: 0,
            const: const_value,
            default: default_value,
            required,
            help
        })
    }

    call(parser, namespace/*, values, option_string = undefined*/) {
        setattr(namespace, this.dest, this.const)
    }
})


const _StoreTrueAction = _callable(class _StoreTrueAction extends _StoreConstAction {

    constructor() {
        let [
            option_strings,
            dest,
            default_value,
            required,
            help
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            default: false,
            required: false,
            help: undefined
        })

        super({
            option_strings,
            dest,
            const: true,
            default: default_value,
            required,
            help
        })
    }
})


const _StoreFalseAction = _callable(class _StoreFalseAction extends _StoreConstAction {

    constructor() {
        let [
            option_strings,
            dest,
            default_value,
            required,
            help
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            default: true,
            required: false,
            help: undefined
        })

        super({
            option_strings,
            dest,
            const: false,
            default: default_value,
            required,
            help
        })
    }
})


const _AppendAction = _callable(class _AppendAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            nargs,
            const_value,
            default_value,
            type,
            choices,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            nargs: undefined,
            const: undefined,
            default: undefined,
            type: undefined,
            choices: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        if (nargs === 0) {
            throw new TypeError('nargs for append actions must be != 0; if arg ' +
                        'strings are not supplying the value to append, ' +
                        'the append const action may be more appropriate')
        }
        if (const_value !== undefined && nargs !== OPTIONAL) {
            throw new TypeError(sub('nargs must be %r to supply const', OPTIONAL))
        }
        super({
            option_strings,
            dest,
            nargs,
            const: const_value,
            default: default_value,
            type,
            choices,
            required,
            help,
            metavar
        })
    }

    call(parser, namespace, values/*, option_string = undefined*/) {
        let items = getattr(namespace, this.dest, undefined)
        items = _copy_items(items)
        items.push(values)
        setattr(namespace, this.dest, items)
    }
})


const _AppendConstAction = _callable(class _AppendConstAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            const_value,
            default_value,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            const: no_default,
            default: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        super({
            option_strings,
            dest,
            nargs: 0,
            const: const_value,
            default: default_value,
            required,
            help,
            metavar
        })
    }

    call(parser, namespace/*, values, option_string = undefined*/) {
        let items = getattr(namespace, this.dest, undefined)
        items = _copy_items(items)
        items.push(this.const)
        setattr(namespace, this.dest, items)
    }
})


const _CountAction = _callable(class _CountAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            default_value,
            required,
            help
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            default: undefined,
            required: false,
            help: undefined
        })

        super({
            option_strings,
            dest,
            nargs: 0,
            default: default_value,
            required,
            help
        })
    }

    call(parser, namespace/*, values, option_string = undefined*/) {
        let count = getattr(namespace, this.dest, undefined)
        if (count === undefined) {
            count = 0
        }
        setattr(namespace, this.dest, count + 1)
    }
})


const _HelpAction = _callable(class _HelpAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            default_value,
            help
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: SUPPRESS,
            default: SUPPRESS,
            help: undefined
        })

        super({
            option_strings,
            dest,
            default: default_value,
            nargs: 0,
            help
        })
    }

    call(parser/*, namespace, values, option_string = undefined*/) {
        parser.print_help()
        parser.exit()
    }
})


const _VersionAction = _callable(class _VersionAction extends Action {

    constructor() {
        let [
            option_strings,
            version,
            dest,
            default_value,
            help
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            version: undefined,
            dest: SUPPRESS,
            default: SUPPRESS,
            help: "show program's version number and exit"
        })

        super({
            option_strings,
            dest,
            default: default_value,
            nargs: 0,
            help
        })
        this.version = version
    }

    call(parser/*, namespace, values, option_string = undefined*/) {
        let version = this.version
        if (version === undefined) {
            version = parser.version
        }
        let formatter = parser._get_formatter()
        formatter.add_text(version)
        parser._print_message(formatter.format_help(), process.stdout)
        parser.exit()
    }
})


const _SubParsersAction = _camelcase_alias(_callable(class _SubParsersAction extends Action {

    constructor() {
        let [
            option_strings,
            prog,
            parser_class,
            dest,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            prog: no_default,
            parser_class: no_default,
            dest: SUPPRESS,
            required: false,
            help: undefined,
            metavar: undefined
        })

        let name_parser_map = {}

        super({
            option_strings,
            dest,
            nargs: PARSER,
            choices: name_parser_map,
            required,
            help,
            metavar
        })

        this._prog_prefix = prog
        this._parser_class = parser_class
        this._name_parser_map = name_parser_map
        this._choices_actions = []
    }

    add_parser() {
        let [
            name,
            kwargs
        ] = _parse_opts(arguments, {
            name: no_default,
            '**kwargs': no_default
        })

        // set prog from the existing prefix
        if (kwargs.prog === undefined) {
            kwargs.prog = sub('%s %s', this._prog_prefix, name)
        }

        let aliases = getattr(kwargs, 'aliases', [])
        delete kwargs.aliases

        // create a pseudo-action to hold the choice help
        if ('help' in kwargs) {
            let help = kwargs.help
            delete kwargs.help
            let choice_action = this._ChoicesPseudoAction(name, aliases, help)
            this._choices_actions.push(choice_action)
        }

        // create the parser and add it to the map
        let parser = new this._parser_class(kwargs)
        this._name_parser_map[name] = parser

        // make parser available under aliases also
        for (let alias of aliases) {
            this._name_parser_map[alias] = parser
        }

        return parser
    }

    _get_subactions() {
        return this._choices_actions
    }

    call(parser, namespace, values/*, option_string = undefined*/) {
        let parser_name = values[0]
        let arg_strings = values.slice(1)

        // set the parser name if requested
        if (this.dest !== SUPPRESS) {
            setattr(namespace, this.dest, parser_name)
        }

        // select the parser
        if (hasattr(this._name_parser_map, parser_name)) {
            parser = this._name_parser_map[parser_name]
        } else {
            let args = {parser_name,
                        choices: this._name_parser_map.join(', ')}
            let msg = sub('unknown parser %(parser_name)r (choices: %(choices)s)', args)
            throw new ArgumentError(this, msg)
        }

        // parse all the remaining options into the namespace
        // store any unrecognized options on the object, so that the top
        // level parser can decide what to do with them

        // In case this subparser defines new defaults, we parse them
        // in a new namespace object and then update the original
        // namespace for the relevant parts.
        let subnamespace
        [ subnamespace, arg_strings ] = parser.parse_known_args(arg_strings, undefined)
        for (let [ key, value ] of Object.entries(subnamespace)) {
            setattr(namespace, key, value)
        }

        if (arg_strings.length) {
            setdefault(namespace, _UNRECOGNIZED_ARGS_ATTR, [])
            getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).push(...arg_strings)
        }
    }
}))


_SubParsersAction.prototype._ChoicesPseudoAction = _callable(class _ChoicesPseudoAction extends Action {
    constructor(name, aliases, help) {
        let metavar = name, dest = name
        if (aliases.length) {
            metavar += sub(' (%s)', aliases.join(', '))
        }
        super({ option_strings: [], dest, help, metavar })
    }
})


const _ExtendAction = _callable(class _ExtendAction extends _AppendAction {
    call(parser, namespace, values/*, option_string = undefined*/) {
        let items = getattr(namespace, this.dest, undefined)
        items = _copy_items(items)
        items = items.concat(values)
        setattr(namespace, this.dest, items)
    }
})


// ==============
// Type classes
// ==============
const FileType = _callable(class FileType extends Function {
    /*
     *  Factory for creating file object types
     *
     *  Instances of FileType are typically passed as type= arguments to the
     *  ArgumentParser add_argument() method.
     *
     *  Keyword Arguments:
     *      - mode -- A string indicating how the file is to be opened. Accepts the
     *          same values as the builtin open() function.
     *      - bufsize -- The file's desired buffer size. Accepts the same values as
     *          the builtin open() function.
     *      - encoding -- The file's encoding. Accepts the same values as the
     *          builtin open() function.
     *      - errors -- A string indicating how encoding and decoding errors are to
     *          be handled. Accepts the same value as the builtin open() function.
     */

    constructor() {
        let [
            flags,
            encoding,
            mode,
            autoClose,
            emitClose,
            start,
            end,
            highWaterMark,
            fs
        ] = _parse_opts(arguments, {
            flags: 'r',
            encoding: undefined,
            mode: undefined, // 0o666
            autoClose: undefined, // true
            emitClose: undefined, // false
            start: undefined, // 0
            end: undefined, // Infinity
            highWaterMark: undefined, // 64 * 1024
            fs: undefined
        })

        // when this class is called as a function, redirect it to .call() method of itself
        super('return arguments.callee.call.apply(arguments.callee, arguments)')

        Object.defineProperty(this, 'name', {
            get() {
                return sub('FileType(%r)', flags)
            }
        })
        this._flags = flags
        this._options = {}
        if (encoding !== undefined) this._options.encoding = encoding
        if (mode !== undefined) this._options.mode = mode
        if (autoClose !== undefined) this._options.autoClose = autoClose
        if (emitClose !== undefined) this._options.emitClose = emitClose
        if (start !== undefined) this._options.start = start
        if (end !== undefined) this._options.end = end
        if (highWaterMark !== undefined) this._options.highWaterMark = highWaterMark
        if (fs !== undefined) this._options.fs = fs
    }

    call(string) {
        // the special argument "-" means sys.std{in,out}
        if (string === '-') {
            if (this._flags.includes('r')) {
                return process.stdin
            } else if (this._flags.includes('w')) {
                return process.stdout
            } else {
                let msg = sub('argument "-" with mode %r', this._flags)
                throw new TypeError(msg)
            }
        }

        // all other arguments are used as file names
        let fd
        try {
            fd = fs.openSync(string, this._flags, this._options.mode)
        } catch (e) {
            let args = { filename: string, error: e.message }
            let message = "can't open '%(filename)s': %(error)s"
            throw new ArgumentTypeError(sub(message, args))
        }

        let options = Object.assign({ fd, flags: this._flags }, this._options)
        if (this._flags.includes('r')) {
            return fs.createReadStream(undefined, options)
        } else if (this._flags.includes('w')) {
            return fs.createWriteStream(undefined, options)
        } else {
            let msg = sub('argument "%s" with mode %r', string, this._flags)
            throw new TypeError(msg)
        }
    }

    [util.inspect.custom]() {
        let args = [ this._flags ]
        let kwargs = Object.entries(this._options).map(([ k, v ]) => {
            if (k === 'mode') v = { value: v, [util.inspect.custom]() { return '0o' + this.value.toString(8) } }
            return [ k, v ]
        })
        let args_str = []
                .concat(args.filter(arg => arg !== -1).map(repr))
                .concat(kwargs.filter(([/*kw*/, arg]) => arg !== undefined)
                    .map(([kw, arg]) => sub('%s=%r', kw, arg)))
                .join(', ')
        return sub('%s(%s)', this.constructor.name, args_str)
    }

    toString() {
        return this[util.inspect.custom]()
    }
})

// ===========================
// Optional and Positional Parsing
// ===========================
const Namespace = _callable(class Namespace extends _AttributeHolder() {
    /*
     *  Simple object for storing attributes.
     *
     *  Implements equality by attribute names and values, and provides a simple
     *  string representation.
     */

    constructor(options = {}) {
        super()
        Object.assign(this, options)
    }
})

// unset string tag to mimic plain object
Namespace.prototype[Symbol.toStringTag] = undefined


const _ActionsContainer = _camelcase_alias(_callable(class _ActionsContainer {

    constructor() {
        let [
            description,
            prefix_chars,
            argument_default,
            conflict_handler
        ] = _parse_opts(arguments, {
            description: no_default,
            prefix_chars: no_default,
            argument_default: no_default,
            conflict_handler: no_default
        })

        this.description = description
        this.argument_default = argument_default
        this.prefix_chars = prefix_chars
        this.conflict_handler = conflict_handler

        // set up registries
        this._registries = {}

        // register actions
        this.register('action', undefined, _StoreAction)
        this.register('action', 'store', _StoreAction)
        this.register('action', 'store_const', _StoreConstAction)
        this.register('action', 'store_true', _StoreTrueAction)
        this.register('action', 'store_false', _StoreFalseAction)
        this.register('action', 'append', _AppendAction)
        this.register('action', 'append_const', _AppendConstAction)
        this.register('action', 'count', _CountAction)
        this.register('action', 'help', _HelpAction)
        this.register('action', 'version', _VersionAction)
        this.register('action', 'parsers', _SubParsersAction)
        this.register('action', 'extend', _ExtendAction)
        // LEGACY (v1 compatibility): camelcase variants
        ;[ 'storeConst', 'storeTrue', 'storeFalse', 'appendConst' ].forEach(old_name => {
            let new_name = _to_new_name(old_name)
            this.register('action', old_name, util.deprecate(this._registry_get('action', new_name),
                sub('{action: "%s"} is renamed to {action: "%s"}', old_name, new_name)))
        })
        // end

        // raise an exception if the conflict handler is invalid
        this._get_handler()

        // action storage
        this._actions = []
        this._option_string_actions = {}

        // groups
        this._action_groups = []
        this._mutually_exclusive_groups = []

        // defaults storage
        this._defaults = {}

        // determines whether an "option" looks like a negative number
        this._negative_number_matcher = /^-\d+$|^-\d*\.\d+$/

        // whether or not there are any optionals that look like negative
        // numbers -- uses a list so it can be shared and edited
        this._has_negative_number_optionals = []
    }

    // ====================
    // Registration methods
    // ====================
    register(registry_name, value, object) {
        let registry = setdefault(this._registries, registry_name, {})
        registry[value] = object
    }

    _registry_get(registry_name, value, default_value = undefined) {
        return getattr(this._registries[registry_name], value, default_value)
    }

    // ==================================
    // Namespace default accessor methods
    // ==================================
    set_defaults(kwargs) {
        Object.assign(this._defaults, kwargs)

        // if these defaults match any existing arguments, replace
        // the previous default on the object with the new one
        for (let action of this._actions) {
            if (action.dest in kwargs) {
                action.default = kwargs[action.dest]
            }
        }
    }

    get_default(dest) {
        for (let action of this._actions) {
            if (action.dest === dest && action.default !== undefined) {
                return action.default
            }
        }
        return this._defaults[dest]
    }


    // =======================
    // Adding argument actions
    // =======================
    add_argument() {
        /*
         *  add_argument(dest, ..., name=value, ...)
         *  add_argument(option_string, option_string, ..., name=value, ...)
         */
        let [
            args,
            kwargs
        ] = _parse_opts(arguments, {
            '*args': no_default,
            '**kwargs': no_default
        })
        // LEGACY (v1 compatibility), old-style add_argument([ args ], { options })
        if (args.length === 1 && Array.isArray(args[0])) {
            args = args[0]
            deprecate('argument-array',
                sub('use add_argument(%(args)s, {...}) instead of add_argument([ %(args)s ], { ... })', {
                    args: args.map(repr).join(', ')
                }))
        }
        // end

        // if no positional args are supplied or only one is supplied and
        // it doesn't look like an option string, parse a positional
        // argument
        let chars = this.prefix_chars
        if (!args.length || args.length === 1 && !chars.includes(args[0][0])) {
            if (args.length && 'dest' in kwargs) {
                throw new TypeError('dest supplied twice for positional argument')
            }
            kwargs = this._get_positional_kwargs(...args, kwargs)

        // otherwise, we're adding an optional argument
        } else {
            kwargs = this._get_optional_kwargs(...args, kwargs)
        }

        // if no default was supplied, use the parser-level default
        if (!('default' in kwargs)) {
            let dest = kwargs.dest
            if (dest in this._defaults) {
                kwargs.default = this._defaults[dest]
            } else if (this.argument_default !== undefined) {
                kwargs.default = this.argument_default
            }
        }

        // create the action object, and add it to the parser
        let action_class = this._pop_action_class(kwargs)
        if (typeof action_class !== 'function') {
            throw new TypeError(sub('unknown action "%s"', action_class))
        }
        // eslint-disable-next-line new-cap
        let action = new action_class(kwargs)

        // raise an error if the action type is not callable
        let type_func = this._registry_get('type', action.type, action.type)
        if (typeof type_func !== 'function') {
            throw new TypeError(sub('%r is not callable', type_func))
        }

        if (type_func === FileType) {
            throw new TypeError(sub('%r is a FileType class object, instance of it' +
                                    ' must be passed', type_func))
        }

        // raise an error if the metavar does not match the type
        if ('_get_formatter' in this) {
            try {
                this._get_formatter()._format_args(action, undefined)
            } catch (err) {
                // check for 'invalid nargs value' is an artifact of TypeError and ValueError in js being the same
                if (err instanceof TypeError && err.message !== 'invalid nargs value') {
                    throw new TypeError('length of metavar tuple does not match nargs')
                } else {
                    throw err
                }
            }
        }

        return this._add_action(action)
    }

    add_argument_group() {
        let group = _ArgumentGroup(this, ...arguments)
        this._action_groups.push(group)
        return group
    }

    add_mutually_exclusive_group() {
        // eslint-disable-next-line no-use-before-define
        let group = _MutuallyExclusiveGroup(this, ...arguments)
        this._mutually_exclusive_groups.push(group)
        return group
    }

    _add_action(action) {
        // resolve any conflicts
        this._check_conflict(action)

        // add to actions list
        this._actions.push(action)
        action.container = this

        // index the action by any option strings it has
        for (let option_string of action.option_strings) {
            this._option_string_actions[option_string] = action
        }

        // set the flag if any option strings look like negative numbers
        for (let option_string of action.option_strings) {
            if (this._negative_number_matcher.test(option_string)) {
                if (!this._has_negative_number_optionals.length) {
                    this._has_negative_number_optionals.push(true)
                }
            }
        }

        // return the created action
        return action
    }

    _remove_action(action) {
        _array_remove(this._actions, action)
    }

    _add_container_actions(container) {
        // collect groups by titles
        let title_group_map = {}
        for (let group of this._action_groups) {
            if (group.title in title_group_map) {
                let msg = 'cannot merge actions - two groups are named %r'
                throw new TypeError(sub(msg, group.title))
            }
            title_group_map[group.title] = group
        }

        // map each action to its group
        let group_map = new Map()
        for (let group of container._action_groups) {

            // if a group with the title exists, use that, otherwise
            // create a new group matching the container's group
            if (!(group.title in title_group_map)) {
                title_group_map[group.title] = this.add_argument_group({
                    title: group.title,
                    description: group.description,
                    conflict_handler: group.conflict_handler
                })
            }

            // map the actions to their new group
            for (let action of group._group_actions) {
                group_map.set(action, title_group_map[group.title])
            }
        }

        // add container's mutually exclusive groups
        // NOTE: if add_mutually_exclusive_group ever gains title= and
        // description= then this code will need to be expanded as above
        for (let group of container._mutually_exclusive_groups) {
            let mutex_group = this.add_mutually_exclusive_group({
                required: group.required
            })

            // map the actions to their new mutex group
            for (let action of group._group_actions) {
                group_map.set(action, mutex_group)
            }
        }

        // add all actions to this container or their group
        for (let action of container._actions) {
            group_map.get(action)._add_action(action)
        }
    }

    _get_positional_kwargs() {
        let [
            dest,
            kwargs
        ] = _parse_opts(arguments, {
            dest: no_default,
            '**kwargs': no_default
        })

        // make sure required is not specified
        if ('required' in kwargs) {
            let msg = "'required' is an invalid argument for positionals"
            throw new TypeError(msg)
        }

        // mark positional arguments as required if at least one is
        // always required
        if (![OPTIONAL, ZERO_OR_MORE].includes(kwargs.nargs)) {
            kwargs.required = true
        }
        if (kwargs.nargs === ZERO_OR_MORE && !('default' in kwargs)) {
            kwargs.required = true
        }

        // return the keyword arguments with no option strings
        return Object.assign(kwargs, { dest, option_strings: [] })
    }

    _get_optional_kwargs() {
        let [
            args,
            kwargs
        ] = _parse_opts(arguments, {
            '*args': no_default,
            '**kwargs': no_default
        })

        // determine short and long option strings
        let option_strings = []
        let long_option_strings = []
        let option_string
        for (option_string of args) {
            // error on strings that don't start with an appropriate prefix
            if (!this.prefix_chars.includes(option_string[0])) {
                let args = {option: option_string,
                            prefix_chars: this.prefix_chars}
                let msg = 'invalid option string %(option)r: ' +
                          'must start with a character %(prefix_chars)r'
                throw new TypeError(sub(msg, args))
            }

            // strings starting with two prefix characters are long options
            option_strings.push(option_string)
            if (option_string.length > 1 && this.prefix_chars.includes(option_string[1])) {
                long_option_strings.push(option_string)
            }
        }

        // infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
        let dest = kwargs.dest
        delete kwargs.dest
        if (dest === undefined) {
            let dest_option_string
            if (long_option_strings.length) {
                dest_option_string = long_option_strings[0]
            } else {
                dest_option_string = option_strings[0]
            }
            dest = _string_lstrip(dest_option_string, this.prefix_chars)
            if (!dest) {
                let msg = 'dest= is required for options like %r'
                throw new TypeError(sub(msg, option_string))
            }
            dest = dest.replace(/-/g, '_')
        }

        // return the updated keyword arguments
        return Object.assign(kwargs, { dest, option_strings })
    }

    _pop_action_class(kwargs, default_value = undefined) {
        let action = getattr(kwargs, 'action', default_value)
        delete kwargs.action
        return this._registry_get('action', action, action)
    }

    _get_handler() {
        // determine function from conflict handler string
        let handler_func_name = sub('_handle_conflict_%s', this.conflict_handler)
        if (typeof this[handler_func_name] === 'function') {
            return this[handler_func_name]
        } else {
            let msg = 'invalid conflict_resolution value: %r'
            throw new TypeError(sub(msg, this.conflict_handler))
        }
    }

    _check_conflict(action) {

        // find all options that conflict with this option
        let confl_optionals = []
        for (let option_string of action.option_strings) {
            if (hasattr(this._option_string_actions, option_string)) {
                let confl_optional = this._option_string_actions[option_string]
                confl_optionals.push([ option_string, confl_optional ])
            }
        }

        // resolve any conflicts
        if (confl_optionals.length) {
            let conflict_handler = this._get_handler()
            conflict_handler.call(this, action, confl_optionals)
        }
    }

    _handle_conflict_error(action, conflicting_actions) {
        let message = conflicting_actions.length === 1 ?
            'conflicting option string: %s' :
            'conflicting option strings: %s'
        let conflict_string = conflicting_actions.map(([ option_string/*, action*/ ]) => option_string).join(', ')
        throw new ArgumentError(action, sub(message, conflict_string))
    }

    _handle_conflict_resolve(action, conflicting_actions) {

        // remove all conflicting options
        for (let [ option_string, action ] of conflicting_actions) {

            // remove the conflicting option
            _array_remove(action.option_strings, option_string)
            delete this._option_string_actions[option_string]

            // if the option now has no option string, remove it from the
            // container holding it
            if (!action.option_strings.length) {
                action.container._remove_action(action)
            }
        }
    }
}))


const _ArgumentGroup = _callable(class _ArgumentGroup extends _ActionsContainer {

    constructor() {
        let [
            container,
            title,
            description,
            kwargs
        ] = _parse_opts(arguments, {
            container: no_default,
            title: undefined,
            description: undefined,
            '**kwargs': no_default
        })

        // add any missing keyword arguments by checking the container
        setdefault(kwargs, 'conflict_handler', container.conflict_handler)
        setdefault(kwargs, 'prefix_chars', container.prefix_chars)
        setdefault(kwargs, 'argument_default', container.argument_default)
        super(Object.assign({ description }, kwargs))

        // group attributes
        this.title = title
        this._group_actions = []

        // share most attributes with the container
        this._registries = container._registries
        this._actions = container._actions
        this._option_string_actions = container._option_string_actions
        this._defaults = container._defaults
        this._has_negative_number_optionals =
            container._has_negative_number_optionals
        this._mutually_exclusive_groups = container._mutually_exclusive_groups
    }

    _add_action(action) {
        action = super._add_action(action)
        this._group_actions.push(action)
        return action
    }

    _remove_action(action) {
        super._remove_action(action)
        _array_remove(this._group_actions, action)
    }
})


const _MutuallyExclusiveGroup = _callable(class _MutuallyExclusiveGroup extends _ArgumentGroup {

    constructor() {
        let [
            container,
            required
        ] = _parse_opts(arguments, {
            container: no_default,
            required: false
        })

        super(container)
        this.required = required
        this._container = container
    }

    _add_action(action) {
        if (action.required) {
            let msg = 'mutually exclusive arguments must be optional'
            throw new TypeError(msg)
        }
        action = this._container._add_action(action)
        this._group_actions.push(action)
        return action
    }

    _remove_action(action) {
        this._container._remove_action(action)
        _array_remove(this._group_actions, action)
    }
})


const ArgumentParser = _camelcase_alias(_callable(class ArgumentParser extends _AttributeHolder(_ActionsContainer) {
    /*
     *  Object for parsing command line strings into Python objects.
     *
     *  Keyword Arguments:
     *      - prog -- The name of the program (default: sys.argv[0])
     *      - usage -- A usage message (default: auto-generated from arguments)
     *      - description -- A description of what the program does
     *      - epilog -- Text following the argument descriptions
     *      - parents -- Parsers whose arguments should be copied into this one
     *      - formatter_class -- HelpFormatter class for printing help messages
     *      - prefix_chars -- Characters that prefix optional arguments
     *      - fromfile_prefix_chars -- Characters that prefix files containing
     *          additional arguments
     *      - argument_default -- The default value for all arguments
     *      - conflict_handler -- String indicating how to handle conflicts
     *      - add_help -- Add a -h/-help option
     *      - allow_abbrev -- Allow long options to be abbreviated unambiguously
     *      - exit_on_error -- Determines whether or not ArgumentParser exits with
     *          error info when an error occurs
     */

    constructor() {
        let [
            prog,
            usage,
            description,
            epilog,
            parents,
            formatter_class,
            prefix_chars,
            fromfile_prefix_chars,
            argument_default,
            conflict_handler,
            add_help,
            allow_abbrev,
            exit_on_error,
            debug, // LEGACY (v1 compatibility), debug mode
            version // LEGACY (v1 compatibility), version
        ] = _parse_opts(arguments, {
            prog: undefined,
            usage: undefined,
            description: undefined,
            epilog: undefined,
            parents: [],
            formatter_class: HelpFormatter,
            prefix_chars: '-',
            fromfile_prefix_chars: undefined,
            argument_default: undefined,
            conflict_handler: 'error',
            add_help: true,
            allow_abbrev: true,
            exit_on_error: true,
            debug: undefined, // LEGACY (v1 compatibility), debug mode
            version: undefined // LEGACY (v1 compatibility), version
        })

        // LEGACY (v1 compatibility)
        if (debug !== undefined) {
            deprecate('debug',
                'The "debug" argument to ArgumentParser is deprecated. Please ' +
                'override ArgumentParser.exit function instead.'
            )
        }

        if (version !== undefined) {
            deprecate('version',
                'The "version" argument to ArgumentParser is deprecated. Please use ' +
                "add_argument(..., { action: 'version', version: 'N', ... }) instead."
            )
        }
        // end

        super({
            description,
            prefix_chars,
            argument_default,
            conflict_handler
        })

        // default setting for prog
        if (prog === undefined) {
            prog = path.basename(get_argv()[0] || '')
        }

        this.prog = prog
        this.usage = usage
        this.epilog = epilog
        this.formatter_class = formatter_class
        this.fromfile_prefix_chars = fromfile_prefix_chars
        this.add_help = add_help
        this.allow_abbrev = allow_abbrev
        this.exit_on_error = exit_on_error
        // LEGACY (v1 compatibility), debug mode
        this.debug = debug
        // end

        this._positionals = this.add_argument_group('positional arguments')
        this._optionals = this.add_argument_group('optional arguments')
        this._subparsers = undefined

        // register types
        function identity(string) {
            return string
        }
        this.register('type', undefined, identity)
        this.register('type', null, identity)
        this.register('type', 'auto', identity)
        this.register('type', 'int', function (x) {
            let result = Number(x)
            if (!Number.isInteger(result)) {
                throw new TypeError(sub('could not convert string to int: %r', x))
            }
            return result
        })
        this.register('type', 'float', function (x) {
            let result = Number(x)
            if (isNaN(result)) {
                throw new TypeError(sub('could not convert string to float: %r', x))
            }
            return result
        })
        this.register('type', 'str', String)
        // LEGACY (v1 compatibility): custom types
        this.register('type', 'string',
            util.deprecate(String, 'use {type:"str"} or {type:String} instead of {type:"string"}'))
        // end

        // add help argument if necessary
        // (using explicit default to override global argument_default)
        let default_prefix = prefix_chars.includes('-') ? '-' : prefix_chars[0]
        if (this.add_help) {
            this.add_argument(
                default_prefix + 'h',
                default_prefix.repeat(2) + 'help',
                {
                    action: 'help',
                    default: SUPPRESS,
                    help: 'show this help message and exit'
                }
            )
        }
        // LEGACY (v1 compatibility), version
        if (version) {
            this.add_argument(
                default_prefix + 'v',
                default_prefix.repeat(2) + 'version',
                {
                    action: 'version',
                    default: SUPPRESS,
                    version: this.version,
                    help: "show program's version number and exit"
                }
            )
        }
        // end

        // add parent arguments and defaults
        for (let parent of parents) {
            this._add_container_actions(parent)
            Object.assign(this._defaults, parent._defaults)
        }
    }

    // =======================
    // Pretty __repr__ methods
    // =======================
    _get_kwargs() {
        let names = [
            'prog',
            'usage',
            'description',
            'formatter_class',
            'conflict_handler',
            'add_help'
        ]
        return names.map(name => [ name, getattr(this, name) ])
    }

    // ==================================
    // Optional/Positional adding methods
    // ==================================
    add_subparsers() {
        let [
            kwargs
        ] = _parse_opts(arguments, {
            '**kwargs': no_default
        })

        if (this._subparsers !== undefined) {
            this.error('cannot have multiple subparser arguments')
        }

        // add the parser class to the arguments if it's not present
        setdefault(kwargs, 'parser_class', this.constructor)

        if ('title' in kwargs || 'description' in kwargs) {
            let title = getattr(kwargs, 'title', 'subcommands')
            let description = getattr(kwargs, 'description', undefined)
            delete kwargs.title
            delete kwargs.description
            this._subparsers = this.add_argument_group(title, description)
        } else {
            this._subparsers = this._positionals
        }

        // prog defaults to the usage message of this parser, skipping
        // optional arguments and with no "usage:" prefix
        if (kwargs.prog === undefined) {
            let formatter = this._get_formatter()
            let positionals = this._get_positional_actions()
            let groups = this._mutually_exclusive_groups
            formatter.add_usage(this.usage, positionals, groups, '')
            kwargs.prog = formatter.format_help().trim()
        }

        // create the parsers action and add it to the positionals list
        let parsers_class = this._pop_action_class(kwargs, 'parsers')
        // eslint-disable-next-line new-cap
        let action = new parsers_class(Object.assign({ option_strings: [] }, kwargs))
        this._subparsers._add_action(action)

        // return the created parsers action
        return action
    }

    _add_action(action) {
        if (action.option_strings.length) {
            this._optionals._add_action(action)
        } else {
            this._positionals._add_action(action)
        }
        return action
    }

    _get_optional_actions() {
        return this._actions.filter(action => action.option_strings.length)
    }

    _get_positional_actions() {
        return this._actions.filter(action => !action.option_strings.length)
    }

    // =====================================
    // Command line argument parsing methods
    // =====================================
    parse_args(args = undefined, namespace = undefined) {
        let argv
        [ args, argv ] = this.parse_known_args(args, namespace)
        if (argv && argv.length > 0) {
            let msg = 'unrecognized arguments: %s'
            this.error(sub(msg, argv.join(' ')))
        }
        return args
    }

    parse_known_args(args = undefined, namespace = undefined) {
        if (args === undefined) {
            args = get_argv().slice(1)
        }

        // default Namespace built from parser defaults
        if (namespace === undefined) {
            namespace = new Namespace()
        }

        // add any action defaults that aren't present
        for (let action of this._actions) {
            if (action.dest !== SUPPRESS) {
                if (!hasattr(namespace, action.dest)) {
                    if (action.default !== SUPPRESS) {
                        setattr(namespace, action.dest, action.default)
                    }
                }
            }
        }

        // add any parser defaults that aren't present
        for (let dest of Object.keys(this._defaults)) {
            if (!hasattr(namespace, dest)) {
                setattr(namespace, dest, this._defaults[dest])
            }
        }

        // parse the arguments and exit if there are any errors
        if (this.exit_on_error) {
            try {
                [ namespace, args ] = this._parse_known_args(args, namespace)
            } catch (err) {
                if (err instanceof ArgumentError) {
                    this.error(err.message)
                } else {
                    throw err
                }
            }
        } else {
            [ namespace, args ] = this._parse_known_args(args, namespace)
        }

        if (hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) {
            args = args.concat(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
            delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
        }

        return [ namespace, args ]
    }

    _parse_known_args(arg_strings, namespace) {
        // replace arg strings that are file references
        if (this.fromfile_prefix_chars !== undefined) {
            arg_strings = this._read_args_from_files(arg_strings)
        }

        // map all mutually exclusive arguments to the other arguments
        // they can't occur with
        let action_conflicts = new Map()
        for (let mutex_group of this._mutually_exclusive_groups) {
            let group_actions = mutex_group._group_actions
            for (let [ i, mutex_action ] of Object.entries(mutex_group._group_actions)) {
                let conflicts = action_conflicts.get(mutex_action) || []
                conflicts = conflicts.concat(group_actions.slice(0, +i))
                conflicts = conflicts.concat(group_actions.slice(+i + 1))
                action_conflicts.set(mutex_action, conflicts)
            }
        }

        // find all option indices, and determine the arg_string_pattern
        // which has an 'O' if there is an option at an index,
        // an 'A' if there is an argument, or a '-' if there is a '--'
        let option_string_indices = {}
        let arg_string_pattern_parts = []
        let arg_strings_iter = Object.entries(arg_strings)[Symbol.iterator]()
        for (let [ i, arg_string ] of arg_strings_iter) {

            // all args after -- are non-options
            if (arg_string === '--') {
                arg_string_pattern_parts.push('-')
                for ([ i, arg_string ] of arg_strings_iter) {
                    arg_string_pattern_parts.push('A')
                }

            // otherwise, add the arg to the arg strings
            // and note the index if it was an option
            } else {
                let option_tuple = this._parse_optional(arg_string)
                let pattern
                if (option_tuple === undefined) {
                    pattern = 'A'
                } else {
                    option_string_indices[i] = option_tuple
                    pattern = 'O'
                }
                arg_string_pattern_parts.push(pattern)
            }
        }

        // join the pieces together to form the pattern
        let arg_strings_pattern = arg_string_pattern_parts.join('')

        // converts arg strings to the appropriate and then takes the action
        let seen_actions = new Set()
        let seen_non_default_actions = new Set()
        let extras

        let take_action = (action, argument_strings, option_string = undefined) => {
            seen_actions.add(action)
            let argument_values = this._get_values(action, argument_strings)

            // error if this argument is not allowed with other previously
            // seen arguments, assuming that actions that use the default
            // value don't really count as "present"
            if (argument_values !== action.default) {
                seen_non_default_actions.add(action)
                for (let conflict_action of action_conflicts.get(action) || []) {
                    if (seen_non_default_actions.has(conflict_action)) {
                        let msg = 'not allowed with argument %s'
                        let action_name = _get_action_name(conflict_action)
                        throw new ArgumentError(action, sub(msg, action_name))
                    }
                }
            }

            // take the action if we didn't receive a SUPPRESS value
            // (e.g. from a default)
            if (argument_values !== SUPPRESS) {
                action(this, namespace, argument_values, option_string)
            }
        }

        // function to convert arg_strings into an optional action
        let consume_optional = start_index => {

            // get the optional identified at this index
            let option_tuple = option_string_indices[start_index]
            let [ action, option_string, explicit_arg ] = option_tuple

            // identify additional optionals in the same arg string
            // (e.g. -xyz is the same as -x -y -z if no args are required)
            let action_tuples = []
            let stop
            for (;;) {

                // if we found no optional action, skip it
                if (action === undefined) {
                    extras.push(arg_strings[start_index])
                    return start_index + 1
                }

                // if there is an explicit argument, try to match the
                // optional's string arguments to only this
                if (explicit_arg !== undefined) {
                    let arg_count = this._match_argument(action, 'A')

                    // if the action is a single-dash option and takes no
                    // arguments, try to parse more single-dash options out
                    // of the tail of the option string
                    let chars = this.prefix_chars
                    if (arg_count === 0 && !chars.includes(option_string[1])) {
                        action_tuples.push([ action, [], option_string ])
                        let char = option_string[0]
                        option_string = char + explicit_arg[0]
                        let new_explicit_arg = explicit_arg.slice(1) || undefined
                        let optionals_map = this._option_string_actions
                        if (hasattr(optionals_map, option_string)) {
                            action = optionals_map[option_string]
                            explicit_arg = new_explicit_arg
                        } else {
                            let msg = 'ignored explicit argument %r'
                            throw new ArgumentError(action, sub(msg, explicit_arg))
                        }

                    // if the action expect exactly one argument, we've
                    // successfully matched the option; exit the loop
                    } else if (arg_count === 1) {
                        stop = start_index + 1
                        let args = [ explicit_arg ]
                        action_tuples.push([ action, args, option_string ])
                        break

                    // error if a double-dash option did not use the
                    // explicit argument
                    } else {
                        let msg = 'ignored explicit argument %r'
                        throw new ArgumentError(action, sub(msg, explicit_arg))
                    }

                // if there is no explicit argument, try to match the
                // optional's string arguments with the following strings
                // if successful, exit the loop
                } else {
                    let start = start_index + 1
                    let selected_patterns = arg_strings_pattern.slice(start)
                    let arg_count = this._match_argument(action, selected_patterns)
                    stop = start + arg_count
                    let args = arg_strings.slice(start, stop)
                    action_tuples.push([ action, args, option_string ])
                    break
                }
            }

            // add the Optional to the list and return the index at which
            // the Optional's string args stopped
            assert(action_tuples.length)
            for (let [ action, args, option_string ] of action_tuples) {
                take_action(action, args, option_string)
            }
            return stop
        }

        // the list of Positionals left to be parsed; this is modified
        // by consume_positionals()
        let positionals = this._get_positional_actions()

        // function to convert arg_strings into positional actions
        let consume_positionals = start_index => {
            // match as many Positionals as possible
            let selected_pattern = arg_strings_pattern.slice(start_index)
            let arg_counts = this._match_arguments_partial(positionals, selected_pattern)

            // slice off the appropriate arg strings for each Positional
            // and add the Positional and its args to the list
            for (let i = 0; i < positionals.length && i < arg_counts.length; i++) {
                let action = positionals[i]
                let arg_count = arg_counts[i]
                let args = arg_strings.slice(start_index, start_index + arg_count)
                start_index += arg_count
                take_action(action, args)
            }

            // slice off the Positionals that we just parsed and return the
            // index at which the Positionals' string args stopped
            positionals = positionals.slice(arg_counts.length)
            return start_index
        }

        // consume Positionals and Optionals alternately, until we have
        // passed the last option string
        extras = []
        let start_index = 0
        let max_option_string_index = Math.max(-1, ...Object.keys(option_string_indices).map(Number))
        while (start_index <= max_option_string_index) {

            // consume any Positionals preceding the next option
            let next_option_string_index = Math.min(
                // eslint-disable-next-line no-loop-func
                ...Object.keys(option_string_indices).map(Number).filter(index => index >= start_index)
            )
            if (start_index !== next_option_string_index) {
                let positionals_end_index = consume_positionals(start_index)

                // only try to parse the next optional if we didn't consume
                // the option string during the positionals parsing
                if (positionals_end_index > start_index) {
                    start_index = positionals_end_index
                    continue
                } else {
                    start_index = positionals_end_index
                }
            }

            // if we consumed all the positionals we could and we're not
            // at the index of an option string, there were extra arguments
            if (!(start_index in option_string_indices)) {
                let strings = arg_strings.slice(start_index, next_option_string_index)
                extras = extras.concat(strings)
                start_index = next_option_string_index
            }

            // consume the next optional and any arguments for it
            start_index = consume_optional(start_index)
        }

        // consume any positionals following the last Optional
        let stop_index = consume_positionals(start_index)

        // if we didn't consume all the argument strings, there were extras
        extras = extras.concat(arg_strings.slice(stop_index))

        // make sure all required actions were present and also convert
        // action defaults which were not given as arguments
        let required_actions = []
        for (let action of this._actions) {
            if (!seen_actions.has(action)) {
                if (action.required) {
                    required_actions.push(_get_action_name(action))
                } else {
                    // Convert action default now instead of doing it before
                    // parsing arguments to avoid calling convert functions
                    // twice (which may fail) if the argument was given, but
                    // only if it was defined already in the namespace
                    if (action.default !== undefined &&
                        typeof action.default === 'string' &&
                        hasattr(namespace, action.dest) &&
                        action.default === getattr(namespace, action.dest)) {
                        setattr(namespace, action.dest,
                                this._get_value(action, action.default))
                    }
                }
            }
        }

        if (required_actions.length) {
            this.error(sub('the following arguments are required: %s',
                       required_actions.join(', ')))
        }

        // make sure all required groups had one option present
        for (let group of this._mutually_exclusive_groups) {
            if (group.required) {
                let no_actions_used = true
                for (let action of group._group_actions) {
                    if (seen_non_default_actions.has(action)) {
                        no_actions_used = false
                        break
                    }
                }

                // if no actions were used, report the error
                if (no_actions_used) {
                    let names = group._group_actions
                        .filter(action => action.help !== SUPPRESS)
                        .map(action => _get_action_name(action))
                    let msg = 'one of the arguments %s is required'
                    this.error(sub(msg, names.join(' ')))
                }
            }
        }

        // return the updated namespace and the extra arguments
        return [ namespace, extras ]
    }

    _read_args_from_files(arg_strings) {
        // expand arguments referencing files
        let new_arg_strings = []
        for (let arg_string of arg_strings) {

            // for regular arguments, just add them back into the list
            if (!arg_string || !this.fromfile_prefix_chars.includes(arg_string[0])) {
                new_arg_strings.push(arg_string)

            // replace arguments referencing files with the file content
            } else {
                try {
                    let args_file = fs.readFileSync(arg_string.slice(1), 'utf8')
                    let arg_strings = []
                    for (let arg_line of splitlines(args_file)) {
                        for (let arg of this.convert_arg_line_to_args(arg_line)) {
                            arg_strings.push(arg)
                        }
                    }
                    arg_strings = this._read_args_from_files(arg_strings)
                    new_arg_strings = new_arg_strings.concat(arg_strings)
                } catch (err) {
                    this.error(err.message)
                }
            }
        }

        // return the modified argument list
        return new_arg_strings
    }

    convert_arg_line_to_args(arg_line) {
        return [arg_line]
    }

    _match_argument(action, arg_strings_pattern) {
        // match the pattern for this action to the arg strings
        let nargs_pattern = this._get_nargs_pattern(action)
        let match = arg_strings_pattern.match(new RegExp('^' + nargs_pattern))

        // raise an exception if we weren't able to find a match
        if (match === null) {
            let nargs_errors = {
                undefined: 'expected one argument',
                [OPTIONAL]: 'expected at most one argument',
                [ONE_OR_MORE]: 'expected at least one argument'
            }
            let msg = nargs_errors[action.nargs]
            if (msg === undefined) {
                msg = sub(action.nargs === 1 ? 'expected %s argument' : 'expected %s arguments', action.nargs)
            }
            throw new ArgumentError(action, msg)
        }

        // return the number of arguments matched
        return match[1].length
    }

    _match_arguments_partial(actions, arg_strings_pattern) {
        // progressively shorten the actions list by slicing off the
        // final actions until we find a match
        let result = []
        for (let i of range(actions.length, 0, -1)) {
            let actions_slice = actions.slice(0, i)
            let pattern = actions_slice.map(action => this._get_nargs_pattern(action)).join('')
            let match = arg_strings_pattern.match(new RegExp('^' + pattern))
            if (match !== null) {
                result = result.concat(match.slice(1).map(string => string.length))
                break
            }
        }

        // return the list of arg string counts
        return result
    }

    _parse_optional(arg_string) {
        // if it's an empty string, it was meant to be a positional
        if (!arg_string) {
            return undefined
        }

        // if it doesn't start with a prefix, it was meant to be positional
        if (!this.prefix_chars.includes(arg_string[0])) {
            return undefined
        }

        // if the option string is present in the parser, return the action
        if (arg_string in this._option_string_actions) {
            let action = this._option_string_actions[arg_string]
            return [ action, arg_string, undefined ]
        }

        // if it's just a single character, it was meant to be positional
        if (arg_string.length === 1) {
            return undefined
        }

        // if the option string before the "=" is present, return the action
        if (arg_string.includes('=')) {
            let [ option_string, explicit_arg ] = _string_split(arg_string, '=', 1)
            if (option_string in this._option_string_actions) {
                let action = this._option_string_actions[option_string]
                return [ action, option_string, explicit_arg ]
            }
        }

        // search through all possible prefixes of the option string
        // and all actions in the parser for possible interpretations
        let option_tuples = this._get_option_tuples(arg_string)

        // if multiple actions match, the option string was ambiguous
        if (option_tuples.length > 1) {
            let options = option_tuples.map(([ /*action*/, option_string/*, explicit_arg*/ ]) => option_string).join(', ')
            let args = {option: arg_string, matches: options}
            let msg = 'ambiguous option: %(option)s could match %(matches)s'
            this.error(sub(msg, args))

        // if exactly one action matched, this segmentation is good,
        // so return the parsed action
        } else if (option_tuples.length === 1) {
            let [ option_tuple ] = option_tuples
            return option_tuple
        }

        // if it was not found as an option, but it looks like a negative
        // number, it was meant to be positional
        // unless there are negative-number-like options
        if (this._negative_number_matcher.test(arg_string)) {
            if (!this._has_negative_number_optionals.length) {
                return undefined
            }
        }

        // if it contains a space, it was meant to be a positional
        if (arg_string.includes(' ')) {
            return undefined
        }

        // it was meant to be an optional but there is no such option
        // in this parser (though it might be a valid option in a subparser)
        return [ undefined, arg_string, undefined ]
    }

    _get_option_tuples(option_string) {
        let result = []

        // option strings starting with two prefix characters are only
        // split at the '='
        let chars = this.prefix_chars
        if (chars.includes(option_string[0]) && chars.includes(option_string[1])) {
            if (this.allow_abbrev) {
                let option_prefix, explicit_arg
                if (option_string.includes('=')) {
                    [ option_prefix, explicit_arg ] = _string_split(option_string, '=', 1)
                } else {
                    option_prefix = option_string
                    explicit_arg = undefined
                }
                for (let option_string of Object.keys(this._option_string_actions)) {
                    if (option_string.startsWith(option_prefix)) {
                        let action = this._option_string_actions[option_string]
                        let tup = [ action, option_string, explicit_arg ]
                        result.push(tup)
                    }
                }
            }

        // single character options can be concatenated with their arguments
        // but multiple character options always have to have their argument
        // separate
        } else if (chars.includes(option_string[0]) && !chars.includes(option_string[1])) {
            let option_prefix = option_string
            let explicit_arg = undefined
            let short_option_prefix = option_string.slice(0, 2)
            let short_explicit_arg = option_string.slice(2)

            for (let option_string of Object.keys(this._option_string_actions)) {
                if (option_string === short_option_prefix) {
                    let action = this._option_string_actions[option_string]
                    let tup = [ action, option_string, short_explicit_arg ]
                    result.push(tup)
                } else if (option_string.startsWith(option_prefix)) {
                    let action = this._option_string_actions[option_string]
                    let tup = [ action, option_string, explicit_arg ]
                    result.push(tup)
                }
            }

        // shouldn't ever get here
        } else {
            this.error(sub('unexpected option string: %s', option_string))
        }

        // return the collected option tuples
        return result
    }

    _get_nargs_pattern(action) {
        // in all examples below, we have to allow for '--' args
        // which are represented as '-' in the pattern
        let nargs = action.nargs
        let nargs_pattern

        // the default (None) is assumed to be a single argument
        if (nargs === undefined) {
            nargs_pattern = '(-*A-*)'

        // allow zero or one arguments
        } else if (nargs === OPTIONAL) {
            nargs_pattern = '(-*A?-*)'

        // allow zero or more arguments
        } else if (nargs === ZERO_OR_MORE) {
            nargs_pattern = '(-*[A-]*)'

        // allow one or more arguments
        } else if (nargs === ONE_OR_MORE) {
            nargs_pattern = '(-*A[A-]*)'

        // allow any number of options or arguments
        } else if (nargs === REMAINDER) {
            nargs_pattern = '([-AO]*)'

        // allow one argument followed by any number of options or arguments
        } else if (nargs === PARSER) {
            nargs_pattern = '(-*A[-AO]*)'

        // suppress action, like nargs=0
        } else if (nargs === SUPPRESS) {
            nargs_pattern = '(-*-*)'

        // all others should be integers
        } else {
            nargs_pattern = sub('(-*%s-*)', 'A'.repeat(nargs).split('').join('-*'))
        }

        // if this is an optional action, -- is not allowed
        if (action.option_strings.length) {
            nargs_pattern = nargs_pattern.replace(/-\*/g, '')
            nargs_pattern = nargs_pattern.replace(/-/g, '')
        }

        // return the pattern
        return nargs_pattern
    }

    // ========================
    // Alt command line argument parsing, allowing free intermix
    // ========================

    parse_intermixed_args(args = undefined, namespace = undefined) {
        let argv
        [ args, argv ] = this.parse_known_intermixed_args(args, namespace)
        if (argv.length) {
            let msg = 'unrecognized arguments: %s'
            this.error(sub(msg, argv.join(' ')))
        }
        return args
    }

    parse_known_intermixed_args(args = undefined, namespace = undefined) {
        // returns a namespace and list of extras
        //
        // positional can be freely intermixed with optionals.  optionals are
        // first parsed with all positional arguments deactivated.  The 'extras'
        // are then parsed.  If the parser definition is incompatible with the
        // intermixed assumptions (e.g. use of REMAINDER, subparsers) a
        // TypeError is raised.
        //
        // positionals are 'deactivated' by setting nargs and default to
        // SUPPRESS.  This blocks the addition of that positional to the
        // namespace

        let extras
        let positionals = this._get_positional_actions()
        let a = positionals.filter(action => [ PARSER, REMAINDER ].includes(action.nargs))
        if (a.length) {
            throw new TypeError(sub('parse_intermixed_args: positional arg' +
                                    ' with nargs=%s', a[0].nargs))
        }

        for (let group of this._mutually_exclusive_groups) {
            for (let action of group._group_actions) {
                if (positionals.includes(action)) {
                    throw new TypeError('parse_intermixed_args: positional in' +
                                        ' mutuallyExclusiveGroup')
                }
            }
        }

        let save_usage
        try {
            save_usage = this.usage
            let remaining_args
            try {
                if (this.usage === undefined) {
                    // capture the full usage for use in error messages
                    this.usage = this.format_usage().slice(7)
                }
                for (let action of positionals) {
                    // deactivate positionals
                    action.save_nargs = action.nargs
                    // action.nargs = 0
                    action.nargs = SUPPRESS
                    action.save_default = action.default
                    action.default = SUPPRESS
                }
                [ namespace, remaining_args ] = this.parse_known_args(args,
                                                                      namespace)
                for (let action of positionals) {
                    // remove the empty positional values from namespace
                    let attr = getattr(namespace, action.dest)
                    if (Array.isArray(attr) && attr.length === 0) {
                        // eslint-disable-next-line no-console
                        console.warn(sub('Do not expect %s in %s', action.dest, namespace))
                        delattr(namespace, action.dest)
                    }
                }
            } finally {
                // restore nargs and usage before exiting
                for (let action of positionals) {
                    action.nargs = action.save_nargs
                    action.default = action.save_default
                }
            }
            let optionals = this._get_optional_actions()
            try {
                // parse positionals.  optionals aren't normally required, but
                // they could be, so make sure they aren't.
                for (let action of optionals) {
                    action.save_required = action.required
                    action.required = false
                }
                for (let group of this._mutually_exclusive_groups) {
                    group.save_required = group.required
                    group.required = false
                }
                [ namespace, extras ] = this.parse_known_args(remaining_args,
                                                              namespace)
            } finally {
                // restore parser values before exiting
                for (let action of optionals) {
                    action.required = action.save_required
                }
                for (let group of this._mutually_exclusive_groups) {
                    group.required = group.save_required
                }
            }
        } finally {
            this.usage = save_usage
        }
        return [ namespace, extras ]
    }

    // ========================
    // Value conversion methods
    // ========================
    _get_values(action, arg_strings) {
        // for everything but PARSER, REMAINDER args, strip out first '--'
        if (![PARSER, REMAINDER].includes(action.nargs)) {
            try {
                _array_remove(arg_strings, '--')
            } catch (err) {}
        }

        let value
        // optional argument produces a default when not present
        if (!arg_strings.length && action.nargs === OPTIONAL) {
            if (action.option_strings.length) {
                value = action.const
            } else {
                value = action.default
            }
            if (typeof value === 'string') {
                value = this._get_value(action, value)
                this._check_value(action, value)
            }

        // when nargs='*' on a positional, if there were no command-line
        // args, use the default if it is anything other than None
        } else if (!arg_strings.length && action.nargs === ZERO_OR_MORE &&
              !action.option_strings.length) {
            if (action.default !== undefined) {
                value = action.default
            } else {
                value = arg_strings
            }
            this._check_value(action, value)

        // single argument or optional argument produces a single value
        } else if (arg_strings.length === 1 && [undefined, OPTIONAL].includes(action.nargs)) {
            let arg_string = arg_strings[0]
            value = this._get_value(action, arg_string)
            this._check_value(action, value)

        // REMAINDER arguments convert all values, checking none
        } else if (action.nargs === REMAINDER) {
            value = arg_strings.map(v => this._get_value(action, v))

        // PARSER arguments convert all values, but check only the first
        } else if (action.nargs === PARSER) {
            value = arg_strings.map(v => this._get_value(action, v))
            this._check_value(action, value[0])

        // SUPPRESS argument does not put anything in the namespace
        } else if (action.nargs === SUPPRESS) {
            value = SUPPRESS

        // all other types of nargs produce a list
        } else {
            value = arg_strings.map(v => this._get_value(action, v))
            for (let v of value) {
                this._check_value(action, v)
            }
        }

        // return the converted value
        return value
    }

    _get_value(action, arg_string) {
        let type_func = this._registry_get('type', action.type, action.type)
        if (typeof type_func !== 'function') {
            let msg = '%r is not callable'
            throw new ArgumentError(action, sub(msg, type_func))
        }

        // convert the value to the appropriate type
        let result
        try {
            try {
                result = type_func(arg_string)
            } catch (err) {
                // Dear TC39, why would you ever consider making es6 classes not callable?
                // We had one universal interface, [[Call]], which worked for anything
                // (with familiar this-instanceof guard for classes). Now we have two.
                if (err instanceof TypeError &&
                    /Class constructor .* cannot be invoked without 'new'/.test(err.message)) {
                    // eslint-disable-next-line new-cap
                    result = new type_func(arg_string)
                } else {
                    throw err
                }
            }

        } catch (err) {
            // ArgumentTypeErrors indicate errors
            if (err instanceof ArgumentTypeError) {
                //let name = getattr(action.type, 'name', repr(action.type))
                let msg = err.message
                throw new ArgumentError(action, msg)

            // TypeErrors or ValueErrors also indicate errors
            } else if (err instanceof TypeError) {
                let name = getattr(action.type, 'name', repr(action.type))
                let args = {type: name, value: arg_string}
                let msg = 'invalid %(type)s value: %(value)r'
                throw new ArgumentError(action, sub(msg, args))
            } else {
                throw err
            }
        }

        // return the converted value
        return result
    }

    _check_value(action, value) {
        // converted value must be one of the choices (if specified)
        if (action.choices !== undefined && !_choices_to_array(action.choices).includes(value)) {
            let args = {value,
                        choices: _choices_to_array(action.choices).map(repr).join(', ')}
            let msg = 'invalid choice: %(value)r (choose from %(choices)s)'
            throw new ArgumentError(action, sub(msg, args))
        }
    }

    // =======================
    // Help-formatting methods
    // =======================
    format_usage() {
        let formatter = this._get_formatter()
        formatter.add_usage(this.usage, this._actions,
                            this._mutually_exclusive_groups)
        return formatter.format_help()
    }

    format_help() {
        let formatter = this._get_formatter()

        // usage
        formatter.add_usage(this.usage, this._actions,
                            this._mutually_exclusive_groups)

        // description
        formatter.add_text(this.description)

        // positionals, optionals and user-defined groups
        for (let action_group of this._action_groups) {
            formatter.start_section(action_group.title)
            formatter.add_text(action_group.description)
            formatter.add_arguments(action_group._group_actions)
            formatter.end_section()
        }

        // epilog
        formatter.add_text(this.epilog)

        // determine help from format above
        return formatter.format_help()
    }

    _get_formatter() {
        // eslint-disable-next-line new-cap
        return new this.formatter_class({ prog: this.prog })
    }

    // =====================
    // Help-printing methods
    // =====================
    print_usage(file = undefined) {
        if (file === undefined) file = process.stdout
        this._print_message(this.format_usage(), file)
    }

    print_help(file = undefined) {
        if (file === undefined) file = process.stdout
        this._print_message(this.format_help(), file)
    }

    _print_message(message, file = undefined) {
        if (message) {
            if (file === undefined) file = process.stderr
            file.write(message)
        }
    }

    // ===============
    // Exiting methods
    // ===============
    exit(status = 0, message = undefined) {
        if (message) {
            this._print_message(message, process.stderr)
        }
        process.exit(status)
    }

    error(message) {
        /*
         *  error(message: string)
         *
         *  Prints a usage message incorporating the message to stderr and
         *  exits.
         *
         *  If you override this in a subclass, it should not return -- it
         *  should either exit or raise an exception.
         */

        // LEGACY (v1 compatibility), debug mode
        if (this.debug === true) throw new Error(message)
        // end
        this.print_usage(process.stderr)
        let args = {prog: this.prog, message: message}
        this.exit(2, sub('%(prog)s: error: %(message)s\n', args))
    }
}))


module.exports = {
    ArgumentParser,
    ArgumentError,
    ArgumentTypeError,
    BooleanOptionalAction,
    FileType,
    HelpFormatter,
    ArgumentDefaultsHelpFormatter,
    RawDescriptionHelpFormatter,
    RawTextHelpFormatter,
    MetavarTypeHelpFormatter,
    Namespace,
    Action,
    ONE_OR_MORE,
    OPTIONAL,
    PARSER,
    REMAINDER,
    SUPPRESS,
    ZERO_OR_MORE
}

// LEGACY (v1 compatibility), Const alias
Object.defineProperty(module.exports, 'Const', {
    get() {
        let result = {}
        Object.entries({ ONE_OR_MORE, OPTIONAL, PARSER, REMAINDER, SUPPRESS, ZERO_OR_MORE }).forEach(([ n, v ]) => {
            Object.defineProperty(result, n, {
                get() {
                    deprecate(n, sub('use argparse.%s instead of argparse.Const.%s', n, n))
                    return v
                }
            })
        })
        Object.entries({ _UNRECOGNIZED_ARGS_ATTR }).forEach(([ n, v ]) => {
            Object.defineProperty(result, n, {
                get() {
                    deprecate(n, sub('argparse.Const.%s is an internal symbol and will no longer be available', n))
                    return v
                }
            })
        })
        return result
    },
    enumerable: false
})
// end
{
  "name": "argparse",
  "description": "CLI arguments parser. Native port of python's argparse.",
  "version": "2.0.1",
  "main": "argparse.js",
  "files": [
    "argparse.js",
    "lib/"
  ],
  "license": "Python-2.0",
  "repository": "nodeca/argparse",
  "devDependencies": {
    "@babel/eslint-parser": "^7.11.0",
    "@babel/plugin-syntax-class-properties": "^7.10.4",
    "eslint": "^7.5.0",
    "mocha": "^8.0.1",
    "nyc": "^15.1.0"
  }
}// Limited implementation of python % string operator, supports only %s and %r for now
// (other formats are not used here, but may appear in custom templates)

'use strict'

const { inspect } = require('util')


module.exports = function sub(pattern, ...values) {
    let regex = /%(?:(%)|(-)?(\*)?(?:\((\w+)\))?([A-Za-z]))/g

    let result = pattern.replace(regex, function (_, is_literal, is_left_align, is_padded, name, format) {
        if (is_literal) return '%'

        let padded_count = 0
        if (is_padded) {
            if (values.length === 0) throw new TypeError('not enough arguments for format string')
            padded_count = values.shift()
            if (!Number.isInteger(padded_count)) throw new TypeError('* wants int')
        }

        let str
        if (name !== undefined) {
            let dict = values[0]
            if (typeof dict !== 'object' || dict === null) throw new TypeError('format requires a mapping')
            if (!(name in dict)) throw new TypeError(`no such key: '${name}'`)
            str = dict[name]
        } else {
            if (values.length === 0) throw new TypeError('not enough arguments for format string')
            str = values.shift()
        }

        switch (format) {
            case 's':
                str = String(str)
                break
            case 'r':
                str = inspect(str)
                break
            case 'd':
            case 'i':
                if (typeof str !== 'number') {
                    throw new TypeError(`%${format} format: a number is required, not ${typeof str}`)
                }
                str = String(str.toFixed(0))
                break
            default:
                throw new TypeError(`unsupported format character '${format}'`)
        }

        if (padded_count > 0) {
            return is_left_align ? str.padEnd(padded_count) : str.padStart(padded_count)
        } else {
            return str
        }
    })

    if (values.length) {
        if (values.length === 1 && typeof values[0] === 'object' && values[0] !== null) {
            // mapping
        } else {
            throw new TypeError('not all arguments converted during string formatting')
        }
    }

    return result
}
// Partial port of python's argparse module, version 3.9.0 (only wrap and fill functions):
// https://github.com/python/cpython/blob/v3.9.0b4/Lib/textwrap.py

'use strict'

/*
 * Text wrapping and filling.
 */

// Copyright (C) 1999-2001 Gregory P. Ward.
// Copyright (C) 2002, 2003 Python Software Foundation.
// Copyright (C) 2020 argparse.js authors
// Originally written by Greg Ward <gward@python.net>

// Hardcode the recognized whitespace characters to the US-ASCII
// whitespace characters.  The main reason for doing this is that
// some Unicode spaces (like \u00a0) are non-breaking whitespaces.
//
// This less funky little regex just split on recognized spaces. E.g.
//   "Hello there -- you goof-ball, use the -b option!"
// splits into
//   Hello/ /there/ /--/ /you/ /goof-ball,/ /use/ /the/ /-b/ /option!/
const wordsep_simple_re = /([\t\n\x0b\x0c\r ]+)/

class TextWrapper {
    /*
     *  Object for wrapping/filling text.  The public interface consists of
     *  the wrap() and fill() methods; the other methods are just there for
     *  subclasses to override in order to tweak the default behaviour.
     *  If you want to completely replace the main wrapping algorithm,
     *  you'll probably have to override _wrap_chunks().
     *
     *  Several instance attributes control various aspects of wrapping:
     *    width (default: 70)
     *      the maximum width of wrapped lines (unless break_long_words
     *      is false)
     *    initial_indent (default: "")
     *      string that will be prepended to the first line of wrapped
     *      output.  Counts towards the line's width.
     *    subsequent_indent (default: "")
     *      string that will be prepended to all lines save the first
     *      of wrapped output; also counts towards each line's width.
     *    expand_tabs (default: true)
     *      Expand tabs in input text to spaces before further processing.
     *      Each tab will become 0 .. 'tabsize' spaces, depending on its position
     *      in its line.  If false, each tab is treated as a single character.
     *    tabsize (default: 8)
     *      Expand tabs in input text to 0 .. 'tabsize' spaces, unless
     *      'expand_tabs' is false.
     *    replace_whitespace (default: true)
     *      Replace all whitespace characters in the input text by spaces
     *      after tab expansion.  Note that if expand_tabs is false and
     *      replace_whitespace is true, every tab will be converted to a
     *      single space!
     *    fix_sentence_endings (default: false)
     *      Ensure that sentence-ending punctuation is always followed
     *      by two spaces.  Off by default because the algorithm is
     *      (unavoidably) imperfect.
     *    break_long_words (default: true)
     *      Break words longer than 'width'.  If false, those words will not
     *      be broken, and some lines might be longer than 'width'.
     *    break_on_hyphens (default: true)
     *      Allow breaking hyphenated words. If true, wrapping will occur
     *      preferably on whitespaces and right after hyphens part of
     *      compound words.
     *    drop_whitespace (default: true)
     *      Drop leading and trailing whitespace from lines.
     *    max_lines (default: None)
     *      Truncate wrapped lines.
     *    placeholder (default: ' [...]')
     *      Append to the last line of truncated text.
     */

    constructor(options = {}) {
        let {
            width = 70,
            initial_indent = '',
            subsequent_indent = '',
            expand_tabs = true,
            replace_whitespace = true,
            fix_sentence_endings = false,
            break_long_words = true,
            drop_whitespace = true,
            break_on_hyphens = true,
            tabsize = 8,
            max_lines = undefined,
            placeholder=' [...]'
        } = options

        this.width = width
        this.initial_indent = initial_indent
        this.subsequent_indent = subsequent_indent
        this.expand_tabs = expand_tabs
        this.replace_whitespace = replace_whitespace
        this.fix_sentence_endings = fix_sentence_endings
        this.break_long_words = break_long_words
        this.drop_whitespace = drop_whitespace
        this.break_on_hyphens = break_on_hyphens
        this.tabsize = tabsize
        this.max_lines = max_lines
        this.placeholder = placeholder
    }


    // -- Private methods -----------------------------------------------
    // (possibly useful for subclasses to override)

    _munge_whitespace(text) {
        /*
         *  _munge_whitespace(text : string) -> string
         *
         *  Munge whitespace in text: expand tabs and convert all other
         *  whitespace characters to spaces.  Eg. " foo\\tbar\\n\\nbaz"
         *  becomes " foo    bar  baz".
         */
        if (this.expand_tabs) {
            text = text.replace(/\t/g, ' '.repeat(this.tabsize)) // not strictly correct in js
        }
        if (this.replace_whitespace) {
            text = text.replace(/[\t\n\x0b\x0c\r]/g, ' ')
        }
        return text
    }

    _split(text) {
        /*
         *  _split(text : string) -> [string]
         *
         *  Split the text to wrap into indivisible chunks.  Chunks are
         *  not quite the same as words; see _wrap_chunks() for full
         *  details.  As an example, the text
         *    Look, goof-ball -- use the -b option!
         *  breaks into the following chunks:
         *    'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ',
         *    'use', ' ', 'the', ' ', '-b', ' ', 'option!'
         *  if break_on_hyphens is True, or in:
         *    'Look,', ' ', 'goof-ball', ' ', '--', ' ',
         *    'use', ' ', 'the', ' ', '-b', ' ', option!'
         *  otherwise.
         */
        let chunks = text.split(wordsep_simple_re)
        chunks = chunks.filter(Boolean)
        return chunks
    }

    _handle_long_word(reversed_chunks, cur_line, cur_len, width) {
        /*
         *  _handle_long_word(chunks : [string],
         *                    cur_line : [string],
         *                    cur_len : int, width : int)
         *
         *  Handle a chunk of text (most likely a word, not whitespace) that
         *  is too long to fit in any line.
         */
        // Figure out when indent is larger than the specified width, and make
        // sure at least one character is stripped off on every pass
        let space_left
        if (width < 1) {
            space_left = 1
        } else {
            space_left = width - cur_len
        }

        // If we're allowed to break long words, then do so: put as much
        // of the next chunk onto the current line as will fit.
        if (this.break_long_words) {
            cur_line.push(reversed_chunks[reversed_chunks.length - 1].slice(0, space_left))
            reversed_chunks[reversed_chunks.length - 1] = reversed_chunks[reversed_chunks.length - 1].slice(space_left)

        // Otherwise, we have to preserve the long word intact.  Only add
        // it to the current line if there's nothing already there --
        // that minimizes how much we violate the width constraint.
        } else if (!cur_line) {
            cur_line.push(...reversed_chunks.pop())
        }

        // If we're not allowed to break long words, and there's already
        // text on the current line, do nothing.  Next time through the
        // main loop of _wrap_chunks(), we'll wind up here again, but
        // cur_len will be zero, so the next line will be entirely
        // devoted to the long word that we can't handle right now.
    }

    _wrap_chunks(chunks) {
        /*
         *  _wrap_chunks(chunks : [string]) -> [string]
         *
         *  Wrap a sequence of text chunks and return a list of lines of
         *  length 'self.width' or less.  (If 'break_long_words' is false,
         *  some lines may be longer than this.)  Chunks correspond roughly
         *  to words and the whitespace between them: each chunk is
         *  indivisible (modulo 'break_long_words'), but a line break can
         *  come between any two chunks.  Chunks should not have internal
         *  whitespace; ie. a chunk is either all whitespace or a "word".
         *  Whitespace chunks will be removed from the beginning and end of
         *  lines, but apart from that whitespace is preserved.
         */
        let lines = []
        let indent
        if (this.width <= 0) {
            throw Error(`invalid width ${this.width} (must be > 0)`)
        }
        if (this.max_lines !== undefined) {
            if (this.max_lines > 1) {
                indent = this.subsequent_indent
            } else {
                indent = this.initial_indent
            }
            if (indent.length + this.placeholder.trimStart().length > this.width) {
                throw Error('placeholder too large for max width')
            }
        }

        // Arrange in reverse order so items can be efficiently popped
        // from a stack of chucks.
        chunks = chunks.reverse()

        while (chunks.length > 0) {

            // Start the list of chunks that will make up the current line.
            // cur_len is just the length of all the chunks in cur_line.
            let cur_line = []
            let cur_len = 0

            // Figure out which static string will prefix this line.
            let indent
            if (lines) {
                indent = this.subsequent_indent
            } else {
                indent = this.initial_indent
            }

            // Maximum width for this line.
            let width = this.width - indent.length

            // First chunk on line is whitespace -- drop it, unless this
            // is the very beginning of the text (ie. no lines started yet).
            if (this.drop_whitespace && chunks[chunks.length - 1].trim() === '' && lines.length > 0) {
                chunks.pop()
            }

            while (chunks.length > 0) {
                let l = chunks[chunks.length - 1].length

                // Can at least squeeze this chunk onto the current line.
                if (cur_len + l <= width) {
                    cur_line.push(chunks.pop())
                    cur_len += l

                // Nope, this line is full.
                } else {
                    break
                }
            }

            // The current line is full, and the next chunk is too big to
            // fit on *any* line (not just this one).
            if (chunks.length && chunks[chunks.length - 1].length > width) {
                this._handle_long_word(chunks, cur_line, cur_len, width)
                cur_len = cur_line.map(l => l.length).reduce((a, b) => a + b, 0)
            }

            // If the last chunk on this line is all whitespace, drop it.
            if (this.drop_whitespace && cur_line.length > 0 && cur_line[cur_line.length - 1].trim() === '') {
                cur_len -= cur_line[cur_line.length - 1].length
                cur_line.pop()
            }

            if (cur_line) {
                if (this.max_lines === undefined ||
                    lines.length + 1 < this.max_lines ||
                    (chunks.length === 0 ||
                     this.drop_whitespace &&
                     chunks.length === 1 &&
                     !chunks[0].trim()) && cur_len <= width) {
                    // Convert current line back to a string and store it in
                    // list of all lines (return value).
                    lines.push(indent + cur_line.join(''))
                } else {
                    let had_break = false
                    while (cur_line) {
                        if (cur_line[cur_line.length - 1].trim() &&
                            cur_len + this.placeholder.length <= width) {
                            cur_line.push(this.placeholder)
                            lines.push(indent + cur_line.join(''))
                            had_break = true
                            break
                        }
                        cur_len -= cur_line[-1].length
                        cur_line.pop()
                    }
                    if (!had_break) {
                        if (lines) {
                            let prev_line = lines[lines.length - 1].trimEnd()
                            if (prev_line.length + this.placeholder.length <=
                                    this.width) {
                                lines[lines.length - 1] = prev_line + this.placeholder
                                break
                            }
                        }
                        lines.push(indent + this.placeholder.lstrip())
                    }
                    break
                }
            }
        }

        return lines
    }

    _split_chunks(text) {
        text = this._munge_whitespace(text)
        return this._split(text)
    }

    // -- Public interface ----------------------------------------------

    wrap(text) {
        /*
         *  wrap(text : string) -> [string]
         *
         *  Reformat the single paragraph in 'text' so it fits in lines of
         *  no more than 'self.width' columns, and return a list of wrapped
         *  lines.  Tabs in 'text' are expanded with string.expandtabs(),
         *  and all other whitespace characters (including newline) are
         *  converted to space.
         */
        let chunks = this._split_chunks(text)
        // not implemented in js
        //if (this.fix_sentence_endings) {
        //    this._fix_sentence_endings(chunks)
        //}
        return this._wrap_chunks(chunks)
    }

    fill(text) {
        /*
         *  fill(text : string) -> string
         *
         *  Reformat the single paragraph in 'text' to fit in lines of no
         *  more than 'self.width' columns, and return a new string
         *  containing the entire wrapped paragraph.
         */
        return this.wrap(text).join('\n')
    }
}


// -- Convenience interface ---------------------------------------------

function wrap(text, options = {}) {
    /*
     *  Wrap a single paragraph of text, returning a list of wrapped lines.
     *
     *  Reformat the single paragraph in 'text' so it fits in lines of no
     *  more than 'width' columns, and return a list of wrapped lines.  By
     *  default, tabs in 'text' are expanded with string.expandtabs(), and
     *  all other whitespace characters (including newline) are converted to
     *  space.  See TextWrapper class for available keyword args to customize
     *  wrapping behaviour.
     */
    let { width = 70, ...kwargs } = options
    let w = new TextWrapper(Object.assign({ width }, kwargs))
    return w.wrap(text)
}

function fill(text, options = {}) {
    /*
     *  Fill a single paragraph of text, returning a new string.
     *
     *  Reformat the single paragraph in 'text' to fit in lines of no more
     *  than 'width' columns, and return a new string containing the entire
     *  wrapped paragraph.  As with wrap(), tabs are expanded and other
     *  whitespace characters converted to space.  See TextWrapper class for
     *  available keyword args to customize wrapping behaviour.
     */
    let { width = 70, ...kwargs } = options
    let w = new TextWrapper(Object.assign({ width }, kwargs))
    return w.fill(text)
}

// -- Loosely related functionality -------------------------------------

let _whitespace_only_re = /^[ \t]+$/mg
let _leading_whitespace_re = /(^[ \t]*)(?:[^ \t\n])/mg

function dedent(text) {
    /*
     *  Remove any common leading whitespace from every line in `text`.
     *
     *  This can be used to make triple-quoted strings line up with the left
     *  edge of the display, while still presenting them in the source code
     *  in indented form.
     *
     *  Note that tabs and spaces are both treated as whitespace, but they
     *  are not equal: the lines "  hello" and "\\thello" are
     *  considered to have no common leading whitespace.
     *
     *  Entirely blank lines are normalized to a newline character.
     */
    // Look for the longest leading string of spaces and tabs common to
    // all lines.
    let margin = undefined
    text = text.replace(_whitespace_only_re, '')
    let indents = text.match(_leading_whitespace_re) || []
    for (let indent of indents) {
        indent = indent.slice(0, -1)

        if (margin === undefined) {
            margin = indent

        // Current line more deeply indented than previous winner:
        // no change (previous winner is still on top).
        } else if (indent.startsWith(margin)) {
            // pass

        // Current line consistent with and no deeper than previous winner:
        // it's the new winner.
        } else if (margin.startsWith(indent)) {
            margin = indent

        // Find the largest common whitespace between current line and previous
        // winner.
        } else {
            for (let i = 0; i < margin.length && i < indent.length; i++) {
                if (margin[i] !== indent[i]) {
                    margin = margin.slice(0, i)
                    break
                }
            }
        }
    }

    if (margin) {
        text = text.replace(new RegExp('^' + margin, 'mg'), '')
    }
    return text
}

module.exports = { wrap, fill, dedent }
(The MIT License)

Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
Copyright (c) 2018-2021 Josh Junon

Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the 'Software'), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

{
  "name": "debug",
  "version": "4.4.3",
  "repository": {
    "type": "git",
    "url": "git://github.com/debug-js/debug.git"
  },
  "description": "Lightweight debugging utility for Node.js and the browser",
  "files": [
    "src",
    "LICENSE",
    "README.md"
  ],
  "author": "Josh Junon (https://github.com/qix-)",
  "license": "MIT",
  "dependencies": {
    "ms": "^2.1.3"
  },
  "devDependencies": {
    "brfs": "^2.0.1",
    "browserify": "^16.2.3",
    "coveralls": "^3.0.2",
    "karma": "^3.1.4",
    "karma-browserify": "^6.0.0",
    "karma-chrome-launcher": "^2.2.0",
    "karma-mocha": "^1.3.0",
    "mocha": "^5.2.0",
    "mocha-lcov-reporter": "^1.2.0",
    "sinon": "^14.0.0",
    "xo": "^0.23.0"
  },
  "peerDependenciesMeta": {
    "supports-color": {
      "optional": true
    }
  },
  "main": "./src/index.js",
  "browser": "./src/browser.js",
  "engines": {
    "node": ">=6.0"
  }
}/* eslint-env browser */

/**
 * This is the web browser implementation of `debug()`.
 */

exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = localstorage();
exports.destroy = (() => {
	let warned = false;

	return () => {
		if (!warned) {
			warned = true;
			console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
		}
	};
})();

/**
 * Colors.
 */

exports.colors = [
	'#0000CC',
	'#0000FF',
	'#0033CC',
	'#0033FF',
	'#0066CC',
	'#0066FF',
	'#0099CC',
	'#0099FF',
	'#00CC00',
	'#00CC33',
	'#00CC66',
	'#00CC99',
	'#00CCCC',
	'#00CCFF',
	'#3300CC',
	'#3300FF',
	'#3333CC',
	'#3333FF',
	'#3366CC',
	'#3366FF',
	'#3399CC',
	'#3399FF',
	'#33CC00',
	'#33CC33',
	'#33CC66',
	'#33CC99',
	'#33CCCC',
	'#33CCFF',
	'#6600CC',
	'#6600FF',
	'#6633CC',
	'#6633FF',
	'#66CC00',
	'#66CC33',
	'#9900CC',
	'#9900FF',
	'#9933CC',
	'#9933FF',
	'#99CC00',
	'#99CC33',
	'#CC0000',
	'#CC0033',
	'#CC0066',
	'#CC0099',
	'#CC00CC',
	'#CC00FF',
	'#CC3300',
	'#CC3333',
	'#CC3366',
	'#CC3399',
	'#CC33CC',
	'#CC33FF',
	'#CC6600',
	'#CC6633',
	'#CC9900',
	'#CC9933',
	'#CCCC00',
	'#CCCC33',
	'#FF0000',
	'#FF0033',
	'#FF0066',
	'#FF0099',
	'#FF00CC',
	'#FF00FF',
	'#FF3300',
	'#FF3333',
	'#FF3366',
	'#FF3399',
	'#FF33CC',
	'#FF33FF',
	'#FF6600',
	'#FF6633',
	'#FF9900',
	'#FF9933',
	'#FFCC00',
	'#FFCC33'
];

/**
 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
 * and the Firebug extension (any Firefox version) are known
 * to support "%c" CSS customizations.
 *
 * TODO: add a `localStorage` variable to explicitly enable/disable colors
 */

// eslint-disable-next-line complexity
function useColors() {
	// NB: In an Electron preload script, document will be defined but not fully
	// initialized. Since we know we're in Chrome, we'll just detect this case
	// explicitly
	if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
		return true;
	}

	// Internet Explorer and Edge do not support colors.
	if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
		return false;
	}

	let m;

	// Is webkit? http://stackoverflow.com/a/16459606/376773
	// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
	// eslint-disable-next-line no-return-assign
	return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
		// Is firebug? http://stackoverflow.com/a/398120/376773
		(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
		// Is firefox >= v31?
		// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
		(typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31) ||
		// Double check webkit in userAgent just in case we are in a worker
		(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
}

/**
 * Colorize log arguments if enabled.
 *
 * @api public
 */

function formatArgs(args) {
	args[0] = (this.useColors ? '%c' : '') +
		this.namespace +
		(this.useColors ? ' %c' : ' ') +
		args[0] +
		(this.useColors ? '%c ' : ' ') +
		'+' + module.exports.humanize(this.diff);

	if (!this.useColors) {
		return;
	}

	const c = 'color: ' + this.color;
	args.splice(1, 0, c, 'color: inherit');

	// The final "%c" is somewhat tricky, because there could be other
	// arguments passed either before or after the %c, so we need to
	// figure out the correct index to insert the CSS into
	let index = 0;
	let lastC = 0;
	args[0].replace(/%[a-zA-Z%]/g, match => {
		if (match === '%%') {
			return;
		}
		index++;
		if (match === '%c') {
			// We only are interested in the *last* %c
			// (the user may have provided their own)
			lastC = index;
		}
	});

	args.splice(lastC, 0, c);
}

/**
 * Invokes `console.debug()` when available.
 * No-op when `console.debug` is not a "function".
 * If `console.debug` is not available, falls back
 * to `console.log`.
 *
 * @api public
 */
exports.log = console.debug || console.log || (() => {});

/**
 * Save `namespaces`.
 *
 * @param {String} namespaces
 * @api private
 */
function save(namespaces) {
	try {
		if (namespaces) {
			exports.storage.setItem('debug', namespaces);
		} else {
			exports.storage.removeItem('debug');
		}
	} catch (error) {
		// Swallow
		// XXX (@Qix-) should we be logging these?
	}
}

/**
 * Load `namespaces`.
 *
 * @return {String} returns the previously persisted debug modes
 * @api private
 */
function load() {
	let r;
	try {
		r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ;
	} catch (error) {
		// Swallow
		// XXX (@Qix-) should we be logging these?
	}

	// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
	if (!r && typeof process !== 'undefined' && 'env' in process) {
		r = process.env.DEBUG;
	}

	return r;
}

/**
 * Localstorage attempts to return the localstorage.
 *
 * This is necessary because safari throws
 * when a user disables cookies/localstorage
 * and you attempt to access it.
 *
 * @return {LocalStorage}
 * @api private
 */

function localstorage() {
	try {
		// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
		// The Browser also has localStorage in the global context.
		return localStorage;
	} catch (error) {
		// Swallow
		// XXX (@Qix-) should we be logging these?
	}
}

module.exports = require('./common')(exports);

const {formatters} = module.exports;

/**
 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
 */

formatters.j = function (v) {
	try {
		return JSON.stringify(v);
	} catch (error) {
		return '[UnexpectedJSONParseError]: ' + error.message;
	}
};

/**
 * This is the common logic for both the Node.js and web browser
 * implementations of `debug()`.
 */

function setup(env) {
	createDebug.debug = createDebug;
	createDebug.default = createDebug;
	createDebug.coerce = coerce;
	createDebug.disable = disable;
	createDebug.enable = enable;
	createDebug.enabled = enabled;
	createDebug.humanize = require('ms');
	createDebug.destroy = destroy;

	Object.keys(env).forEach(key => {
		createDebug[key] = env[key];
	});

	/**
	* The currently active debug mode names, and names to skip.
	*/

	createDebug.names = [];
	createDebug.skips = [];

	/**
	* Map of special "%n" handling functions, for the debug "format" argument.
	*
	* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
	*/
	createDebug.formatters = {};

	/**
	* Selects a color for a debug namespace
	* @param {String} namespace The namespace string for the debug instance to be colored
	* @return {Number|String} An ANSI color code for the given namespace
	* @api private
	*/
	function selectColor(namespace) {
		let hash = 0;

		for (let i = 0; i < namespace.length; i++) {
			hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
			hash |= 0; // Convert to 32bit integer
		}

		return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
	}
	createDebug.selectColor = selectColor;

	/**
	* Create a debugger with the given `namespace`.
	*
	* @param {String} namespace
	* @return {Function}
	* @api public
	*/
	function createDebug(namespace) {
		let prevTime;
		let enableOverride = null;
		let namespacesCache;
		let enabledCache;

		function debug(...args) {
			// Disabled?
			if (!debug.enabled) {
				return;
			}

			const self = debug;

			// Set `diff` timestamp
			const curr = Number(new Date());
			const ms = curr - (prevTime || curr);
			self.diff = ms;
			self.prev = prevTime;
			self.curr = curr;
			prevTime = curr;

			args[0] = createDebug.coerce(args[0]);

			if (typeof args[0] !== 'string') {
				// Anything else let's inspect with %O
				args.unshift('%O');
			}

			// Apply any `formatters` transformations
			let index = 0;
			args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
				// If we encounter an escaped % then don't increase the array index
				if (match === '%%') {
					return '%';
				}
				index++;
				const formatter = createDebug.formatters[format];
				if (typeof formatter === 'function') {
					const val = args[index];
					match = formatter.call(self, val);

					// Now we need to remove `args[index]` since it's inlined in the `format`
					args.splice(index, 1);
					index--;
				}
				return match;
			});

			// Apply env-specific formatting (colors, etc.)
			createDebug.formatArgs.call(self, args);

			const logFn = self.log || createDebug.log;
			logFn.apply(self, args);
		}

		debug.namespace = namespace;
		debug.useColors = createDebug.useColors();
		debug.color = createDebug.selectColor(namespace);
		debug.extend = extend;
		debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.

		Object.defineProperty(debug, 'enabled', {
			enumerable: true,
			configurable: false,
			get: () => {
				if (enableOverride !== null) {
					return enableOverride;
				}
				if (namespacesCache !== createDebug.namespaces) {
					namespacesCache = createDebug.namespaces;
					enabledCache = createDebug.enabled(namespace);
				}

				return enabledCache;
			},
			set: v => {
				enableOverride = v;
			}
		});

		// Env-specific initialization logic for debug instances
		if (typeof createDebug.init === 'function') {
			createDebug.init(debug);
		}

		return debug;
	}

	function extend(namespace, delimiter) {
		const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
		newDebug.log = this.log;
		return newDebug;
	}

	/**
	* Enables a debug mode by namespaces. This can include modes
	* separated by a colon and wildcards.
	*
	* @param {String} namespaces
	* @api public
	*/
	function enable(namespaces) {
		createDebug.save(namespaces);
		createDebug.namespaces = namespaces;

		createDebug.names = [];
		createDebug.skips = [];

		const split = (typeof namespaces === 'string' ? namespaces : '')
			.trim()
			.replace(/\s+/g, ',')
			.split(',')
			.filter(Boolean);

		for (const ns of split) {
			if (ns[0] === '-') {
				createDebug.skips.push(ns.slice(1));
			} else {
				createDebug.names.push(ns);
			}
		}
	}

	/**
	 * Checks if the given string matches a namespace template, honoring
	 * asterisks as wildcards.
	 *
	 * @param {String} search
	 * @param {String} template
	 * @return {Boolean}
	 */
	function matchesTemplate(search, template) {
		let searchIndex = 0;
		let templateIndex = 0;
		let starIndex = -1;
		let matchIndex = 0;

		while (searchIndex < search.length) {
			if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {
				// Match character or proceed with wildcard
				if (template[templateIndex] === '*') {
					starIndex = templateIndex;
					matchIndex = searchIndex;
					templateIndex++; // Skip the '*'
				} else {
					searchIndex++;
					templateIndex++;
				}
			} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition
				// Backtrack to the last '*' and try to match more characters
				templateIndex = starIndex + 1;
				matchIndex++;
				searchIndex = matchIndex;
			} else {
				return false; // No match
			}
		}

		// Handle trailing '*' in template
		while (templateIndex < template.length && template[templateIndex] === '*') {
			templateIndex++;
		}

		return templateIndex === template.length;
	}

	/**
	* Disable debug output.
	*
	* @return {String} namespaces
	* @api public
	*/
	function disable() {
		const namespaces = [
			...createDebug.names,
			...createDebug.skips.map(namespace => '-' + namespace)
		].join(',');
		createDebug.enable('');
		return namespaces;
	}

	/**
	* Returns true if the given mode name is enabled, false otherwise.
	*
	* @param {String} name
	* @return {Boolean}
	* @api public
	*/
	function enabled(name) {
		for (const skip of createDebug.skips) {
			if (matchesTemplate(name, skip)) {
				return false;
			}
		}

		for (const ns of createDebug.names) {
			if (matchesTemplate(name, ns)) {
				return true;
			}
		}

		return false;
	}

	/**
	* Coerce `val`.
	*
	* @param {Mixed} val
	* @return {Mixed}
	* @api private
	*/
	function coerce(val) {
		if (val instanceof Error) {
			return val.stack || val.message;
		}
		return val;
	}

	/**
	* XXX DO NOT USE. This is a temporary stub function.
	* XXX It WILL be removed in the next major release.
	*/
	function destroy() {
		console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
	}

	createDebug.enable(createDebug.load());

	return createDebug;
}

module.exports = setup;
/**
 * Detect Electron renderer / nwjs process, which is node, but we should
 * treat as a browser.
 */

if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
	module.exports = require('./browser.js');
} else {
	module.exports = require('./node.js');
}
/**
 * Module dependencies.
 */

const tty = require('tty');
const util = require('util');

/**
 * This is the Node.js implementation of `debug()`.
 */

exports.init = init;
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.destroy = util.deprecate(
	() => {},
	'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'
);

/**
 * Colors.
 */

exports.colors = [6, 2, 3, 4, 5, 1];

try {
	// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
	// eslint-disable-next-line import/no-extraneous-dependencies
	const supportsColor = require('supports-color');

	if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
		exports.colors = [
			20,
			21,
			26,
			27,
			32,
			33,
			38,
			39,
			40,
			41,
			42,
			43,
			44,
			45,
			56,
			57,
			62,
			63,
			68,
			69,
			74,
			75,
			76,
			77,
			78,
			79,
			80,
			81,
			92,
			93,
			98,
			99,
			112,
			113,
			128,
			129,
			134,
			135,
			148,
			149,
			160,
			161,
			162,
			163,
			164,
			165,
			166,
			167,
			168,
			169,
			170,
			171,
			172,
			173,
			178,
			179,
			184,
			185,
			196,
			197,
			198,
			199,
			200,
			201,
			202,
			203,
			204,
			205,
			206,
			207,
			208,
			209,
			214,
			215,
			220,
			221
		];
	}
} catch (error) {
	// Swallow - we only care if `supports-color` is available; it doesn't have to be.
}

/**
 * Build up the default `inspectOpts` object from the environment variables.
 *
 *   $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
 */

exports.inspectOpts = Object.keys(process.env).filter(key => {
	return /^debug_/i.test(key);
}).reduce((obj, key) => {
	// Camel-case
	const prop = key
		.substring(6)
		.toLowerCase()
		.replace(/_([a-z])/g, (_, k) => {
			return k.toUpperCase();
		});

	// Coerce string value into JS value
	let val = process.env[key];
	if (/^(yes|on|true|enabled)$/i.test(val)) {
		val = true;
	} else if (/^(no|off|false|disabled)$/i.test(val)) {
		val = false;
	} else if (val === 'null') {
		val = null;
	} else {
		val = Number(val);
	}

	obj[prop] = val;
	return obj;
}, {});

/**
 * Is stdout a TTY? Colored output is enabled when `true`.
 */

function useColors() {
	return 'colors' in exports.inspectOpts ?
		Boolean(exports.inspectOpts.colors) :
		tty.isatty(process.stderr.fd);
}

/**
 * Adds ANSI color escape codes if enabled.
 *
 * @api public
 */

function formatArgs(args) {
	const {namespace: name, useColors} = this;

	if (useColors) {
		const c = this.color;
		const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
		const prefix = `  ${colorCode};1m${name} \u001B[0m`;

		args[0] = prefix + args[0].split('\n').join('\n' + prefix);
		args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
	} else {
		args[0] = getDate() + name + ' ' + args[0];
	}
}

function getDate() {
	if (exports.inspectOpts.hideDate) {
		return '';
	}
	return new Date().toISOString() + ' ';
}

/**
 * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr.
 */

function log(...args) {
	return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\n');
}

/**
 * Save `namespaces`.
 *
 * @param {String} namespaces
 * @api private
 */
function save(namespaces) {
	if (namespaces) {
		process.env.DEBUG = namespaces;
	} else {
		// If you set a process.env field to null or undefined, it gets cast to the
		// string 'null' or 'undefined'. Just delete instead.
		delete process.env.DEBUG;
	}
}

/**
 * Load `namespaces`.
 *
 * @return {String} returns the previously persisted debug modes
 * @api private
 */

function load() {
	return process.env.DEBUG;
}

/**
 * Init logic for `debug` instances.
 *
 * Create a new `inspectOpts` object in case `useColors` is set
 * differently for a particular `debug` instance.
 */

function init(debug) {
	debug.inspectOpts = {};

	const keys = Object.keys(exports.inspectOpts);
	for (let i = 0; i < keys.length; i++) {
		debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
	}
}

module.exports = require('./common')(exports);

const {formatters} = module.exports;

/**
 * Map %o to `util.inspect()`, all on a single line.
 */

formatters.o = function (v) {
	this.inspectOpts.colors = this.useColors;
	return util.inspect(v, this.inspectOpts)
		.split('\n')
		.map(str => str.trim())
		.join(' ');
};

/**
 * Map %O to `util.inspect()`, allowing multiple lines if needed.
 */

formatters.O = function (v) {
	this.inspectOpts.colors = this.useColors;
	return util.inspect(v, this.inspectOpts);
};
The MIT License (MIT)

Copyright (c) 2015 Loopline Systems

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

{
  "name": "electron-updater",
  "version": "6.8.9",
  "description": "Cross platform updater for electron applications",
  "main": "out/main.js",
  "author": "Vladimir Krivosheev",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/electron-userland/electron-builder.git",
    "directory": "packages/electron-updater"
  },
  "homepage": "https://github.com/electron-userland/electron-builder",
  "files": [
    "out"
  ],
  "dependencies": {
    "fs-extra": "^10.1.0",
    "js-yaml": "^4.1.0",
    "lazy-val": "^1.0.5",
    "lodash.escaperegexp": "^4.1.2",
    "lodash.isequal": "^4.5.0",
    "semver": "~7.7.3",
    "tiny-typed-emitter": "^2.1.0",
    "builder-util-runtime": "9.7.0"
  },
  "devDependencies": {
    "@types/fs-extra": "9.0.13",
    "@types/js-yaml": "4.0.3",
    "@types/lodash.escaperegexp": "4.1.6",
    "@types/lodash.isequal": "4.5.5",
    "@types/semver": "7.7.1",
    "electron": "39.8.5"
  },
  "typings": "./out/main.d.ts",
  "publishConfig": {
    "tag": "next"
  }
}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAppCacheDir = getAppCacheDir;
const path = require("path");
const os_1 = require("os");
function getAppCacheDir() {
    const homedir = (0, os_1.homedir)();
    // https://github.com/electron/electron/issues/1404#issuecomment-194391247
    let result;
    if (process.platform === "win32") {
        result = process.env["LOCALAPPDATA"] || path.join(homedir, "AppData", "Local");
    }
    else if (process.platform === "darwin") {
        result = path.join(homedir, "Library", "Caches");
    }
    else {
        result = process.env["XDG_CACHE_HOME"] || path.join(homedir, ".cache");
    }
    return result;
}
//# sourceMappingURL=AppAdapter.js.map{"version":3,"file":"AppAdapter.js","sourceRoot":"","sources":["../src/AppAdapter.ts"],"names":[],"mappings":";;AAiCA,wCAYC;AA7CD,6BAA4B;AAC5B,2BAA0C;AAgC1C,SAAgB,cAAc;IAC5B,MAAM,OAAO,GAAG,IAAA,YAAU,GAAE,CAAA;IAC5B,0EAA0E;IAC1E,IAAI,MAAc,CAAA;IAClB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;IAChF,CAAC;SAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACzC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;IAClD,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IACxE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import * as path from \"path\"\nimport { homedir as getHomedir } from \"os\"\n\nexport interface AppAdapter {\n  readonly version: string\n  readonly name: string\n\n  readonly isPackaged: boolean\n\n  /**\n   * Path to update metadata file.\n   */\n  readonly appUpdateConfigPath: string\n\n  /**\n   * Path to user data directory.\n   */\n  readonly userDataPath: string\n\n  /**\n   * Path to cache directory.\n   */\n  readonly baseCachePath: string\n\n  whenReady(): Promise<void>\n\n  relaunch(): void\n\n  quit(): void\n\n  onQuit(handler: (exitCode: number) => void): void\n}\n\nexport function getAppCacheDir() {\n  const homedir = getHomedir()\n  // https://github.com/electron/electron/issues/1404#issuecomment-194391247\n  let result: string\n  if (process.platform === \"win32\") {\n    result = process.env[\"LOCALAPPDATA\"] || path.join(homedir, \"AppData\", \"Local\")\n  } else if (process.platform === \"darwin\") {\n    result = path.join(homedir, \"Library\", \"Caches\")\n  } else {\n    result = process.env[\"XDG_CACHE_HOME\"] || path.join(homedir, \".cache\")\n  }\n  return result\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppImageUpdater = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const child_process_1 = require("child_process");
const fs_extra_1 = require("fs-extra");
const fs_1 = require("fs");
const path = require("path");
const BaseUpdater_1 = require("./BaseUpdater");
const FileWithEmbeddedBlockMapDifferentialDownloader_1 = require("./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader");
const Provider_1 = require("./providers/Provider");
const types_1 = require("./types");
class AppImageUpdater extends BaseUpdater_1.BaseUpdater {
    constructor(options, app) {
        super(options, app);
    }
    isUpdaterActive() {
        if (process.env["APPIMAGE"] == null && !this.forceDevUpdateConfig) {
            if (process.env["SNAP"] == null) {
                this._logger.warn("APPIMAGE env is not defined, current application is not an AppImage");
            }
            else {
                this._logger.info("SNAP env is defined, updater is disabled");
            }
            return false;
        }
        return super.isUpdaterActive();
    }
    /*** @private */
    doDownloadUpdate(downloadUpdateOptions) {
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const fileInfo = (0, Provider_1.findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "AppImage", ["rpm", "deb", "pacman"]);
        return this.executeDownload({
            fileExtension: "AppImage",
            fileInfo,
            downloadUpdateOptions,
            task: async (updateFile, downloadOptions) => {
                const oldFile = process.env["APPIMAGE"];
                if (oldFile == null) {
                    throw (0, builder_util_runtime_1.newError)("APPIMAGE env is not defined", "ERR_UPDATER_OLD_FILE_NOT_FOUND");
                }
                if (downloadUpdateOptions.disableDifferentialDownload || (await this.downloadDifferential(fileInfo, oldFile, updateFile, provider, downloadUpdateOptions))) {
                    await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions);
                }
                await (0, fs_extra_1.chmod)(updateFile, 0o755);
            },
        });
    }
    async downloadDifferential(fileInfo, oldFile, updateFile, provider, downloadUpdateOptions) {
        try {
            const downloadOptions = {
                newUrl: fileInfo.url,
                oldFile,
                logger: this._logger,
                newFile: updateFile,
                isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,
                requestHeaders: downloadUpdateOptions.requestHeaders,
                cancellationToken: downloadUpdateOptions.cancellationToken,
            };
            if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
            }
            await new FileWithEmbeddedBlockMapDifferentialDownloader_1.FileWithEmbeddedBlockMapDifferentialDownloader(fileInfo.info, this.httpExecutor, downloadOptions).download();
            return false;
        }
        catch (e) {
            this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`);
            // during test (developer machine mac) we must throw error
            return process.platform === "linux";
        }
    }
    doInstall(options) {
        const appImageFile = process.env["APPIMAGE"];
        if (appImageFile == null) {
            throw (0, builder_util_runtime_1.newError)("APPIMAGE env is not defined", "ERR_UPDATER_OLD_FILE_NOT_FOUND");
        }
        if (!path.isAbsolute(appImageFile) || appImageFile.includes("\0")) {
            throw (0, builder_util_runtime_1.newError)(`APPIMAGE env is not a valid absolute path: "${appImageFile}"`, "ERR_UPDATER_OLD_FILE_NOT_FOUND");
        }
        // https://stackoverflow.com/a/1712051/1910191
        (0, fs_1.unlinkSync)(appImageFile);
        let destination;
        const existingBaseName = path.basename(appImageFile);
        const installerPath = this.installerPath;
        if (installerPath == null) {
            this.dispatchError(new Error("No update filepath provided, can't quit and install"));
            return false;
        }
        // https://github.com/electron-userland/electron-builder/issues/2964
        // if no version in existing file name, it means that user wants to preserve current custom name
        if (path.basename(installerPath) === existingBaseName || !/\d+\.\d+\.\d+/.test(existingBaseName)) {
            // no version in the file name, overwrite existing
            destination = appImageFile;
        }
        else {
            destination = path.join(path.dirname(appImageFile), path.basename(installerPath));
        }
        (0, child_process_1.execFileSync)("mv", ["-f", installerPath, destination]);
        if (destination !== appImageFile) {
            this.emit("appimage-filename-updated", destination);
        }
        const env = {
            ...process.env,
            APPIMAGE_SILENT_INSTALL: "true",
        };
        if (options.isForceRunAfter) {
            // eslint-disable-next-line @typescript-eslint/no-floating-promises
            this.spawnLog(destination, [], env);
        }
        else {
            env.APPIMAGE_EXIT_AFTER_INSTALL = "true";
            (0, child_process_1.execFileSync)(destination, [], { env });
        }
        return true;
    }
}
exports.AppImageUpdater = AppImageUpdater;
//# sourceMappingURL=AppImageUpdater.js.map{"version":3,"file":"AppImageUpdater.js","sourceRoot":"","sources":["../src/AppImageUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions, newError } from \"builder-util-runtime\"\nimport { execFileSync } from \"child_process\"\nimport { chmod } from \"fs-extra\"\nimport { unlinkSync } from \"fs\"\nimport * as path from \"path\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { BaseUpdater, InstallOptions } from \"./BaseUpdater\"\nimport { DifferentialDownloaderOptions } from \"./differentialDownloader/DifferentialDownloader\"\nimport { FileWithEmbeddedBlockMapDifferentialDownloader } from \"./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader\"\nimport { findFile, Provider } from \"./providers/Provider\"\nimport { DOWNLOAD_PROGRESS, ResolvedUpdateFileInfo } from \"./types\"\n\nexport class AppImageUpdater extends BaseUpdater {\n  constructor(options?: AllPublishOptions | null, app?: any) {\n    super(options, app)\n  }\n\n  public isUpdaterActive(): boolean {\n    if (process.env[\"APPIMAGE\"] == null && !this.forceDevUpdateConfig) {\n      if (process.env[\"SNAP\"] == null) {\n        this._logger.warn(\"APPIMAGE env is not defined, current application is not an AppImage\")\n      } else {\n        this._logger.info(\"SNAP env is defined, updater is disabled\")\n      }\n      return false\n    }\n    return super.isUpdaterActive()\n  }\n\n  /*** @private */\n  protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"AppImage\", [\"rpm\", \"deb\", \"pacman\"])!\n    return this.executeDownload({\n      fileExtension: \"AppImage\",\n      fileInfo,\n      downloadUpdateOptions,\n      task: async (updateFile, downloadOptions) => {\n        const oldFile = process.env[\"APPIMAGE\"]!\n        if (oldFile == null) {\n          throw newError(\"APPIMAGE env is not defined\", \"ERR_UPDATER_OLD_FILE_NOT_FOUND\")\n        }\n\n        if (downloadUpdateOptions.disableDifferentialDownload || (await this.downloadDifferential(fileInfo, oldFile, updateFile, provider, downloadUpdateOptions))) {\n          await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions)\n        }\n\n        await chmod(updateFile, 0o755)\n      },\n    })\n  }\n\n  private async downloadDifferential(fileInfo: ResolvedUpdateFileInfo, oldFile: string, updateFile: string, provider: Provider<any>, downloadUpdateOptions: DownloadUpdateOptions) {\n    try {\n      const downloadOptions: DifferentialDownloaderOptions = {\n        newUrl: fileInfo.url,\n        oldFile,\n        logger: this._logger,\n        newFile: updateFile,\n        isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,\n        requestHeaders: downloadUpdateOptions.requestHeaders,\n        cancellationToken: downloadUpdateOptions.cancellationToken,\n      }\n\n      if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n        downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n      }\n\n      await new FileWithEmbeddedBlockMapDifferentialDownloader(fileInfo.info, this.httpExecutor, downloadOptions).download()\n      return false\n    } catch (e: any) {\n      this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`)\n      // during test (developer machine mac) we must throw error\n      return process.platform === \"linux\"\n    }\n  }\n\n  protected doInstall(options: InstallOptions): boolean {\n    const appImageFile = process.env[\"APPIMAGE\"]!\n    if (appImageFile == null) {\n      throw newError(\"APPIMAGE env is not defined\", \"ERR_UPDATER_OLD_FILE_NOT_FOUND\")\n    }\n    if (!path.isAbsolute(appImageFile) || appImageFile.includes(\"\\0\")) {\n      throw newError(`APPIMAGE env is not a valid absolute path: \"${appImageFile}\"`, \"ERR_UPDATER_OLD_FILE_NOT_FOUND\")\n    }\n\n    // https://stackoverflow.com/a/1712051/1910191\n    unlinkSync(appImageFile)\n\n    let destination: string\n    const existingBaseName = path.basename(appImageFile)\n    const installerPath = this.installerPath\n    if (installerPath == null) {\n      this.dispatchError(new Error(\"No update filepath provided, can't quit and install\"))\n      return false\n    }\n    // https://github.com/electron-userland/electron-builder/issues/2964\n    // if no version in existing file name, it means that user wants to preserve current custom name\n    if (path.basename(installerPath) === existingBaseName || !/\\d+\\.\\d+\\.\\d+/.test(existingBaseName)) {\n      // no version in the file name, overwrite existing\n      destination = appImageFile\n    } else {\n      destination = path.join(path.dirname(appImageFile), path.basename(installerPath))\n    }\n\n    execFileSync(\"mv\", [\"-f\", installerPath, destination])\n    if (destination !== appImageFile) {\n      this.emit(\"appimage-filename-updated\", destination)\n    }\n\n    const env: NodeJS.ProcessEnv = {\n      ...process.env,\n      APPIMAGE_SILENT_INSTALL: \"true\",\n    }\n\n    if (options.isForceRunAfter) {\n      // eslint-disable-next-line @typescript-eslint/no-floating-promises\n      this.spawnLog(destination, [], env)\n    } else {\n      env.APPIMAGE_EXIT_AFTER_INSTALL = \"true\"\n      execFileSync(destination, [], { env })\n    }\n    return true\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NoOpLogger = exports.AppUpdater = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const crypto_1 = require("crypto");
const os_1 = require("os");
const events_1 = require("events");
const fs_extra_1 = require("fs-extra");
const js_yaml_1 = require("js-yaml");
const lazy_val_1 = require("lazy-val");
const path = require("path");
const semver_1 = require("semver");
const DownloadedUpdateHelper_1 = require("./DownloadedUpdateHelper");
const ElectronAppAdapter_1 = require("./ElectronAppAdapter");
const electronHttpExecutor_1 = require("./electronHttpExecutor");
const GenericProvider_1 = require("./providers/GenericProvider");
const providerFactory_1 = require("./providerFactory");
const zlib_1 = require("zlib");
const GenericDifferentialDownloader_1 = require("./differentialDownloader/GenericDifferentialDownloader");
const types_1 = require("./types");
class AppUpdater extends events_1.EventEmitter {
    /**
     * Get the update channel. Doesn't return `channel` from the update configuration, only if was previously set.
     */
    get channel() {
        return this._channel;
    }
    /**
     * Set the update channel. Overrides `channel` in the update configuration.
     *
     * `allowDowngrade` will be automatically set to `true`. If this behavior is not suitable for you, simple set `allowDowngrade` explicitly after.
     */
    set channel(value) {
        if (this._channel != null) {
            // noinspection SuspiciousTypeOfGuard
            if (typeof value !== "string") {
                throw (0, builder_util_runtime_1.newError)(`Channel must be a string, but got: ${value}`, "ERR_UPDATER_INVALID_CHANNEL");
            }
            else if (value.length === 0) {
                throw (0, builder_util_runtime_1.newError)(`Channel must be not an empty string`, "ERR_UPDATER_INVALID_CHANNEL");
            }
        }
        this._channel = value;
        this.allowDowngrade = true;
    }
    /**
     *  Shortcut for explicitly adding auth tokens to request headers
     */
    addAuthHeader(token) {
        this.requestHeaders = Object.assign({}, this.requestHeaders, {
            authorization: token,
        });
    }
    // noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols
    get netSession() {
        return (0, electronHttpExecutor_1.getNetSession)();
    }
    /**
     * The logger. You can pass [electron-log](https://github.com/megahertz/electron-log), [winston](https://github.com/winstonjs/winston) or another logger with the following interface: `{ info(), warn(), error() }`.
     * Set it to `null` if you would like to disable a logging feature.
     */
    get logger() {
        return this._logger;
    }
    set logger(value) {
        this._logger = value == null ? new NoOpLogger() : value;
    }
    // noinspection JSUnusedGlobalSymbols
    /**
     * test only
     * @private
     */
    set updateConfigPath(value) {
        this.clientPromise = null;
        this._appUpdateConfigPath = value;
        this.configOnDisk = new lazy_val_1.Lazy(() => this.loadUpdateConfig());
    }
    /**
     * Allows developer to override default logic for determining if an update is supported.
     * The default logic compares the `UpdateInfo` minimum system version against the `os.release()` with `semver` package
     */
    get isUpdateSupported() {
        return this._isUpdateSupported;
    }
    set isUpdateSupported(value) {
        if (value) {
            this._isUpdateSupported = value;
        }
    }
    /**
     * Allows developer to override default logic for determining if the user is below the rollout threshold.
     * The default logic compares the staging percentage with numerical representation of user ID.
     * An override can define custom logic, or bypass it if needed.
     */
    get isUserWithinRollout() {
        return this._isUserWithinRollout;
    }
    set isUserWithinRollout(value) {
        if (value) {
            this._isUserWithinRollout = value;
        }
    }
    constructor(options, app) {
        super();
        /**
         * Whether to automatically download an update when it is found.
         * @default true
         */
        this.autoDownload = true;
        /**
         * Whether to automatically install a downloaded update on app quit (if `quitAndInstall` was not called before).
         * @default true
         */
        this.autoInstallOnAppQuit = true;
        /**
         * Whether to run the app after finish install when run the installer is NOT in silent mode.
         * @default true
         */
        this.autoRunAppAfterInstall = true;
        /**
         * *GitHub provider only.* Whether to allow update to pre-release versions. Defaults to `true` if application version contains prerelease components (e.g. `0.12.1-alpha.1`, here `alpha` is a prerelease component), otherwise `false`.
         *
         * If `true`, downgrade will be allowed (`allowDowngrade` will be set to `true`).
         */
        this.allowPrerelease = false;
        /**
         * *GitHub provider only.* Get all release notes (from current version to latest), not just the latest.
         * @default false
         */
        this.fullChangelog = false;
        /**
         * Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel).
         *
         * Taken in account only if channel differs (pre-release version component in terms of semantic versioning).
         *
         * @default false
         */
        this.allowDowngrade = false;
        /**
         * Web installer files might not have signature verification, this switch prevents to load them unless it is needed.
         *
         * Currently false to prevent breaking the current API, but it should be changed to default true at some point that
         * breaking changes are allowed.
         *
         * @default false
         */
        this.disableWebInstaller = false;
        /**
         * *NSIS only* Disable differential downloads and always perform full download of installer.
         *
         * @default false
         */
        this.disableDifferentialDownload = false;
        /**
         * Allows developer to force the updater to work in "dev" mode, looking for "dev-app-update.yml" instead of "app-update.yml"
         * Dev: `path.join(this.app.getAppPath(), "dev-app-update.yml")`
         * Prod: `path.join(process.resourcesPath!, "app-update.yml")`
         *
         * @default false
         */
        this.forceDevUpdateConfig = false;
        /**
         * The base URL of the old block map file.
         *
         * When null, the updater will use the base URL of the update file to download the update.
         * When set, the updater will use this string as the base URL of the old block map file.
         * Some servers like github cannot download the old block map file from latest release,
         * so you need to compute the old block map file base URL manually.
         *
         * @default null
         */
        this.previousBlockmapBaseUrlOverride = null;
        this._channel = null;
        this.downloadedUpdateHelper = null;
        /**
         *  The request headers.
         */
        this.requestHeaders = null;
        this._logger = console;
        // noinspection JSUnusedGlobalSymbols
        /**
         * For type safety you can use signals, e.g. `autoUpdater.signals.updateDownloaded(() => {})` instead of `autoUpdater.on('update-available', () => {})`
         */
        this.signals = new types_1.UpdaterSignal(this);
        this._appUpdateConfigPath = null;
        this._isUpdateSupported = updateInfo => this.checkIfUpdateSupported(updateInfo);
        this._isUserWithinRollout = updateInfo => this.isStagingMatch(updateInfo);
        this.clientPromise = null;
        this.stagingUserIdPromise = new lazy_val_1.Lazy(() => this.getOrCreateStagingUserId());
        // public, allow to read old config for anyone
        /** @internal */
        this.configOnDisk = new lazy_val_1.Lazy(() => this.loadUpdateConfig());
        this.checkForUpdatesPromise = null;
        this.downloadPromise = null;
        this.updateInfoAndProvider = null;
        /**
         * @private
         * @internal
         */
        this._testOnlyOptions = null;
        this.on("error", (error) => {
            this._logger.error(`Error: ${error.stack || error.message}`);
        });
        if (app == null) {
            this.app = new ElectronAppAdapter_1.ElectronAppAdapter();
            this.httpExecutor = new electronHttpExecutor_1.ElectronHttpExecutor((authInfo, callback) => this.emit("login", authInfo, callback));
        }
        else {
            this.app = app;
            this.httpExecutor = null;
        }
        const currentVersionString = this.app.version;
        const currentVersion = (0, semver_1.parse)(currentVersionString);
        if (currentVersion == null) {
            throw (0, builder_util_runtime_1.newError)(`App version is not a valid semver version: "${currentVersionString}"`, "ERR_UPDATER_INVALID_VERSION");
        }
        this.currentVersion = currentVersion;
        this.allowPrerelease = hasPrereleaseComponents(currentVersion);
        if (options != null) {
            this.setFeedURL(options);
            if (typeof options !== "string" && options.requestHeaders) {
                this.requestHeaders = options.requestHeaders;
            }
        }
    }
    //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols
    getFeedURL() {
        return "Deprecated. Do not use it.";
    }
    /**
     * Configure update provider. If value is `string`, [GenericServerOptions](https://www.electron.build/publish#genericserveroptions) will be set with value as `url`.
     * @param options If you want to override configuration in the `app-update.yml`.
     */
    setFeedURL(options) {
        const runtimeOptions = this.createProviderRuntimeOptions();
        // https://github.com/electron-userland/electron-builder/issues/1105
        let provider;
        if (typeof options === "string") {
            provider = new GenericProvider_1.GenericProvider({ provider: "generic", url: options }, this, {
                ...runtimeOptions,
                isUseMultipleRangeRequest: (0, providerFactory_1.isUrlProbablySupportMultiRangeRequests)(options),
            });
        }
        else {
            provider = (0, providerFactory_1.createClient)(options, this, runtimeOptions);
        }
        this.clientPromise = Promise.resolve(provider);
    }
    /**
     * Asks the server whether there is an update.
     * @returns null if the updater is disabled, otherwise info about the latest version
     */
    checkForUpdates() {
        if (!this.isUpdaterActive()) {
            return Promise.resolve(null);
        }
        let checkForUpdatesPromise = this.checkForUpdatesPromise;
        if (checkForUpdatesPromise != null) {
            this._logger.info("Checking for update (already in progress)");
            return checkForUpdatesPromise;
        }
        const nullizePromise = () => (this.checkForUpdatesPromise = null);
        this._logger.info("Checking for update");
        checkForUpdatesPromise = this.doCheckForUpdates()
            .then(it => {
            nullizePromise();
            return it;
        })
            .catch((e) => {
            nullizePromise();
            this.emit("error", e, `Cannot check for updates: ${(e.stack || e).toString()}`);
            throw e;
        });
        this.checkForUpdatesPromise = checkForUpdatesPromise;
        return checkForUpdatesPromise;
    }
    isUpdaterActive() {
        const isEnabled = this.app.isPackaged || this.forceDevUpdateConfig;
        if (!isEnabled) {
            this._logger.info("Skip checkForUpdates because application is not packed and dev update config is not forced");
            return false;
        }
        return true;
    }
    // noinspection JSUnusedGlobalSymbols
    checkForUpdatesAndNotify(downloadNotification) {
        return this.checkForUpdates().then(it => {
            if (!(it === null || it === void 0 ? void 0 : it.downloadPromise)) {
                if (this._logger.debug != null) {
                    this._logger.debug("checkForUpdatesAndNotify called, downloadPromise is null");
                }
                return it;
            }
            void it.downloadPromise.then(() => {
                const notificationContent = AppUpdater.formatDownloadNotification(it.updateInfo.version, this.app.name, downloadNotification);
                new (require("electron").Notification)(notificationContent).show();
            });
            return it;
        });
    }
    static formatDownloadNotification(version, appName, downloadNotification) {
        if (downloadNotification == null) {
            downloadNotification = {
                title: "A new update is ready to install",
                body: `{appName} version {version} has been downloaded and will be automatically installed on exit`,
            };
        }
        downloadNotification = {
            title: downloadNotification.title.replace("{appName}", appName).replace("{version}", version),
            body: downloadNotification.body.replace("{appName}", appName).replace("{version}", version),
        };
        return downloadNotification;
    }
    async isStagingMatch(updateInfo) {
        const rawStagingPercentage = updateInfo.stagingPercentage;
        let stagingPercentage = rawStagingPercentage;
        if (stagingPercentage == null) {
            return true;
        }
        stagingPercentage = parseInt(stagingPercentage, 10);
        if (isNaN(stagingPercentage)) {
            this._logger.warn(`Staging percentage is NaN: ${rawStagingPercentage}`);
            return true;
        }
        // convert from user 0-100 to internal 0-1
        stagingPercentage = stagingPercentage / 100;
        const stagingUserId = await this.stagingUserIdPromise.value;
        const val = builder_util_runtime_1.UUID.parse(stagingUserId).readUInt32BE(12);
        const percentage = val / 0xffffffff;
        this._logger.info(`Staging percentage: ${stagingPercentage}, percentage: ${percentage}, user id: ${stagingUserId}`);
        return percentage < stagingPercentage;
    }
    computeFinalHeaders(headers) {
        if (this.requestHeaders != null) {
            Object.assign(headers, this.requestHeaders);
        }
        return headers;
    }
    async isUpdateAvailable(updateInfo) {
        const latestVersion = (0, semver_1.parse)(updateInfo.version);
        if (latestVersion == null) {
            throw (0, builder_util_runtime_1.newError)(`This file could not be downloaded, or the latest version (from update server) does not have a valid semver version: "${updateInfo.version}"`, "ERR_UPDATER_INVALID_VERSION");
        }
        const currentVersion = this.currentVersion;
        if ((0, semver_1.eq)(latestVersion, currentVersion)) {
            return false;
        }
        if (!(await Promise.resolve(this.isUpdateSupported(updateInfo)))) {
            return false;
        }
        const isUserWithinRollout = await Promise.resolve(this.isUserWithinRollout(updateInfo));
        if (!isUserWithinRollout) {
            return false;
        }
        // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405033227
        // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405030797
        const isLatestVersionNewer = (0, semver_1.gt)(latestVersion, currentVersion);
        const isLatestVersionOlder = (0, semver_1.lt)(latestVersion, currentVersion);
        if (isLatestVersionNewer) {
            return true;
        }
        return this.allowDowngrade && isLatestVersionOlder;
    }
    checkIfUpdateSupported(updateInfo) {
        const minimumSystemVersion = updateInfo === null || updateInfo === void 0 ? void 0 : updateInfo.minimumSystemVersion;
        const currentOSVersion = (0, os_1.release)();
        if (minimumSystemVersion) {
            try {
                if ((0, semver_1.lt)(currentOSVersion, minimumSystemVersion)) {
                    this._logger.info(`Current OS version ${currentOSVersion} is less than the minimum OS version required ${minimumSystemVersion} for version ${currentOSVersion}`);
                    return false;
                }
            }
            catch (e) {
                this._logger.warn(`Failed to compare current OS version(${currentOSVersion}) with minimum OS version(${minimumSystemVersion}): ${(e.message || e).toString()}`);
            }
        }
        return true;
    }
    async getUpdateInfoAndProvider() {
        await this.app.whenReady();
        if (this.clientPromise == null) {
            this.clientPromise = this.configOnDisk.value.then(it => (0, providerFactory_1.createClient)(it, this, this.createProviderRuntimeOptions()));
        }
        const client = await this.clientPromise;
        const stagingUserId = await this.stagingUserIdPromise.value;
        client.setRequestHeaders(this.computeFinalHeaders({ "x-user-staging-id": stagingUserId }));
        return {
            info: await client.getLatestVersion(),
            provider: client,
        };
    }
    createProviderRuntimeOptions() {
        return {
            isUseMultipleRangeRequest: true,
            platform: this._testOnlyOptions == null ? process.platform : this._testOnlyOptions.platform,
            executor: this.httpExecutor,
        };
    }
    async doCheckForUpdates() {
        this.emit("checking-for-update");
        const result = await this.getUpdateInfoAndProvider();
        const updateInfo = result.info;
        if (!(await this.isUpdateAvailable(updateInfo))) {
            this._logger.info(`Update for version ${this.currentVersion.format()} is not available (latest version: ${updateInfo.version}, downgrade is ${this.allowDowngrade ? "allowed" : "disallowed"}).`);
            this.emit("update-not-available", updateInfo);
            return {
                isUpdateAvailable: false,
                versionInfo: updateInfo,
                updateInfo,
            };
        }
        this.updateInfoAndProvider = result;
        this.onUpdateAvailable(updateInfo);
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        //noinspection ES6MissingAwait
        return {
            isUpdateAvailable: true,
            versionInfo: updateInfo,
            updateInfo,
            cancellationToken,
            downloadPromise: this.autoDownload ? this.downloadUpdate(cancellationToken) : null,
        };
    }
    onUpdateAvailable(updateInfo) {
        this._logger.info(`Found version ${updateInfo.version} (url: ${(0, builder_util_runtime_1.asArray)(updateInfo.files)
            .map(it => it.url)
            .join(", ")})`);
        this.emit("update-available", updateInfo);
    }
    /**
     * Start downloading update manually. You can use this method if `autoDownload` option is set to `false`.
     * @returns {Promise<Array<string>>} Paths to downloaded files.
     */
    downloadUpdate(cancellationToken = new builder_util_runtime_1.CancellationToken()) {
        const updateInfoAndProvider = this.updateInfoAndProvider;
        if (updateInfoAndProvider == null) {
            const error = new Error("Please check update first");
            this.dispatchError(error);
            return Promise.reject(error);
        }
        if (this.downloadPromise != null) {
            this._logger.info("Downloading update (already in progress)");
            return this.downloadPromise;
        }
        this._logger.info(`Downloading update from ${(0, builder_util_runtime_1.asArray)(updateInfoAndProvider.info.files)
            .map(it => it.url)
            .join(", ")}`);
        const errorHandler = (e) => {
            // https://github.com/electron-userland/electron-builder/issues/1150#issuecomment-436891159
            if (!(e instanceof builder_util_runtime_1.CancellationError)) {
                try {
                    this.dispatchError(e);
                }
                catch (nestedError) {
                    this._logger.warn(`Cannot dispatch error event: ${nestedError.stack || nestedError}`);
                }
            }
            return e;
        };
        this.downloadPromise = this.doDownloadUpdate({
            updateInfoAndProvider,
            requestHeaders: this.computeRequestHeaders(updateInfoAndProvider.provider),
            cancellationToken,
            disableWebInstaller: this.disableWebInstaller,
            disableDifferentialDownload: this.disableDifferentialDownload,
        })
            .catch((e) => {
            throw errorHandler(e);
        })
            .finally(() => {
            this.downloadPromise = null;
        });
        return this.downloadPromise;
    }
    dispatchError(e) {
        this.emit("error", e, (e.stack || e).toString());
    }
    dispatchUpdateDownloaded(event) {
        this.emit(types_1.UPDATE_DOWNLOADED, event);
    }
    async loadUpdateConfig() {
        if (this._appUpdateConfigPath == null) {
            this._appUpdateConfigPath = this.app.appUpdateConfigPath;
        }
        return (0, js_yaml_1.load)(await (0, fs_extra_1.readFile)(this._appUpdateConfigPath, "utf-8"));
    }
    computeRequestHeaders(provider) {
        const fileExtraDownloadHeaders = provider.fileExtraDownloadHeaders;
        if (fileExtraDownloadHeaders != null) {
            const requestHeaders = this.requestHeaders;
            return requestHeaders == null
                ? fileExtraDownloadHeaders
                : {
                    ...fileExtraDownloadHeaders,
                    ...requestHeaders,
                };
        }
        return this.computeFinalHeaders({ accept: "*/*" });
    }
    async getOrCreateStagingUserId() {
        const file = path.join(this.app.userDataPath, ".updaterId");
        try {
            const id = await (0, fs_extra_1.readFile)(file, "utf-8");
            if (builder_util_runtime_1.UUID.check(id)) {
                return id;
            }
            else {
                this._logger.warn(`Staging user id file exists, but content was invalid: ${id}`);
            }
        }
        catch (e) {
            if (e.code !== "ENOENT") {
                this._logger.warn(`Couldn't read staging user ID, creating a blank one: ${e}`);
            }
        }
        const id = builder_util_runtime_1.UUID.v5((0, crypto_1.randomBytes)(4096), builder_util_runtime_1.UUID.OID);
        this._logger.info(`Generated new staging user ID: ${id}`);
        try {
            await (0, fs_extra_1.outputFile)(file, id);
        }
        catch (e) {
            this._logger.warn(`Couldn't write out staging user ID: ${e}`);
        }
        return id;
    }
    /** @internal */
    get isAddNoCacheQuery() {
        const headers = this.requestHeaders;
        // https://github.com/electron-userland/electron-builder/issues/3021
        if (headers == null) {
            return true;
        }
        for (const headerName of Object.keys(headers)) {
            const s = headerName.toLowerCase();
            if (s === "authorization" || s === "private-token") {
                return false;
            }
        }
        return true;
    }
    async getOrCreateDownloadHelper() {
        let result = this.downloadedUpdateHelper;
        if (result == null) {
            const dirName = (await this.configOnDisk.value).updaterCacheDirName;
            const logger = this._logger;
            if (dirName == null) {
                logger.error("updaterCacheDirName is not specified in app-update.yml Was app build using at least electron-builder 20.34.0?");
            }
            const cacheDir = path.join(this.app.baseCachePath, dirName || this.app.name);
            if (logger.debug != null) {
                logger.debug(`updater cache dir: ${cacheDir}`);
            }
            result = new DownloadedUpdateHelper_1.DownloadedUpdateHelper(cacheDir);
            this.downloadedUpdateHelper = result;
        }
        return result;
    }
    async executeDownload(taskOptions) {
        const fileInfo = taskOptions.fileInfo;
        const downloadOptions = {
            headers: taskOptions.downloadUpdateOptions.requestHeaders,
            cancellationToken: taskOptions.downloadUpdateOptions.cancellationToken,
            sha2: fileInfo.info.sha2,
            sha512: fileInfo.info.sha512,
        };
        if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
            downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
        }
        const updateInfo = taskOptions.downloadUpdateOptions.updateInfoAndProvider.info;
        const version = updateInfo.version;
        const packageInfo = fileInfo.packageInfo;
        function getCacheUpdateFileName() {
            // NodeJS URL doesn't decode automatically
            const urlPath = decodeURIComponent(taskOptions.fileInfo.url.pathname);
            if (urlPath.toLowerCase().endsWith(`.${taskOptions.fileExtension.toLowerCase()}`)) {
                return path.basename(urlPath);
            }
            else {
                // url like /latest — use basename so a server-supplied path like "../../etc/evil"
                // cannot escape the cache directory via path.join
                return path.basename(taskOptions.fileInfo.info.url);
            }
        }
        const downloadedUpdateHelper = await this.getOrCreateDownloadHelper();
        const cacheDir = downloadedUpdateHelper.cacheDirForPendingUpdate;
        await (0, fs_extra_1.mkdir)(cacheDir, { recursive: true });
        const updateFileName = getCacheUpdateFileName();
        let updateFile = path.join(cacheDir, updateFileName);
        const packageFile = packageInfo == null ? null : path.join(cacheDir, `package-${version}${path.extname(packageInfo.path) || ".7z"}`);
        const done = async (isSaveCache) => {
            await downloadedUpdateHelper.setDownloadedFile(updateFile, packageFile, updateInfo, fileInfo, updateFileName, isSaveCache);
            await taskOptions.done({
                ...updateInfo,
                downloadedFile: updateFile,
            });
            const currentBlockMapFile = path.join(cacheDir, "current.blockmap");
            if (await (0, fs_extra_1.pathExists)(currentBlockMapFile)) {
                await (0, fs_extra_1.copyFile)(currentBlockMapFile, path.join(downloadedUpdateHelper.cacheDir, "current.blockmap"));
            }
            return packageFile == null ? [updateFile] : [updateFile, packageFile];
        };
        const log = this._logger;
        const cachedUpdateFile = await downloadedUpdateHelper.validateDownloadedPath(updateFile, updateInfo, fileInfo, log);
        if (cachedUpdateFile != null) {
            updateFile = cachedUpdateFile;
            return await done(false);
        }
        const removeFileIfAny = async () => {
            await downloadedUpdateHelper.clear().catch(() => {
                // ignore
            });
            return await (0, fs_extra_1.unlink)(updateFile).catch(() => {
                // ignore
            });
        };
        const tempUpdateFile = await (0, DownloadedUpdateHelper_1.createTempUpdateFile)(`temp-${updateFileName}`, cacheDir, log);
        try {
            await taskOptions.task(tempUpdateFile, downloadOptions, packageFile, removeFileIfAny);
            await (0, builder_util_runtime_1.retry)(() => (0, fs_extra_1.rename)(tempUpdateFile, updateFile), {
                retries: 60,
                interval: 500,
                shouldRetry: (error) => {
                    if (error instanceof Error && /^EBUSY:/.test(error.message)) {
                        return true;
                    }
                    log.warn(`Cannot rename temp file to final file: ${error.message || error.stack}`);
                    return false;
                },
            });
        }
        catch (e) {
            await removeFileIfAny();
            if (e instanceof builder_util_runtime_1.CancellationError) {
                log.info("cancelled");
                this.emit("update-cancelled", updateInfo);
            }
            throw e;
        }
        log.info(`New version ${version} has been downloaded to ${updateFile}`);
        return await done(true);
    }
    async differentialDownloadInstaller(fileInfo, downloadUpdateOptions, installerPath, provider, oldInstallerFileName) {
        try {
            if (this._testOnlyOptions != null && !this._testOnlyOptions.isUseDifferentialDownload) {
                return true;
            }
            const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
            const blockmapFileUrls = await provider.getBlockMapFiles(fileInfo.url, this.app.version, downloadUpdateOptions.updateInfoAndProvider.info.version, this.previousBlockmapBaseUrlOverride);
            this._logger.info(`Download block maps (old: "${blockmapFileUrls[0]}", new: ${blockmapFileUrls[1]})`);
            const downloadBlockMap = async (url) => {
                const data = await this.httpExecutor.downloadToBuffer(url, {
                    headers: downloadUpdateOptions.requestHeaders,
                    cancellationToken: downloadUpdateOptions.cancellationToken,
                });
                if (data == null || data.length === 0) {
                    throw new Error(`Blockmap "${url.href}" is empty`);
                }
                try {
                    return JSON.parse((0, zlib_1.gunzipSync)(data).toString());
                }
                catch (e) {
                    throw new Error(`Cannot parse blockmap "${url.href}", error: ${e}`);
                }
            };
            const downloadOptions = {
                newUrl: fileInfo.url,
                oldFile: path.join(this.downloadedUpdateHelper.cacheDir, oldInstallerFileName),
                logger: this._logger,
                newFile: installerPath,
                isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,
                requestHeaders: downloadUpdateOptions.requestHeaders,
                cancellationToken: downloadUpdateOptions.cancellationToken,
            };
            if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
            }
            const saveBlockMapToCacheDir = async (blockMapData, cacheDir) => {
                const blockMapFile = path.join(cacheDir, "current.blockmap");
                await (0, fs_extra_1.outputFile)(blockMapFile, (0, zlib_1.gzipSync)(JSON.stringify(blockMapData)));
            };
            const getBlockMapFromCacheDir = async (cacheDir) => {
                const blockMapFile = path.join(cacheDir, "current.blockmap");
                try {
                    if (await (0, fs_extra_1.pathExists)(blockMapFile)) {
                        return JSON.parse((0, zlib_1.gunzipSync)(await (0, fs_extra_1.readFile)(blockMapFile)).toString());
                    }
                }
                catch (e) {
                    this._logger.warn(`Cannot parse blockmap "${blockMapFile}", error: ${e}`);
                }
                return null;
            };
            const newBlockMapData = await downloadBlockMap(blockmapFileUrls[1]);
            await saveBlockMapToCacheDir(newBlockMapData, this.downloadedUpdateHelper.cacheDirForPendingUpdate);
            // get old blockmap from cache dir first, if not found, download it
            let oldBlockMapData = await getBlockMapFromCacheDir(this.downloadedUpdateHelper.cacheDir);
            if (oldBlockMapData == null) {
                oldBlockMapData = await downloadBlockMap(blockmapFileUrls[0]);
            }
            await new GenericDifferentialDownloader_1.GenericDifferentialDownloader(fileInfo.info, this.httpExecutor, downloadOptions).download(oldBlockMapData, newBlockMapData);
            return false;
        }
        catch (e) {
            this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`);
            if (this._testOnlyOptions != null) {
                // test mode
                throw e;
            }
            return true;
        }
    }
}
exports.AppUpdater = AppUpdater;
function hasPrereleaseComponents(version) {
    const versionPrereleaseComponent = (0, semver_1.prerelease)(version);
    return versionPrereleaseComponent != null && versionPrereleaseComponent.length > 0;
}
/** @private */
class NoOpLogger {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    info(message) {
        // ignore
    }
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    warn(message) {
        // ignore
    }
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    error(message) {
        // ignore
    }
}
exports.NoOpLogger = NoOpLogger;
//# sourceMappingURL=AppUpdater.js.map{"version":3,"file":"AppUpdater.js","sourceRoot":"","sources":["../src/AppUpdater.ts"],"names":[],"mappings":";;;AAAA,+DAa6B;AAC7B,mCAAoC;AACpC,2BAA4B;AAC5B,mCAAqC;AACrC,uCAA4F;AAE5F,qCAA8B;AAC9B,uCAA+B;AAC/B,6BAA4B;AAC5B,mCAA8K;AAE9K,qEAAuF;AACvF,6DAAyD;AACzD,iEAA2F;AAC3F,iEAA6D;AAC7D,uDAAwF;AAKxF,+BAA2C;AAE3C,0GAAsG;AACtG,mCAAuJ;AAevJ,MAAsB,UAAW,SAAS,qBAAyD;IAwFjG;;OAEG;IACH,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED;;;;OAIG;IACH,IAAI,OAAO,CAAC,KAAoB;QAC9B,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;YAC1B,qCAAqC;YACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,MAAM,IAAA,+BAAQ,EAAC,sCAAsC,KAAK,EAAE,EAAE,6BAA6B,CAAC,CAAA;YAC9F,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAA,+BAAQ,EAAC,qCAAqC,EAAE,6BAA6B,CAAC,CAAA;YACtF,CAAC;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;QACrB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;IAC5B,CAAC;IAOD;;OAEG;IACH,aAAa,CAAC,KAAa;QACzB,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,cAAc,EAAE;YAC3D,aAAa,EAAE,KAAK;SACrB,CAAC,CAAA;IACJ,CAAC;IAID,yDAAyD;IACzD,IAAI,UAAU;QACZ,OAAO,IAAA,oCAAa,GAAE,CAAA;IACxB,CAAC;IAED;;;OAGG;IACH,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,IAAI,MAAM,CAAC,KAAoB;QAC7B,IAAI,CAAC,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;IACzD,CAAC;IAUD,qCAAqC;IACrC;;;OAGG;IACH,IAAI,gBAAgB,CAAC,KAAoB;QACvC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAA;QACzB,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAA;QACjC,IAAI,CAAC,YAAY,GAAG,IAAI,eAAI,CAAM,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAA;IAClE,CAAC;IAID;;;OAGG;IACH,IAAI,iBAAiB;QACnB,OAAO,IAAI,CAAC,kBAAkB,CAAA;IAChC,CAAC;IAED,IAAI,iBAAiB,CAAC,KAA0B;QAC9C,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAA;QACjC,CAAC;IACH,CAAC;IAID;;;;OAIG;IACH,IAAI,mBAAmB;QACrB,OAAO,IAAI,CAAC,oBAAoB,CAAA;IAClC,CAAC;IAED,IAAI,mBAAmB,CAAC,KAA0B;QAChD,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAA;QACnC,CAAC;IACH,CAAC;IAoBD,YAAsB,OAA6C,EAAE,GAAgB;QACnF,KAAK,EAAE,CAAA;QAzNT;;;WAGG;QACH,iBAAY,GAAG,IAAI,CAAA;QAEnB;;;WAGG;QACH,yBAAoB,GAAG,IAAI,CAAA;QAE3B;;;WAGG;QACH,2BAAsB,GAAG,IAAI,CAAA;QAE7B;;;;WAIG;QACH,oBAAe,GAAG,KAAK,CAAA;QAEvB;;;WAGG;QACH,kBAAa,GAAG,KAAK,CAAA;QAErB;;;;;;WAMG;QACH,mBAAc,GAAG,KAAK,CAAA;QAEtB;;;;;;;WAOG;QACH,wBAAmB,GAAG,KAAK,CAAA;QAE3B;;;;WAIG;QACH,gCAA2B,GAAG,KAAK,CAAA;QAEnC;;;;;;WAMG;QACH,yBAAoB,GAAG,KAAK,CAAA;QAE5B;;;;;;;;;WASG;QACI,oCAA+B,GAAkB,IAAI,CAAA;QAOpD,aAAQ,GAAkB,IAAI,CAAA;QAE5B,2BAAsB,GAAkC,IAAI,CAAA;QA4BtE;;WAEG;QACH,mBAAc,GAA+B,IAAI,CAAA;QAWvC,YAAO,GAAW,OAAO,CAAA;QAmBnC,qCAAqC;QACrC;;WAEG;QACM,YAAO,GAAG,IAAI,qBAAa,CAAC,IAAI,CAAC,CAAA;QAElC,yBAAoB,GAAkB,IAAI,CAAA;QAaxC,uBAAkB,GAAwB,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAA;QAgB/F,yBAAoB,GAAwB,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAA;QAiB3F,kBAAa,GAAkC,IAAI,CAAA;QAExC,yBAAoB,GAAG,IAAI,eAAI,CAAS,GAAG,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,CAAA;QAEjG,8CAA8C;QAC9C,gBAAgB;QAChB,iBAAY,GAAG,IAAI,eAAI,CAAM,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAA;QAEnD,2BAAsB,GAAsC,IAAI,CAAA;QAChE,oBAAe,GAAkC,IAAI,CAAA;QAInD,0BAAqB,GAAiC,IAAI,CAAA;QAoapE;;;WAGG;QACH,qBAAgB,GAAkC,IAAI,CAAA;QAhapD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;YAChC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAC9D,CAAC,CAAC,CAAA;QAEF,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAChB,IAAI,CAAC,GAAG,GAAG,IAAI,uCAAkB,EAAE,CAAA;YACnC,IAAI,CAAC,YAAY,GAAG,IAAI,2CAAoB,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAA;QAC9G,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;YACd,IAAI,CAAC,YAAY,GAAG,IAAW,CAAA;QACjC,CAAC;QAED,MAAM,oBAAoB,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAA;QAC7C,MAAM,cAAc,GAAG,IAAA,cAAY,EAAC,oBAAoB,CAAC,CAAA;QACzD,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;YAC3B,MAAM,IAAA,+BAAQ,EAAC,+CAA+C,oBAAoB,GAAG,EAAE,6BAA6B,CAAC,CAAA;QACvH,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,cAAc,CAAA;QACpC,IAAI,CAAC,eAAe,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAA;QAE9D,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;YAExB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;gBAC1D,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAA;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IAED,wDAAwD;IACxD,UAAU;QACR,OAAO,4BAA4B,CAAA;IACrC,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,OAA0D;QACnE,MAAM,cAAc,GAAG,IAAI,CAAC,4BAA4B,EAAE,CAAA;QAC1D,oEAAoE;QACpE,IAAI,QAAuB,CAAA;QAC3B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,QAAQ,GAAG,IAAI,iCAAe,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE;gBAC1E,GAAG,cAAc;gBACjB,yBAAyB,EAAE,IAAA,wDAAsC,EAAC,OAAO,CAAC;aAC3E,CAAC,CAAA;QACJ,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,IAAA,8BAAY,EAAC,OAAO,EAAE,IAAI,EAAE,cAAc,CAAC,CAAA;QACxD,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAChD,CAAC;IAED;;;OAGG;IACH,eAAe;QACb,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YAC5B,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC9B,CAAC;QAED,IAAI,sBAAsB,GAAG,IAAI,CAAC,sBAAsB,CAAA;QACxD,IAAI,sBAAsB,IAAI,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAA;YAC9D,OAAO,sBAAsB,CAAA;QAC/B,CAAC;QAED,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAA;QAEjE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;QACxC,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,EAAE;aAC9C,IAAI,CAAC,EAAE,CAAC,EAAE;YACT,cAAc,EAAE,CAAA;YAChB,OAAO,EAAE,CAAA;QACX,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,CAAM,EAAE,EAAE;YAChB,cAAc,EAAE,CAAA;YAChB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,6BAA6B,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;YAC/E,MAAM,CAAC,CAAA;QACT,CAAC,CAAC,CAAA;QAEJ,IAAI,CAAC,sBAAsB,GAAG,sBAAsB,CAAA;QACpD,OAAO,sBAAsB,CAAA;IAC/B,CAAC;IAEM,eAAe;QACpB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,oBAAoB,CAAA;QAClE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,4FAA4F,CAAC,CAAA;YAC/G,OAAO,KAAK,CAAA;QACd,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,qCAAqC;IACrC,wBAAwB,CAAC,oBAA2C;QAClE,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;YACtC,IAAI,CAAC,CAAA,EAAE,aAAF,EAAE,uBAAF,EAAE,CAAE,eAAe,CAAA,EAAE,CAAC;gBACzB,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;oBAC/B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAA;gBAChF,CAAC;gBACD,OAAO,EAAE,CAAA;YACX,CAAC;YAED,KAAK,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE;gBAChC,MAAM,mBAAmB,GAAG,UAAU,CAAC,0BAA0B,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAA;gBAC7H,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,mBAAmB,CAAC,CAAC,IAAI,EAAE,CAAA;YACpE,CAAC,CAAC,CAAA;YAEF,OAAO,EAAE,CAAA;QACX,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,MAAM,CAAC,0BAA0B,CAAC,OAAe,EAAE,OAAe,EAAE,oBAA2C;QACrH,IAAI,oBAAoB,IAAI,IAAI,EAAE,CAAC;YACjC,oBAAoB,GAAG;gBACrB,KAAK,EAAE,kCAAkC;gBACzC,IAAI,EAAE,6FAA6F;aACpG,CAAA;QACH,CAAC;QACD,oBAAoB,GAAG;YACrB,KAAK,EAAE,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC;YAC7F,IAAI,EAAE,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC;SAC5F,CAAA;QACD,OAAO,oBAAoB,CAAA;IAC7B,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,UAAsB;QACjD,MAAM,oBAAoB,GAAG,UAAU,CAAC,iBAAiB,CAAA;QACzD,IAAI,iBAAiB,GAAG,oBAAoB,CAAA;QAC5C,IAAI,iBAAiB,IAAI,IAAI,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAA;QACb,CAAC;QAED,iBAAiB,GAAG,QAAQ,CAAC,iBAAwB,EAAE,EAAE,CAAC,CAAA;QAC1D,IAAI,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,8BAA8B,oBAAoB,EAAE,CAAC,CAAA;YACvE,OAAO,IAAI,CAAA;QACb,CAAC;QAED,0CAA0C;QAC1C,iBAAiB,GAAG,iBAAiB,GAAG,GAAG,CAAA;QAE3C,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAA;QAC3D,MAAM,GAAG,GAAG,2BAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;QACtD,MAAM,UAAU,GAAG,GAAG,GAAG,UAAU,CAAA;QACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,uBAAuB,iBAAiB,iBAAiB,UAAU,cAAc,aAAa,EAAE,CAAC,CAAA;QACnH,OAAO,UAAU,GAAG,iBAAiB,CAAA;IACvC,CAAC;IAEO,mBAAmB,CAAC,OAA4B;QACtD,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;QAC7C,CAAC;QACD,OAAO,OAAO,CAAA;IAChB,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,UAAsB;QACpD,MAAM,aAAa,GAAG,IAAA,cAAY,EAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QACtD,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YAC1B,MAAM,IAAA,+BAAQ,EACZ,wHAAwH,UAAU,CAAC,OAAO,GAAG,EAC7I,6BAA6B,CAC9B,CAAA;QACH,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAA;QAC1C,IAAI,IAAA,WAAe,EAAC,aAAa,EAAE,cAAc,CAAC,EAAE,CAAC;YACnD,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,OAAO,KAAK,CAAA;QACd,CAAC;QAED,MAAM,mBAAmB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAA;QACvF,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACzB,OAAO,KAAK,CAAA;QACd,CAAC;QAED,yFAAyF;QACzF,yFAAyF;QACzF,MAAM,oBAAoB,GAAG,IAAA,WAAoB,EAAC,aAAa,EAAE,cAAc,CAAC,CAAA;QAChF,MAAM,oBAAoB,GAAG,IAAA,WAAiB,EAAC,aAAa,EAAE,cAAc,CAAC,CAAA;QAE7E,IAAI,oBAAoB,EAAE,CAAC;YACzB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,IAAI,oBAAoB,CAAA;IACpD,CAAC;IAEO,sBAAsB,CAAC,UAAsB;QACnD,MAAM,oBAAoB,GAAG,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,oBAAoB,CAAA;QAC7D,MAAM,gBAAgB,GAAG,IAAA,YAAO,GAAE,CAAA;QAClC,IAAI,oBAAoB,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,IAAI,IAAA,WAAiB,EAAC,gBAAgB,EAAE,oBAAoB,CAAC,EAAE,CAAC;oBAC9D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,gBAAgB,iDAAiD,oBAAoB,gBAAgB,gBAAgB,EAAE,CAAC,CAAA;oBAChK,OAAO,KAAK,CAAA;gBACd,CAAC;YACH,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,wCAAwC,gBAAgB,6BAA6B,oBAAoB,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;YACjK,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAES,KAAK,CAAC,wBAAwB;QACtC,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;QAE1B,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC;YAC/B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAA,8BAAY,EAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,4BAA4B,EAAE,CAAC,CAAC,CAAA;QACtH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAA;QACvC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAA;QAC3D,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,aAAa,EAAE,CAAC,CAAC,CAAA;QAC1F,OAAO;YACL,IAAI,EAAE,MAAM,MAAM,CAAC,gBAAgB,EAAE;YACrC,QAAQ,EAAE,MAAM;SACjB,CAAA;IACH,CAAC;IAEO,4BAA4B;QAClC,OAAO;YACL,yBAAyB,EAAE,IAAI;YAC/B,QAAQ,EAAE,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAE,OAAO,CAAC,QAA6B,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ;YACjH,QAAQ,EAAE,IAAI,CAAC,YAAY;SAC5B,CAAA;IACH,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC7B,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;QAEhC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAA;QACpD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAA;QAC9B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,OAAO,CAAC,IAAI,CACf,sBAAsB,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,sCAAsC,UAAU,CAAC,OAAO,kBACxG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YACpC,IAAI,CACL,CAAA;YACD,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAA;YAC7C,OAAO;gBACL,iBAAiB,EAAE,KAAK;gBACxB,WAAW,EAAE,UAAU;gBACvB,UAAU;aACX,CAAA;QACH,CAAC;QAED,IAAI,CAAC,qBAAqB,GAAG,MAAM,CAAA;QACnC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAA;QAElC,MAAM,iBAAiB,GAAG,IAAI,wCAAiB,EAAE,CAAA;QACjD,8BAA8B;QAC9B,OAAO;YACL,iBAAiB,EAAE,IAAI;YACvB,WAAW,EAAE,UAAU;YACvB,UAAU;YACV,iBAAiB;YACjB,eAAe,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI;SACnF,CAAA;IACH,CAAC;IAES,iBAAiB,CAAC,UAAsB;QAChD,IAAI,CAAC,OAAO,CAAC,IAAI,CACf,iBAAiB,UAAU,CAAC,OAAO,UAAU,IAAA,8BAAO,EAAC,UAAU,CAAC,KAAK,CAAC;aACnE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC;aACjB,IAAI,CAAC,IAAI,CAAC,GAAG,CACjB,CAAA;QACD,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAA;IAC3C,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,oBAAuC,IAAI,wCAAiB,EAAE;QAC3E,MAAM,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAAA;QACxD,IAAI,qBAAqB,IAAI,IAAI,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;YACpD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;YACzB,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC9B,CAAC;QAED,IAAI,IAAI,CAAC,eAAe,IAAI,IAAI,EAAE,CAAC;YACjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAA;YAC7D,OAAO,IAAI,CAAC,eAAe,CAAA;QAC7B,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CACf,2BAA2B,IAAA,8BAAO,EAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC;aACjE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC;aACjB,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAA;QACD,MAAM,YAAY,GAAG,CAAC,CAAQ,EAAS,EAAE;YACvC,2FAA2F;YAC3F,IAAI,CAAC,CAAC,CAAC,YAAY,wCAAiB,CAAC,EAAE,CAAC;gBACtC,IAAI,CAAC;oBACH,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;gBACvB,CAAC;gBAAC,OAAO,WAAgB,EAAE,CAAC;oBAC1B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,gCAAgC,WAAW,CAAC,KAAK,IAAI,WAAW,EAAE,CAAC,CAAA;gBACvF,CAAC;YACH,CAAC;YAED,OAAO,CAAC,CAAA;QACV,CAAC,CAAA;QAED,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAC;YAC3C,qBAAqB;YACrB,cAAc,EAAE,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,QAAQ,CAAC;YAC1E,iBAAiB;YACjB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;YAC7C,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;SAC9D,CAAC;aACC,KAAK,CAAC,CAAC,CAAM,EAAE,EAAE;YAChB,MAAM,YAAY,CAAC,CAAC,CAAC,CAAA;QACvB,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;QAC7B,CAAC,CAAC,CAAA;QAEJ,OAAO,IAAI,CAAC,eAAe,CAAA;IAC7B,CAAC;IAES,aAAa,CAAC,CAAQ;QAC9B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;IAClD,CAAC;IAES,wBAAwB,CAAC,KAA4B;QAC7D,IAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,KAAK,CAAC,CAAA;IACrC,CAAC;IAiBO,KAAK,CAAC,gBAAgB;QAC5B,IAAI,IAAI,CAAC,oBAAoB,IAAI,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAA;QAC1D,CAAC;QACD,OAAO,IAAA,cAAI,EAAC,MAAM,IAAA,mBAAQ,EAAC,IAAI,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAAA;IACjE,CAAC;IAEO,qBAAqB,CAAC,QAAuB;QACnD,MAAM,wBAAwB,GAAG,QAAQ,CAAC,wBAAwB,CAAA;QAClE,IAAI,wBAAwB,IAAI,IAAI,EAAE,CAAC;YACrC,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAA;YAC1C,OAAO,cAAc,IAAI,IAAI;gBAC3B,CAAC,CAAC,wBAAwB;gBAC1B,CAAC,CAAC;oBACE,GAAG,wBAAwB;oBAC3B,GAAG,cAAc;iBAClB,CAAA;QACP,CAAC;QACD,OAAO,IAAI,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;IACpD,CAAC;IAEO,KAAK,CAAC,wBAAwB;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;QAC3D,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YACxC,IAAI,2BAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnB,OAAO,EAAE,CAAA;YACX,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,yDAAyD,EAAE,EAAE,CAAC,CAAA;YAClF,CAAC;QACH,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACxB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,wDAAwD,CAAC,EAAE,CAAC,CAAA;YAChF,CAAC;QACH,CAAC;QAED,MAAM,EAAE,GAAG,2BAAI,CAAC,EAAE,CAAC,IAAA,oBAAW,EAAC,IAAI,CAAC,EAAE,2BAAI,CAAC,GAAG,CAAC,CAAA;QAC/C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,kCAAkC,EAAE,EAAE,CAAC,CAAA;QACzD,IAAI,CAAC;YACH,MAAM,IAAA,qBAAU,EAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QAC5B,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,uCAAuC,CAAC,EAAE,CAAC,CAAA;QAC/D,CAAC;QACD,OAAO,EAAE,CAAA;IACX,CAAC;IAED,gBAAgB;IAChB,IAAI,iBAAiB;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAA;QACnC,oEAAoE;QACpE,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,OAAO,IAAI,CAAA;QACb,CAAC;QAED,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9C,MAAM,CAAC,GAAG,UAAU,CAAC,WAAW,EAAE,CAAA;YAClC,IAAI,CAAC,KAAK,eAAe,IAAI,CAAC,KAAK,eAAe,EAAE,CAAC;gBACnD,OAAO,KAAK,CAAA;YACd,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAQO,KAAK,CAAC,yBAAyB;QACrC,IAAI,MAAM,GAAG,IAAI,CAAC,sBAAsB,CAAA;QACxC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,mBAAmB,CAAA;YACnE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAA;YAC3B,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;gBACpB,MAAM,CAAC,KAAK,CAAC,+GAA+G,CAAC,CAAA;YAC/H,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAC5E,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;gBACzB,MAAM,CAAC,KAAK,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAA;YAChD,CAAC;YAED,MAAM,GAAG,IAAI,+CAAsB,CAAC,QAAQ,CAAC,CAAA;YAC7C,IAAI,CAAC,sBAAsB,GAAG,MAAM,CAAA;QACtC,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAES,KAAK,CAAC,eAAe,CAAC,WAAiC;QAC/D,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAA;QACrC,MAAM,eAAe,GAAoB;YACvC,OAAO,EAAE,WAAW,CAAC,qBAAqB,CAAC,cAAc;YACzD,iBAAiB,EAAE,WAAW,CAAC,qBAAqB,CAAC,iBAAiB;YACtE,IAAI,EAAG,QAAQ,CAAC,IAAY,CAAC,IAAI;YACjC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM;SAC7B,CAAA;QAED,IAAI,IAAI,CAAC,aAAa,CAAC,yBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,eAAe,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,EAAE,CAAC,CAAA;QACrE,CAAC;QAED,MAAM,UAAU,GAAG,WAAW,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,IAAI,CAAA;QAC/E,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAA;QAClC,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;QAExC,SAAS,sBAAsB;YAC7B,0CAA0C;YAC1C,MAAM,OAAO,GAAG,kBAAkB,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YACrE,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,aAAa,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC;gBAClF,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;YAC/B,CAAC;iBAAM,CAAC;gBACN,kFAAkF;gBAClF,kDAAkD;gBAClD,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACrD,CAAC;QACH,CAAC;QAED,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,yBAAyB,EAAE,CAAA;QACrE,MAAM,QAAQ,GAAG,sBAAsB,CAAC,wBAAwB,CAAA;QAChE,MAAM,IAAA,gBAAK,EAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC1C,MAAM,cAAc,GAAG,sBAAsB,EAAE,CAAA;QAC/C,IAAI,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;QACpD,MAAM,WAAW,GAAG,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC,CAAA;QAEpI,MAAM,IAAI,GAAG,KAAK,EAAE,WAAoB,EAAE,EAAE;YAC1C,MAAM,sBAAsB,CAAC,iBAAiB,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,CAAC,CAAA;YAC1H,MAAM,WAAW,CAAC,IAAK,CAAC;gBACtB,GAAG,UAAU;gBACb,cAAc,EAAE,UAAU;aAC3B,CAAC,CAAA;YACF,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAA;YACnE,IAAI,MAAM,IAAA,qBAAU,EAAC,mBAAmB,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAA,mBAAQ,EAAC,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAA;YACrG,CAAC;YACD,OAAO,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;QACvE,CAAC,CAAA;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAA;QACxB,MAAM,gBAAgB,GAAG,MAAM,sBAAsB,CAAC,sBAAsB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;QACnH,IAAI,gBAAgB,IAAI,IAAI,EAAE,CAAC;YAC7B,UAAU,GAAG,gBAAgB,CAAA;YAC7B,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,CAAA;QAC1B,CAAC;QAED,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;YACjC,MAAM,sBAAsB,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;gBAC9C,SAAS;YACX,CAAC,CAAC,CAAA;YACF,OAAO,MAAM,IAAA,iBAAM,EAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBACzC,SAAS;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;QAED,MAAM,cAAc,GAAG,MAAM,IAAA,6CAAoB,EAAC,QAAQ,cAAc,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;QAC1F,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,CAAC,CAAA;YACrF,MAAM,IAAA,4BAAK,EAAC,GAAG,EAAE,CAAC,IAAA,iBAAM,EAAC,cAAc,EAAE,UAAU,CAAC,EAAE;gBACpD,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,GAAG;gBACb,WAAW,EAAE,CAAC,KAAY,EAAE,EAAE;oBAC5B,IAAI,KAAK,YAAY,KAAK,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;wBAC5D,OAAO,IAAI,CAAA;oBACb,CAAC;oBACD,GAAG,CAAC,IAAI,CAAC,0CAA0C,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;oBAClF,OAAO,KAAK,CAAA;gBACd,CAAC;aACF,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,MAAM,eAAe,EAAE,CAAA;YAEvB,IAAI,CAAC,YAAY,wCAAiB,EAAE,CAAC;gBACnC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;gBACrB,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAA;YAC3C,CAAC;YACD,MAAM,CAAC,CAAA;QACT,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,eAAe,OAAO,2BAA2B,UAAU,EAAE,CAAC,CAAA;QACvE,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IACS,KAAK,CAAC,6BAA6B,CAC3C,QAAgC,EAChC,qBAA4C,EAC5C,aAAqB,EACrB,QAAuB,EACvB,oBAA4B;QAE5B,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,gBAAgB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,yBAAyB,EAAE,CAAC;gBACtF,OAAO,IAAI,CAAA;YACb,CAAC;YACD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,qBAAqB,CAAC,QAAQ,CAAA;YACrE,MAAM,gBAAgB,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CACtD,QAAQ,CAAC,GAAG,EACZ,IAAI,CAAC,GAAG,CAAC,OAAO,EAChB,qBAAqB,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,EACxD,IAAI,CAAC,+BAA+B,CACrC,CAAA;YACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,8BAA8B,gBAAgB,CAAC,CAAC,CAAC,WAAW,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;YAErG,MAAM,gBAAgB,GAAG,KAAK,EAAE,GAAQ,EAAqB,EAAE;gBAC7D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,GAAG,EAAE;oBACzD,OAAO,EAAE,qBAAqB,CAAC,cAAc;oBAC7C,iBAAiB,EAAE,qBAAqB,CAAC,iBAAiB;iBAC3D,CAAC,CAAA;gBAEF,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACtC,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,IAAI,YAAY,CAAC,CAAA;gBACpD,CAAC;gBAED,IAAI,CAAC;oBACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAU,EAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;gBAChD,CAAC;gBAAC,OAAO,CAAM,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,IAAI,aAAa,CAAC,EAAE,CAAC,CAAA;gBACrE,CAAC;YACH,CAAC,CAAA;YAED,MAAM,eAAe,GAAkC;gBACrD,MAAM,EAAE,QAAQ,CAAC,GAAG;gBACpB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAuB,CAAC,QAAQ,EAAE,oBAAoB,CAAC;gBAC/E,MAAM,EAAE,IAAI,CAAC,OAAO;gBACpB,OAAO,EAAE,aAAa;gBACtB,yBAAyB,EAAE,QAAQ,CAAC,yBAAyB;gBAC7D,cAAc,EAAE,qBAAqB,CAAC,cAAc;gBACpD,iBAAiB,EAAE,qBAAqB,CAAC,iBAAiB;aAC3D,CAAA;YAED,IAAI,IAAI,CAAC,aAAa,CAAC,yBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9C,eAAe,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,EAAE,CAAC,CAAA;YACrE,CAAC;YAED,MAAM,sBAAsB,GAAG,KAAK,EAAE,YAAsB,EAAE,QAAgB,EAAE,EAAE;gBAChF,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAA;gBAC5D,MAAM,IAAA,qBAAU,EAAC,YAAY,EAAE,IAAA,eAAQ,EAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;YACxE,CAAC,CAAA;YAED,MAAM,uBAAuB,GAAG,KAAK,EAAE,QAAgB,EAAE,EAAE;gBACzD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAA;gBAC5D,IAAI,CAAC;oBACH,IAAI,MAAM,IAAA,qBAAU,EAAC,YAAY,CAAC,EAAE,CAAC;wBACnC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAU,EAAC,MAAM,IAAA,mBAAQ,EAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;oBACxE,CAAC;gBACH,CAAC;gBAAC,OAAO,CAAM,EAAE,CAAC;oBAChB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,0BAA0B,YAAY,aAAa,CAAC,EAAE,CAAC,CAAA;gBAC3E,CAAC;gBACD,OAAO,IAAI,CAAA;YACb,CAAC,CAAA;YAED,MAAM,eAAe,GAAG,MAAM,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAA;YACnE,MAAM,sBAAsB,CAAC,eAAe,EAAE,IAAI,CAAC,sBAAuB,CAAC,wBAAwB,CAAC,CAAA;YAEpG,mEAAmE;YACnE,IAAI,eAAe,GAAG,MAAM,uBAAuB,CAAC,IAAI,CAAC,sBAAuB,CAAC,QAAQ,CAAC,CAAA;YAC1F,IAAI,eAAe,IAAI,IAAI,EAAE,CAAC;gBAC5B,eAAe,GAAG,MAAM,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAA;YAC/D,CAAC;YAED,MAAM,IAAI,6DAA6B,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC,CAAA;YACrI,OAAO,KAAK,CAAA;QACd,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC,CAAA;YAChG,IAAI,IAAI,CAAC,gBAAgB,IAAI,IAAI,EAAE,CAAC;gBAClC,YAAY;gBACZ,MAAM,CAAC,CAAA;YACT,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;CACF;AAr0BD,gCAq0BC;AAUD,SAAS,uBAAuB,CAAC,OAAe;IAC9C,MAAM,0BAA0B,GAAG,IAAA,mBAA4B,EAAC,OAAO,CAAC,CAAA;IACxE,OAAO,0BAA0B,IAAI,IAAI,IAAI,0BAA0B,CAAC,MAAM,GAAG,CAAC,CAAA;AACpF,CAAC;AAED,eAAe;AACf,MAAa,UAAU;IACrB,6DAA6D;IAC7D,IAAI,CAAC,OAAa;QAChB,SAAS;IACX,CAAC;IAED,6DAA6D;IAC7D,IAAI,CAAC,OAAa;QAChB,SAAS;IACX,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,OAAa;QACjB,SAAS;IACX,CAAC;CACF;AAfD,gCAeC","sourcesContent":["import {\n  AllPublishOptions,\n  asArray,\n  CancellationToken,\n  newError,\n  PublishConfiguration,\n  UpdateInfo,\n  UUID,\n  DownloadOptions,\n  CancellationError,\n  ProgressInfo,\n  BlockMap,\n  retry,\n} from \"builder-util-runtime\"\nimport { randomBytes } from \"crypto\"\nimport { release } from \"os\"\nimport { EventEmitter } from \"events\"\nimport { mkdir, outputFile, readFile, rename, unlink, copyFile, pathExists } from \"fs-extra\"\nimport { OutgoingHttpHeaders } from \"http\"\nimport { load } from \"js-yaml\"\nimport { Lazy } from \"lazy-val\"\nimport * as path from \"path\"\nimport { eq as isVersionsEqual, gt as isVersionGreaterThan, lt as isVersionLessThan, parse as parseVersion, prerelease as getVersionPreleaseComponents, SemVer } from \"semver\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { createTempUpdateFile, DownloadedUpdateHelper } from \"./DownloadedUpdateHelper\"\nimport { ElectronAppAdapter } from \"./ElectronAppAdapter\"\nimport { ElectronHttpExecutor, getNetSession, LoginCallback } from \"./electronHttpExecutor\"\nimport { GenericProvider } from \"./providers/GenericProvider\"\nimport { createClient, isUrlProbablySupportMultiRangeRequests } from \"./providerFactory\"\nimport { Provider, ProviderPlatform } from \"./providers/Provider\"\nimport type { TypedEmitter } from \"tiny-typed-emitter\"\nimport Session = Electron.Session\nimport type { AuthInfo } from \"electron\"\nimport { gunzipSync, gzipSync } from \"zlib\"\nimport { DifferentialDownloaderOptions } from \"./differentialDownloader/DifferentialDownloader\"\nimport { GenericDifferentialDownloader } from \"./differentialDownloader/GenericDifferentialDownloader\"\nimport { DOWNLOAD_PROGRESS, Logger, ResolvedUpdateFileInfo, UPDATE_DOWNLOADED, UpdateCheckResult, UpdateDownloadedEvent, UpdaterSignal } from \"./types\"\nimport { VerifyUpdateSupport } from \"./main\"\n\nexport type AppUpdaterEvents = {\n  error: (error: Error, message?: string) => void\n  login: (info: AuthInfo, callback: LoginCallback) => void\n  \"checking-for-update\": () => void\n  \"update-not-available\": (info: UpdateInfo) => void\n  \"update-available\": (info: UpdateInfo) => void\n  \"update-downloaded\": (event: UpdateDownloadedEvent) => void\n  \"download-progress\": (info: ProgressInfo) => void\n  \"update-cancelled\": (info: UpdateInfo) => void\n  \"appimage-filename-updated\": (path: string) => void\n}\n\nexport abstract class AppUpdater extends (EventEmitter as new () => TypedEmitter<AppUpdaterEvents>) {\n  /**\n   * Whether to automatically download an update when it is found.\n   * @default true\n   */\n  autoDownload = true\n\n  /**\n   * Whether to automatically install a downloaded update on app quit (if `quitAndInstall` was not called before).\n   * @default true\n   */\n  autoInstallOnAppQuit = true\n\n  /**\n   * Whether to run the app after finish install when run the installer is NOT in silent mode.\n   * @default true\n   */\n  autoRunAppAfterInstall = true\n\n  /**\n   * *GitHub provider only.* Whether to allow update to pre-release versions. Defaults to `true` if application version contains prerelease components (e.g. `0.12.1-alpha.1`, here `alpha` is a prerelease component), otherwise `false`.\n   *\n   * If `true`, downgrade will be allowed (`allowDowngrade` will be set to `true`).\n   */\n  allowPrerelease = false\n\n  /**\n   * *GitHub provider only.* Get all release notes (from current version to latest), not just the latest.\n   * @default false\n   */\n  fullChangelog = false\n\n  /**\n   * Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel).\n   *\n   * Taken in account only if channel differs (pre-release version component in terms of semantic versioning).\n   *\n   * @default false\n   */\n  allowDowngrade = false\n\n  /**\n   * Web installer files might not have signature verification, this switch prevents to load them unless it is needed.\n   *\n   * Currently false to prevent breaking the current API, but it should be changed to default true at some point that\n   * breaking changes are allowed.\n   *\n   * @default false\n   */\n  disableWebInstaller = false\n\n  /**\n   * *NSIS only* Disable differential downloads and always perform full download of installer.\n   *\n   * @default false\n   */\n  disableDifferentialDownload = false\n\n  /**\n   * Allows developer to force the updater to work in \"dev\" mode, looking for \"dev-app-update.yml\" instead of \"app-update.yml\"\n   * Dev: `path.join(this.app.getAppPath(), \"dev-app-update.yml\")`\n   * Prod: `path.join(process.resourcesPath!, \"app-update.yml\")`\n   *\n   * @default false\n   */\n  forceDevUpdateConfig = false\n\n  /**\n   * The base URL of the old block map file.\n   *\n   * When null, the updater will use the base URL of the update file to download the update.\n   * When set, the updater will use this string as the base URL of the old block map file.\n   * Some servers like github cannot download the old block map file from latest release,\n   * so you need to compute the old block map file base URL manually.\n   *\n   * @default null\n   */\n  public previousBlockmapBaseUrlOverride: string | null = null\n\n  /**\n   * The current application version.\n   */\n  readonly currentVersion: SemVer\n\n  private _channel: string | null = null\n\n  protected downloadedUpdateHelper: DownloadedUpdateHelper | null = null\n\n  /**\n   * Get the update channel. Doesn't return `channel` from the update configuration, only if was previously set.\n   */\n  get channel(): string | null {\n    return this._channel\n  }\n\n  /**\n   * Set the update channel. Overrides `channel` in the update configuration.\n   *\n   * `allowDowngrade` will be automatically set to `true`. If this behavior is not suitable for you, simple set `allowDowngrade` explicitly after.\n   */\n  set channel(value: string | null) {\n    if (this._channel != null) {\n      // noinspection SuspiciousTypeOfGuard\n      if (typeof value !== \"string\") {\n        throw newError(`Channel must be a string, but got: ${value}`, \"ERR_UPDATER_INVALID_CHANNEL\")\n      } else if (value.length === 0) {\n        throw newError(`Channel must be not an empty string`, \"ERR_UPDATER_INVALID_CHANNEL\")\n      }\n    }\n\n    this._channel = value\n    this.allowDowngrade = true\n  }\n\n  /**\n   *  The request headers.\n   */\n  requestHeaders: OutgoingHttpHeaders | null = null\n\n  /**\n   *  Shortcut for explicitly adding auth tokens to request headers\n   */\n  addAuthHeader(token: string) {\n    this.requestHeaders = Object.assign({}, this.requestHeaders, {\n      authorization: token,\n    })\n  }\n\n  protected _logger: Logger = console\n\n  // noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n  get netSession(): Session {\n    return getNetSession()\n  }\n\n  /**\n   * The logger. You can pass [electron-log](https://github.com/megahertz/electron-log), [winston](https://github.com/winstonjs/winston) or another logger with the following interface: `{ info(), warn(), error() }`.\n   * Set it to `null` if you would like to disable a logging feature.\n   */\n  get logger(): Logger | null {\n    return this._logger\n  }\n\n  set logger(value: Logger | null) {\n    this._logger = value == null ? new NoOpLogger() : value\n  }\n\n  // noinspection JSUnusedGlobalSymbols\n  /**\n   * For type safety you can use signals, e.g. `autoUpdater.signals.updateDownloaded(() => {})` instead of `autoUpdater.on('update-available', () => {})`\n   */\n  readonly signals = new UpdaterSignal(this)\n\n  private _appUpdateConfigPath: string | null = null\n\n  // noinspection JSUnusedGlobalSymbols\n  /**\n   * test only\n   * @private\n   */\n  set updateConfigPath(value: string | null) {\n    this.clientPromise = null\n    this._appUpdateConfigPath = value\n    this.configOnDisk = new Lazy<any>(() => this.loadUpdateConfig())\n  }\n\n  protected _isUpdateSupported: VerifyUpdateSupport = updateInfo => this.checkIfUpdateSupported(updateInfo)\n\n  /**\n   * Allows developer to override default logic for determining if an update is supported.\n   * The default logic compares the `UpdateInfo` minimum system version against the `os.release()` with `semver` package\n   */\n  get isUpdateSupported(): VerifyUpdateSupport {\n    return this._isUpdateSupported\n  }\n\n  set isUpdateSupported(value: VerifyUpdateSupport) {\n    if (value) {\n      this._isUpdateSupported = value\n    }\n  }\n\n  protected _isUserWithinRollout: VerifyUpdateSupport = updateInfo => this.isStagingMatch(updateInfo)\n\n  /**\n   * Allows developer to override default logic for determining if the user is below the rollout threshold.\n   * The default logic compares the staging percentage with numerical representation of user ID.\n   * An override can define custom logic, or bypass it if needed.\n   */\n  get isUserWithinRollout(): VerifyUpdateSupport {\n    return this._isUserWithinRollout\n  }\n\n  set isUserWithinRollout(value: VerifyUpdateSupport) {\n    if (value) {\n      this._isUserWithinRollout = value\n    }\n  }\n\n  private clientPromise: Promise<Provider<any>> | null = null\n\n  protected readonly stagingUserIdPromise = new Lazy<string>(() => this.getOrCreateStagingUserId())\n\n  // public, allow to read old config for anyone\n  /** @internal */\n  configOnDisk = new Lazy<any>(() => this.loadUpdateConfig())\n\n  private checkForUpdatesPromise: Promise<UpdateCheckResult> | null = null\n  private downloadPromise: Promise<Array<string>> | null = null\n\n  protected readonly app: AppAdapter\n\n  protected updateInfoAndProvider: UpdateInfoAndProvider | null = null\n\n  /** @internal */\n  readonly httpExecutor: ElectronHttpExecutor\n\n  protected constructor(options: AllPublishOptions | null | undefined, app?: AppAdapter) {\n    super()\n\n    this.on(\"error\", (error: Error) => {\n      this._logger.error(`Error: ${error.stack || error.message}`)\n    })\n\n    if (app == null) {\n      this.app = new ElectronAppAdapter()\n      this.httpExecutor = new ElectronHttpExecutor((authInfo, callback) => this.emit(\"login\", authInfo, callback))\n    } else {\n      this.app = app\n      this.httpExecutor = null as any\n    }\n\n    const currentVersionString = this.app.version\n    const currentVersion = parseVersion(currentVersionString)\n    if (currentVersion == null) {\n      throw newError(`App version is not a valid semver version: \"${currentVersionString}\"`, \"ERR_UPDATER_INVALID_VERSION\")\n    }\n    this.currentVersion = currentVersion\n    this.allowPrerelease = hasPrereleaseComponents(currentVersion)\n\n    if (options != null) {\n      this.setFeedURL(options)\n\n      if (typeof options !== \"string\" && options.requestHeaders) {\n        this.requestHeaders = options.requestHeaders\n      }\n    }\n  }\n\n  //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n  getFeedURL(): string | null | undefined {\n    return \"Deprecated. Do not use it.\"\n  }\n\n  /**\n   * Configure update provider. If value is `string`, [GenericServerOptions](https://www.electron.build/publish#genericserveroptions) will be set with value as `url`.\n   * @param options If you want to override configuration in the `app-update.yml`.\n   */\n  setFeedURL(options: PublishConfiguration | AllPublishOptions | string) {\n    const runtimeOptions = this.createProviderRuntimeOptions()\n    // https://github.com/electron-userland/electron-builder/issues/1105\n    let provider: Provider<any>\n    if (typeof options === \"string\") {\n      provider = new GenericProvider({ provider: \"generic\", url: options }, this, {\n        ...runtimeOptions,\n        isUseMultipleRangeRequest: isUrlProbablySupportMultiRangeRequests(options),\n      })\n    } else {\n      provider = createClient(options, this, runtimeOptions)\n    }\n    this.clientPromise = Promise.resolve(provider)\n  }\n\n  /**\n   * Asks the server whether there is an update.\n   * @returns null if the updater is disabled, otherwise info about the latest version\n   */\n  checkForUpdates(): Promise<UpdateCheckResult | null> {\n    if (!this.isUpdaterActive()) {\n      return Promise.resolve(null)\n    }\n\n    let checkForUpdatesPromise = this.checkForUpdatesPromise\n    if (checkForUpdatesPromise != null) {\n      this._logger.info(\"Checking for update (already in progress)\")\n      return checkForUpdatesPromise\n    }\n\n    const nullizePromise = () => (this.checkForUpdatesPromise = null)\n\n    this._logger.info(\"Checking for update\")\n    checkForUpdatesPromise = this.doCheckForUpdates()\n      .then(it => {\n        nullizePromise()\n        return it\n      })\n      .catch((e: any) => {\n        nullizePromise()\n        this.emit(\"error\", e, `Cannot check for updates: ${(e.stack || e).toString()}`)\n        throw e\n      })\n\n    this.checkForUpdatesPromise = checkForUpdatesPromise\n    return checkForUpdatesPromise\n  }\n\n  public isUpdaterActive(): boolean {\n    const isEnabled = this.app.isPackaged || this.forceDevUpdateConfig\n    if (!isEnabled) {\n      this._logger.info(\"Skip checkForUpdates because application is not packed and dev update config is not forced\")\n      return false\n    }\n    return true\n  }\n\n  // noinspection JSUnusedGlobalSymbols\n  checkForUpdatesAndNotify(downloadNotification?: DownloadNotification): Promise<UpdateCheckResult | null> {\n    return this.checkForUpdates().then(it => {\n      if (!it?.downloadPromise) {\n        if (this._logger.debug != null) {\n          this._logger.debug(\"checkForUpdatesAndNotify called, downloadPromise is null\")\n        }\n        return it\n      }\n\n      void it.downloadPromise.then(() => {\n        const notificationContent = AppUpdater.formatDownloadNotification(it.updateInfo.version, this.app.name, downloadNotification)\n        new (require(\"electron\").Notification)(notificationContent).show()\n      })\n\n      return it\n    })\n  }\n\n  private static formatDownloadNotification(version: string, appName: string, downloadNotification?: DownloadNotification): DownloadNotification {\n    if (downloadNotification == null) {\n      downloadNotification = {\n        title: \"A new update is ready to install\",\n        body: `{appName} version {version} has been downloaded and will be automatically installed on exit`,\n      }\n    }\n    downloadNotification = {\n      title: downloadNotification.title.replace(\"{appName}\", appName).replace(\"{version}\", version),\n      body: downloadNotification.body.replace(\"{appName}\", appName).replace(\"{version}\", version),\n    }\n    return downloadNotification\n  }\n\n  private async isStagingMatch(updateInfo: UpdateInfo): Promise<boolean> {\n    const rawStagingPercentage = updateInfo.stagingPercentage\n    let stagingPercentage = rawStagingPercentage\n    if (stagingPercentage == null) {\n      return true\n    }\n\n    stagingPercentage = parseInt(stagingPercentage as any, 10)\n    if (isNaN(stagingPercentage)) {\n      this._logger.warn(`Staging percentage is NaN: ${rawStagingPercentage}`)\n      return true\n    }\n\n    // convert from user 0-100 to internal 0-1\n    stagingPercentage = stagingPercentage / 100\n\n    const stagingUserId = await this.stagingUserIdPromise.value\n    const val = UUID.parse(stagingUserId).readUInt32BE(12)\n    const percentage = val / 0xffffffff\n    this._logger.info(`Staging percentage: ${stagingPercentage}, percentage: ${percentage}, user id: ${stagingUserId}`)\n    return percentage < stagingPercentage\n  }\n\n  private computeFinalHeaders(headers: OutgoingHttpHeaders) {\n    if (this.requestHeaders != null) {\n      Object.assign(headers, this.requestHeaders)\n    }\n    return headers\n  }\n\n  private async isUpdateAvailable(updateInfo: UpdateInfo): Promise<boolean> {\n    const latestVersion = parseVersion(updateInfo.version)\n    if (latestVersion == null) {\n      throw newError(\n        `This file could not be downloaded, or the latest version (from update server) does not have a valid semver version: \"${updateInfo.version}\"`,\n        \"ERR_UPDATER_INVALID_VERSION\"\n      )\n    }\n\n    const currentVersion = this.currentVersion\n    if (isVersionsEqual(latestVersion, currentVersion)) {\n      return false\n    }\n\n    if (!(await Promise.resolve(this.isUpdateSupported(updateInfo)))) {\n      return false\n    }\n\n    const isUserWithinRollout = await Promise.resolve(this.isUserWithinRollout(updateInfo))\n    if (!isUserWithinRollout) {\n      return false\n    }\n\n    // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405033227\n    // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405030797\n    const isLatestVersionNewer = isVersionGreaterThan(latestVersion, currentVersion)\n    const isLatestVersionOlder = isVersionLessThan(latestVersion, currentVersion)\n\n    if (isLatestVersionNewer) {\n      return true\n    }\n    return this.allowDowngrade && isLatestVersionOlder\n  }\n\n  private checkIfUpdateSupported(updateInfo: UpdateInfo) {\n    const minimumSystemVersion = updateInfo?.minimumSystemVersion\n    const currentOSVersion = release()\n    if (minimumSystemVersion) {\n      try {\n        if (isVersionLessThan(currentOSVersion, minimumSystemVersion)) {\n          this._logger.info(`Current OS version ${currentOSVersion} is less than the minimum OS version required ${minimumSystemVersion} for version ${currentOSVersion}`)\n          return false\n        }\n      } catch (e: any) {\n        this._logger.warn(`Failed to compare current OS version(${currentOSVersion}) with minimum OS version(${minimumSystemVersion}): ${(e.message || e).toString()}`)\n      }\n    }\n    return true\n  }\n\n  protected async getUpdateInfoAndProvider(): Promise<UpdateInfoAndProvider> {\n    await this.app.whenReady()\n\n    if (this.clientPromise == null) {\n      this.clientPromise = this.configOnDisk.value.then(it => createClient(it, this, this.createProviderRuntimeOptions()))\n    }\n\n    const client = await this.clientPromise\n    const stagingUserId = await this.stagingUserIdPromise.value\n    client.setRequestHeaders(this.computeFinalHeaders({ \"x-user-staging-id\": stagingUserId }))\n    return {\n      info: await client.getLatestVersion(),\n      provider: client,\n    }\n  }\n\n  private createProviderRuntimeOptions() {\n    return {\n      isUseMultipleRangeRequest: true,\n      platform: this._testOnlyOptions == null ? (process.platform as ProviderPlatform) : this._testOnlyOptions.platform,\n      executor: this.httpExecutor,\n    }\n  }\n\n  private async doCheckForUpdates(): Promise<UpdateCheckResult> {\n    this.emit(\"checking-for-update\")\n\n    const result = await this.getUpdateInfoAndProvider()\n    const updateInfo = result.info\n    if (!(await this.isUpdateAvailable(updateInfo))) {\n      this._logger.info(\n        `Update for version ${this.currentVersion.format()} is not available (latest version: ${updateInfo.version}, downgrade is ${\n          this.allowDowngrade ? \"allowed\" : \"disallowed\"\n        }).`\n      )\n      this.emit(\"update-not-available\", updateInfo)\n      return {\n        isUpdateAvailable: false,\n        versionInfo: updateInfo,\n        updateInfo,\n      }\n    }\n\n    this.updateInfoAndProvider = result\n    this.onUpdateAvailable(updateInfo)\n\n    const cancellationToken = new CancellationToken()\n    //noinspection ES6MissingAwait\n    return {\n      isUpdateAvailable: true,\n      versionInfo: updateInfo,\n      updateInfo,\n      cancellationToken,\n      downloadPromise: this.autoDownload ? this.downloadUpdate(cancellationToken) : null,\n    }\n  }\n\n  protected onUpdateAvailable(updateInfo: UpdateInfo): void {\n    this._logger.info(\n      `Found version ${updateInfo.version} (url: ${asArray(updateInfo.files)\n        .map(it => it.url)\n        .join(\", \")})`\n    )\n    this.emit(\"update-available\", updateInfo)\n  }\n\n  /**\n   * Start downloading update manually. You can use this method if `autoDownload` option is set to `false`.\n   * @returns {Promise<Array<string>>} Paths to downloaded files.\n   */\n  downloadUpdate(cancellationToken: CancellationToken = new CancellationToken()): Promise<Array<string>> {\n    const updateInfoAndProvider = this.updateInfoAndProvider\n    if (updateInfoAndProvider == null) {\n      const error = new Error(\"Please check update first\")\n      this.dispatchError(error)\n      return Promise.reject(error)\n    }\n\n    if (this.downloadPromise != null) {\n      this._logger.info(\"Downloading update (already in progress)\")\n      return this.downloadPromise\n    }\n\n    this._logger.info(\n      `Downloading update from ${asArray(updateInfoAndProvider.info.files)\n        .map(it => it.url)\n        .join(\", \")}`\n    )\n    const errorHandler = (e: Error): Error => {\n      // https://github.com/electron-userland/electron-builder/issues/1150#issuecomment-436891159\n      if (!(e instanceof CancellationError)) {\n        try {\n          this.dispatchError(e)\n        } catch (nestedError: any) {\n          this._logger.warn(`Cannot dispatch error event: ${nestedError.stack || nestedError}`)\n        }\n      }\n\n      return e\n    }\n\n    this.downloadPromise = this.doDownloadUpdate({\n      updateInfoAndProvider,\n      requestHeaders: this.computeRequestHeaders(updateInfoAndProvider.provider),\n      cancellationToken,\n      disableWebInstaller: this.disableWebInstaller,\n      disableDifferentialDownload: this.disableDifferentialDownload,\n    })\n      .catch((e: any) => {\n        throw errorHandler(e)\n      })\n      .finally(() => {\n        this.downloadPromise = null\n      })\n\n    return this.downloadPromise\n  }\n\n  protected dispatchError(e: Error): void {\n    this.emit(\"error\", e, (e.stack || e).toString())\n  }\n\n  protected dispatchUpdateDownloaded(event: UpdateDownloadedEvent): void {\n    this.emit(UPDATE_DOWNLOADED, event)\n  }\n\n  protected abstract doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>>\n\n  /**\n   * Restarts the app and installs the update after it has been downloaded.\n   * It should only be called after `update-downloaded` has been emitted.\n   *\n   * **Note:** `autoUpdater.quitAndInstall()` will close all application windows first and only emit `before-quit` event on `app` after that.\n   * This is different from the normal quit event sequence.\n   *\n   * @param isSilent *windows-only* Runs the installer in silent mode. Defaults to `false`.\n   * @param isForceRunAfter Run the app after finish even on silent install. Not applicable for macOS.\n   * Ignored if `isSilent` is set to `false`(In this case you can still set `autoRunAppAfterInstall` to `false` to prevent run the app after finish).\n   */\n  abstract quitAndInstall(isSilent?: boolean, isForceRunAfter?: boolean): void\n\n  private async loadUpdateConfig(): Promise<any> {\n    if (this._appUpdateConfigPath == null) {\n      this._appUpdateConfigPath = this.app.appUpdateConfigPath\n    }\n    return load(await readFile(this._appUpdateConfigPath, \"utf-8\"))\n  }\n\n  private computeRequestHeaders(provider: Provider<any>): OutgoingHttpHeaders {\n    const fileExtraDownloadHeaders = provider.fileExtraDownloadHeaders\n    if (fileExtraDownloadHeaders != null) {\n      const requestHeaders = this.requestHeaders\n      return requestHeaders == null\n        ? fileExtraDownloadHeaders\n        : {\n            ...fileExtraDownloadHeaders,\n            ...requestHeaders,\n          }\n    }\n    return this.computeFinalHeaders({ accept: \"*/*\" })\n  }\n\n  private async getOrCreateStagingUserId(): Promise<string> {\n    const file = path.join(this.app.userDataPath, \".updaterId\")\n    try {\n      const id = await readFile(file, \"utf-8\")\n      if (UUID.check(id)) {\n        return id\n      } else {\n        this._logger.warn(`Staging user id file exists, but content was invalid: ${id}`)\n      }\n    } catch (e: any) {\n      if (e.code !== \"ENOENT\") {\n        this._logger.warn(`Couldn't read staging user ID, creating a blank one: ${e}`)\n      }\n    }\n\n    const id = UUID.v5(randomBytes(4096), UUID.OID)\n    this._logger.info(`Generated new staging user ID: ${id}`)\n    try {\n      await outputFile(file, id)\n    } catch (e: any) {\n      this._logger.warn(`Couldn't write out staging user ID: ${e}`)\n    }\n    return id\n  }\n\n  /** @internal */\n  get isAddNoCacheQuery(): boolean {\n    const headers = this.requestHeaders\n    // https://github.com/electron-userland/electron-builder/issues/3021\n    if (headers == null) {\n      return true\n    }\n\n    for (const headerName of Object.keys(headers)) {\n      const s = headerName.toLowerCase()\n      if (s === \"authorization\" || s === \"private-token\") {\n        return false\n      }\n    }\n    return true\n  }\n\n  /**\n   * @private\n   * @internal\n   */\n  _testOnlyOptions: TestOnlyUpdaterOptions | null = null\n\n  private async getOrCreateDownloadHelper(): Promise<DownloadedUpdateHelper> {\n    let result = this.downloadedUpdateHelper\n    if (result == null) {\n      const dirName = (await this.configOnDisk.value).updaterCacheDirName\n      const logger = this._logger\n      if (dirName == null) {\n        logger.error(\"updaterCacheDirName is not specified in app-update.yml Was app build using at least electron-builder 20.34.0?\")\n      }\n      const cacheDir = path.join(this.app.baseCachePath, dirName || this.app.name)\n      if (logger.debug != null) {\n        logger.debug(`updater cache dir: ${cacheDir}`)\n      }\n\n      result = new DownloadedUpdateHelper(cacheDir)\n      this.downloadedUpdateHelper = result\n    }\n    return result\n  }\n\n  protected async executeDownload(taskOptions: DownloadExecutorTask): Promise<Array<string>> {\n    const fileInfo = taskOptions.fileInfo\n    const downloadOptions: DownloadOptions = {\n      headers: taskOptions.downloadUpdateOptions.requestHeaders,\n      cancellationToken: taskOptions.downloadUpdateOptions.cancellationToken,\n      sha2: (fileInfo.info as any).sha2,\n      sha512: fileInfo.info.sha512,\n    }\n\n    if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n      downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n    }\n\n    const updateInfo = taskOptions.downloadUpdateOptions.updateInfoAndProvider.info\n    const version = updateInfo.version\n    const packageInfo = fileInfo.packageInfo\n\n    function getCacheUpdateFileName(): string {\n      // NodeJS URL doesn't decode automatically\n      const urlPath = decodeURIComponent(taskOptions.fileInfo.url.pathname)\n      if (urlPath.toLowerCase().endsWith(`.${taskOptions.fileExtension.toLowerCase()}`)) {\n        return path.basename(urlPath)\n      } else {\n        // url like /latest — use basename so a server-supplied path like \"../../etc/evil\"\n        // cannot escape the cache directory via path.join\n        return path.basename(taskOptions.fileInfo.info.url)\n      }\n    }\n\n    const downloadedUpdateHelper = await this.getOrCreateDownloadHelper()\n    const cacheDir = downloadedUpdateHelper.cacheDirForPendingUpdate\n    await mkdir(cacheDir, { recursive: true })\n    const updateFileName = getCacheUpdateFileName()\n    let updateFile = path.join(cacheDir, updateFileName)\n    const packageFile = packageInfo == null ? null : path.join(cacheDir, `package-${version}${path.extname(packageInfo.path) || \".7z\"}`)\n\n    const done = async (isSaveCache: boolean) => {\n      await downloadedUpdateHelper.setDownloadedFile(updateFile, packageFile, updateInfo, fileInfo, updateFileName, isSaveCache)\n      await taskOptions.done!({\n        ...updateInfo,\n        downloadedFile: updateFile,\n      })\n      const currentBlockMapFile = path.join(cacheDir, \"current.blockmap\")\n      if (await pathExists(currentBlockMapFile)) {\n        await copyFile(currentBlockMapFile, path.join(downloadedUpdateHelper.cacheDir, \"current.blockmap\"))\n      }\n      return packageFile == null ? [updateFile] : [updateFile, packageFile]\n    }\n\n    const log = this._logger\n    const cachedUpdateFile = await downloadedUpdateHelper.validateDownloadedPath(updateFile, updateInfo, fileInfo, log)\n    if (cachedUpdateFile != null) {\n      updateFile = cachedUpdateFile\n      return await done(false)\n    }\n\n    const removeFileIfAny = async () => {\n      await downloadedUpdateHelper.clear().catch(() => {\n        // ignore\n      })\n      return await unlink(updateFile).catch(() => {\n        // ignore\n      })\n    }\n\n    const tempUpdateFile = await createTempUpdateFile(`temp-${updateFileName}`, cacheDir, log)\n    try {\n      await taskOptions.task(tempUpdateFile, downloadOptions, packageFile, removeFileIfAny)\n      await retry(() => rename(tempUpdateFile, updateFile), {\n        retries: 60,\n        interval: 500,\n        shouldRetry: (error: Error) => {\n          if (error instanceof Error && /^EBUSY:/.test(error.message)) {\n            return true\n          }\n          log.warn(`Cannot rename temp file to final file: ${error.message || error.stack}`)\n          return false\n        },\n      })\n    } catch (e: any) {\n      await removeFileIfAny()\n\n      if (e instanceof CancellationError) {\n        log.info(\"cancelled\")\n        this.emit(\"update-cancelled\", updateInfo)\n      }\n      throw e\n    }\n\n    log.info(`New version ${version} has been downloaded to ${updateFile}`)\n    return await done(true)\n  }\n  protected async differentialDownloadInstaller(\n    fileInfo: ResolvedUpdateFileInfo,\n    downloadUpdateOptions: DownloadUpdateOptions,\n    installerPath: string,\n    provider: Provider<any>,\n    oldInstallerFileName: string\n  ): Promise<boolean> {\n    try {\n      if (this._testOnlyOptions != null && !this._testOnlyOptions.isUseDifferentialDownload) {\n        return true\n      }\n      const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n      const blockmapFileUrls = await provider.getBlockMapFiles(\n        fileInfo.url,\n        this.app.version,\n        downloadUpdateOptions.updateInfoAndProvider.info.version,\n        this.previousBlockmapBaseUrlOverride\n      )\n      this._logger.info(`Download block maps (old: \"${blockmapFileUrls[0]}\", new: ${blockmapFileUrls[1]})`)\n\n      const downloadBlockMap = async (url: URL): Promise<BlockMap> => {\n        const data = await this.httpExecutor.downloadToBuffer(url, {\n          headers: downloadUpdateOptions.requestHeaders,\n          cancellationToken: downloadUpdateOptions.cancellationToken,\n        })\n\n        if (data == null || data.length === 0) {\n          throw new Error(`Blockmap \"${url.href}\" is empty`)\n        }\n\n        try {\n          return JSON.parse(gunzipSync(data).toString())\n        } catch (e: any) {\n          throw new Error(`Cannot parse blockmap \"${url.href}\", error: ${e}`)\n        }\n      }\n\n      const downloadOptions: DifferentialDownloaderOptions = {\n        newUrl: fileInfo.url,\n        oldFile: path.join(this.downloadedUpdateHelper!.cacheDir, oldInstallerFileName),\n        logger: this._logger,\n        newFile: installerPath,\n        isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,\n        requestHeaders: downloadUpdateOptions.requestHeaders,\n        cancellationToken: downloadUpdateOptions.cancellationToken,\n      }\n\n      if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n        downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n      }\n\n      const saveBlockMapToCacheDir = async (blockMapData: BlockMap, cacheDir: string) => {\n        const blockMapFile = path.join(cacheDir, \"current.blockmap\")\n        await outputFile(blockMapFile, gzipSync(JSON.stringify(blockMapData)))\n      }\n\n      const getBlockMapFromCacheDir = async (cacheDir: string) => {\n        const blockMapFile = path.join(cacheDir, \"current.blockmap\")\n        try {\n          if (await pathExists(blockMapFile)) {\n            return JSON.parse(gunzipSync(await readFile(blockMapFile)).toString())\n          }\n        } catch (e: any) {\n          this._logger.warn(`Cannot parse blockmap \"${blockMapFile}\", error: ${e}`)\n        }\n        return null\n      }\n\n      const newBlockMapData = await downloadBlockMap(blockmapFileUrls[1])\n      await saveBlockMapToCacheDir(newBlockMapData, this.downloadedUpdateHelper!.cacheDirForPendingUpdate)\n\n      // get old blockmap from cache dir first, if not found, download it\n      let oldBlockMapData = await getBlockMapFromCacheDir(this.downloadedUpdateHelper!.cacheDir)\n      if (oldBlockMapData == null) {\n        oldBlockMapData = await downloadBlockMap(blockmapFileUrls[0])\n      }\n\n      await new GenericDifferentialDownloader(fileInfo.info, this.httpExecutor, downloadOptions).download(oldBlockMapData, newBlockMapData)\n      return false\n    } catch (e: any) {\n      this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`)\n      if (this._testOnlyOptions != null) {\n        // test mode\n        throw e\n      }\n      return true\n    }\n  }\n}\n\nexport interface DownloadUpdateOptions {\n  readonly updateInfoAndProvider: UpdateInfoAndProvider\n  readonly requestHeaders: OutgoingHttpHeaders\n  readonly cancellationToken: CancellationToken\n  readonly disableWebInstaller?: boolean\n  readonly disableDifferentialDownload?: boolean\n}\n\nfunction hasPrereleaseComponents(version: SemVer) {\n  const versionPrereleaseComponent = getVersionPreleaseComponents(version)\n  return versionPrereleaseComponent != null && versionPrereleaseComponent.length > 0\n}\n\n/** @private */\nexport class NoOpLogger implements Logger {\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  info(message?: any) {\n    // ignore\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  warn(message?: any) {\n    // ignore\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  error(message?: any) {\n    // ignore\n  }\n}\n\nexport interface UpdateInfoAndProvider {\n  info: UpdateInfo\n  provider: Provider<any>\n}\n\nexport interface DownloadExecutorTask {\n  readonly fileExtension: string\n  readonly fileInfo: ResolvedUpdateFileInfo\n  readonly downloadUpdateOptions: DownloadUpdateOptions\n  readonly task: (destinationFile: string, downloadOptions: DownloadOptions, packageFile: string | null, removeTempDirIfAny: () => Promise<any>) => Promise<any>\n\n  readonly done?: (event: UpdateDownloadedEvent) => Promise<any>\n}\n\nexport interface DownloadNotification {\n  body: string\n  title: string\n}\n\n/** @private */\nexport interface TestOnlyUpdaterOptions {\n  platform: ProviderPlatform\n\n  isUseDifferentialDownload?: boolean\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseUpdater = void 0;
const child_process_1 = require("child_process");
const path = require("path");
const AppUpdater_1 = require("./AppUpdater");
class BaseUpdater extends AppUpdater_1.AppUpdater {
    constructor(options, app) {
        super(options, app);
        this.quitAndInstallCalled = false;
        this.quitHandlerAdded = false;
    }
    quitAndInstall(isSilent = false, isForceRunAfter = false) {
        this._logger.info(`Install on explicit quitAndInstall`);
        // If NOT in silent mode use `autoRunAppAfterInstall` to determine whether to force run the app
        const isInstalled = this.install(isSilent, isSilent ? isForceRunAfter : this.autoRunAppAfterInstall);
        if (isInstalled) {
            setImmediate(() => {
                // this event is normally emitted when calling quitAndInstall, this emulates that
                require("electron").autoUpdater.emit("before-quit-for-update");
                this.app.quit();
            });
        }
        else {
            this.quitAndInstallCalled = false;
        }
    }
    executeDownload(taskOptions) {
        return super.executeDownload({
            ...taskOptions,
            done: event => {
                this.dispatchUpdateDownloaded(event);
                this.addQuitHandler();
                return Promise.resolve();
            },
        });
    }
    get installerPath() {
        return this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.file;
    }
    // must be sync (because quit even handler is not async)
    install(isSilent = false, isForceRunAfter = false) {
        if (this.quitAndInstallCalled) {
            this._logger.warn("install call ignored: quitAndInstallCalled is set to true");
            return false;
        }
        const downloadedUpdateHelper = this.downloadedUpdateHelper;
        const installerPath = this.installerPath;
        const downloadedFileInfo = downloadedUpdateHelper == null ? null : downloadedUpdateHelper.downloadedFileInfo;
        if (installerPath == null || downloadedFileInfo == null) {
            this.dispatchError(new Error("No update filepath provided, can't quit and install"));
            return false;
        }
        // prevent calling several times
        this.quitAndInstallCalled = true;
        try {
            this._logger.info(`Install: isSilent: ${isSilent}, isForceRunAfter: ${isForceRunAfter}`);
            return this.doInstall({
                isSilent,
                isForceRunAfter,
                isAdminRightsRequired: downloadedFileInfo.isAdminRightsRequired,
            });
        }
        catch (e) {
            this.dispatchError(e);
            return false;
        }
    }
    addQuitHandler() {
        if (this.quitHandlerAdded || !this.autoInstallOnAppQuit) {
            return;
        }
        this.quitHandlerAdded = true;
        this.app.onQuit(exitCode => {
            if (this.quitAndInstallCalled) {
                this._logger.info("Update installer has already been triggered. Quitting application.");
                return;
            }
            if (!this.autoInstallOnAppQuit) {
                this._logger.info("Update will not be installed on quit because autoInstallOnAppQuit is set to false.");
                return;
            }
            if (exitCode !== 0) {
                this._logger.info(`Update will be not installed on quit because application is quitting with exit code ${exitCode}`);
                return;
            }
            this._logger.info("Auto install update on quit");
            this.install(true, false);
        });
    }
    /**
     * Strips relative-path entries from a PATH string.
     * Prevents PATH-poisoning where a writable directory earlier in PATH shadows
     * a trusted package manager binary.
     */
    sanitizeEnvPath(envPath) {
        return envPath
            .split(path.delimiter)
            .filter((dir) => path.isAbsolute(dir))
            .join(path.delimiter);
    }
    spawnSyncLog(cmd, args = [], env = {}) {
        var _a;
        this._logger.info(`Executing: ${cmd} with args: ${args}`);
        const mergedEnv = { ...process.env, ...env };
        const response = (0, child_process_1.spawnSync)(cmd, args, {
            env: { ...mergedEnv, PATH: this.sanitizeEnvPath((_a = mergedEnv.PATH) !== null && _a !== void 0 ? _a : "") },
            encoding: "utf-8",
            shell: true,
        });
        const { error, status, stdout, stderr } = response;
        if (error != null) {
            this._logger.error(stderr);
            throw error;
        }
        else if (status != null && status !== 0) {
            this._logger.error(stderr);
            throw new Error(`Command ${cmd} exited with code ${status}`);
        }
        return stdout.trim();
    }
    /**
     * This handles both node 8 and node 10 way of emitting error when spawning a process
     *   - node 8: Throws the error
     *   - node 10: Emit the error(Need to listen with on)
     */
    // https://github.com/electron-userland/electron-builder/issues/1129
    // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors
    async spawnLog(cmd, args = [], env = undefined, stdio = "ignore") {
        this._logger.info(`Executing: ${cmd} with args: ${args}`);
        return new Promise((resolve, reject) => {
            try {
                const params = { stdio, env, detached: true };
                const p = (0, child_process_1.spawn)(cmd, args, params);
                p.on("error", error => {
                    reject(error);
                });
                p.unref();
                if (p.pid !== undefined) {
                    resolve(true);
                }
            }
            catch (error) {
                reject(error);
            }
        });
    }
}
exports.BaseUpdater = BaseUpdater;
//# sourceMappingURL=BaseUpdater.js.map{"version":3,"file":"BaseUpdater.js","sourceRoot":"","sources":["../src/BaseUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions } from \"builder-util-runtime\"\nimport { spawn, SpawnOptions, spawnSync, StdioOptions } from \"child_process\"\nimport * as path from \"path\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { AppUpdater, DownloadExecutorTask } from \"./AppUpdater\"\n\nexport abstract class BaseUpdater extends AppUpdater {\n  protected quitAndInstallCalled = false\n  private quitHandlerAdded = false\n\n  protected constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  quitAndInstall(isSilent = false, isForceRunAfter = false): void {\n    this._logger.info(`Install on explicit quitAndInstall`)\n    // If NOT in silent mode use `autoRunAppAfterInstall` to determine whether to force run the app\n    const isInstalled = this.install(isSilent, isSilent ? isForceRunAfter : this.autoRunAppAfterInstall)\n    if (isInstalled) {\n      setImmediate(() => {\n        // this event is normally emitted when calling quitAndInstall, this emulates that\n        require(\"electron\").autoUpdater.emit(\"before-quit-for-update\")\n        this.app.quit()\n      })\n    } else {\n      this.quitAndInstallCalled = false\n    }\n  }\n\n  protected executeDownload(taskOptions: DownloadExecutorTask): Promise<Array<string>> {\n    return super.executeDownload({\n      ...taskOptions,\n      done: event => {\n        this.dispatchUpdateDownloaded(event)\n        this.addQuitHandler()\n        return Promise.resolve()\n      },\n    })\n  }\n\n  protected get installerPath(): string | null {\n    return this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.file\n  }\n\n  // must be sync\n  protected abstract doInstall(options: InstallOptions): boolean\n\n  // must be sync (because quit even handler is not async)\n  install(isSilent = false, isForceRunAfter = false): boolean {\n    if (this.quitAndInstallCalled) {\n      this._logger.warn(\"install call ignored: quitAndInstallCalled is set to true\")\n      return false\n    }\n\n    const downloadedUpdateHelper = this.downloadedUpdateHelper\n    const installerPath = this.installerPath\n    const downloadedFileInfo = downloadedUpdateHelper == null ? null : downloadedUpdateHelper.downloadedFileInfo\n    if (installerPath == null || downloadedFileInfo == null) {\n      this.dispatchError(new Error(\"No update filepath provided, can't quit and install\"))\n      return false\n    }\n\n    // prevent calling several times\n    this.quitAndInstallCalled = true\n\n    try {\n      this._logger.info(`Install: isSilent: ${isSilent}, isForceRunAfter: ${isForceRunAfter}`)\n      return this.doInstall({\n        isSilent,\n        isForceRunAfter,\n        isAdminRightsRequired: downloadedFileInfo.isAdminRightsRequired,\n      })\n    } catch (e: any) {\n      this.dispatchError(e)\n      return false\n    }\n  }\n\n  protected addQuitHandler(): void {\n    if (this.quitHandlerAdded || !this.autoInstallOnAppQuit) {\n      return\n    }\n\n    this.quitHandlerAdded = true\n\n    this.app.onQuit(exitCode => {\n      if (this.quitAndInstallCalled) {\n        this._logger.info(\"Update installer has already been triggered. Quitting application.\")\n        return\n      }\n\n      if (!this.autoInstallOnAppQuit) {\n        this._logger.info(\"Update will not be installed on quit because autoInstallOnAppQuit is set to false.\")\n        return\n      }\n\n      if (exitCode !== 0) {\n        this._logger.info(`Update will be not installed on quit because application is quitting with exit code ${exitCode}`)\n        return\n      }\n\n      this._logger.info(\"Auto install update on quit\")\n      this.install(true, false)\n    })\n  }\n\n  /**\n   * Strips relative-path entries from a PATH string.\n   * Prevents PATH-poisoning where a writable directory earlier in PATH shadows\n   * a trusted package manager binary.\n   */\n  protected sanitizeEnvPath(envPath: string): string {\n    return envPath\n      .split(path.delimiter)\n      .filter((dir: string) => path.isAbsolute(dir))\n      .join(path.delimiter)\n  }\n\n  protected spawnSyncLog(cmd: string, args: string[] = [], env = {}): string {\n    this._logger.info(`Executing: ${cmd} with args: ${args}`)\n    const mergedEnv: NodeJS.ProcessEnv = { ...process.env, ...env }\n    const response = spawnSync(cmd, args, {\n      env: { ...mergedEnv, PATH: this.sanitizeEnvPath(mergedEnv.PATH ?? \"\") },\n      encoding: \"utf-8\",\n      shell: true,\n    })\n\n    const { error, status, stdout, stderr } = response\n    if (error != null) {\n      this._logger.error(stderr)\n      throw error\n    } else if (status != null && status !== 0) {\n      this._logger.error(stderr)\n      throw new Error(`Command ${cmd} exited with code ${status}`)\n    }\n\n    return stdout.trim()\n  }\n\n  /**\n   * This handles both node 8 and node 10 way of emitting error when spawning a process\n   *   - node 8: Throws the error\n   *   - node 10: Emit the error(Need to listen with on)\n   */\n  // https://github.com/electron-userland/electron-builder/issues/1129\n  // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors\n  protected async spawnLog(cmd: string, args: string[] = [], env: any = undefined, stdio: StdioOptions = \"ignore\"): Promise<boolean> {\n    this._logger.info(`Executing: ${cmd} with args: ${args}`)\n    return new Promise<boolean>((resolve, reject) => {\n      try {\n        const params: SpawnOptions = { stdio, env, detached: true }\n        const p = spawn(cmd, args, params)\n        p.on(\"error\", error => {\n          reject(error)\n        })\n        p.unref()\n        if (p.pid !== undefined) {\n          resolve(true)\n        }\n      } catch (error) {\n        reject(error)\n      }\n    })\n  }\n}\n\nexport interface InstallOptions {\n  readonly isSilent: boolean\n  readonly isForceRunAfter: boolean\n  readonly isAdminRightsRequired: boolean\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DebUpdater = void 0;
const Provider_1 = require("./providers/Provider");
const types_1 = require("./types");
const LinuxUpdater_1 = require("./LinuxUpdater");
class DebUpdater extends LinuxUpdater_1.LinuxUpdater {
    constructor(options, app) {
        super(options, app);
    }
    /*** @private */
    doDownloadUpdate(downloadUpdateOptions) {
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const fileInfo = (0, Provider_1.findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "deb", ["AppImage", "rpm", "pacman"]);
        return this.executeDownload({
            fileExtension: "deb",
            fileInfo,
            downloadUpdateOptions,
            task: async (updateFile, downloadOptions) => {
                if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                    downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
                }
                await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions);
            },
        });
    }
    doInstall(options) {
        const installerPath = this.installerPath;
        if (installerPath == null) {
            this.dispatchError(new Error("No update filepath provided, can't quit and install"));
            return false;
        }
        if (!this.hasCommand("dpkg") && !this.hasCommand("apt")) {
            this.dispatchError(new Error("Neither dpkg nor apt command found. Cannot install .deb package."));
            return false;
        }
        const priorityList = ["dpkg", "apt"];
        const packageManager = this.detectPackageManager(priorityList);
        try {
            DebUpdater.installWithCommandRunner(packageManager, installerPath, this.runCommandWithSudoIfNeeded.bind(this), this._logger);
        }
        catch (error) {
            this.dispatchError(error);
            return false;
        }
        if (options.isForceRunAfter) {
            this.app.relaunch();
        }
        return true;
    }
    static installWithCommandRunner(packageManager, installerPath, commandRunner, logger) {
        var _a;
        if (packageManager === "dpkg") {
            try {
                // Primary: Install unsigned .deb directly with dpkg
                commandRunner(["dpkg", "-i", installerPath]);
            }
            catch (error) {
                // Handle missing dependencies via apt-get
                logger.warn((_a = error.message) !== null && _a !== void 0 ? _a : error);
                logger.warn("dpkg installation failed, trying to fix broken dependencies with apt-get");
                commandRunner(["apt-get", "install", "-f", "-y"]);
            }
        }
        else if (packageManager === "apt") {
            // Fallback: Use apt for direct install (less safe for unsigned .deb)
            logger.warn("Using apt to install a local .deb. This may fail for unsigned packages unless properly configured.");
            commandRunner([
                "apt",
                "install",
                "-y",
                "--allow-unauthenticated", // needed for unsigned .debs
                "--allow-downgrades", // allow lower version installs
                "--allow-change-held-packages",
                installerPath,
            ]);
        }
        else {
            throw new Error(`Package manager ${packageManager} not supported`);
        }
    }
}
exports.DebUpdater = DebUpdater;
//# sourceMappingURL=DebUpdater.js.map{"version":3,"file":"DebUpdater.js","sourceRoot":"","sources":["../src/DebUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions } from \"builder-util-runtime\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { InstallOptions } from \"./BaseUpdater\"\nimport { findFile } from \"./providers/Provider\"\nimport { DOWNLOAD_PROGRESS, Logger } from \"./types\"\nimport { LinuxUpdater } from \"./LinuxUpdater\"\n\nexport class DebUpdater extends LinuxUpdater {\n  constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  /*** @private */\n  protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"deb\", [\"AppImage\", \"rpm\", \"pacman\"])!\n    return this.executeDownload({\n      fileExtension: \"deb\",\n      fileInfo,\n      downloadUpdateOptions,\n      task: async (updateFile, downloadOptions) => {\n        if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n          downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n        }\n        await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions)\n      },\n    })\n  }\n\n  protected doInstall(options: InstallOptions): boolean {\n    const installerPath = this.installerPath\n    if (installerPath == null) {\n      this.dispatchError(new Error(\"No update filepath provided, can't quit and install\"))\n      return false\n    }\n    if (!this.hasCommand(\"dpkg\") && !this.hasCommand(\"apt\")) {\n      this.dispatchError(new Error(\"Neither dpkg nor apt command found. Cannot install .deb package.\"))\n      return false\n    }\n    const priorityList = [\"dpkg\", \"apt\"]\n    const packageManager = this.detectPackageManager(priorityList)\n    try {\n      DebUpdater.installWithCommandRunner(packageManager as any, installerPath, this.runCommandWithSudoIfNeeded.bind(this), this._logger)\n    } catch (error: any) {\n      this.dispatchError(error)\n      return false\n    }\n    if (options.isForceRunAfter) {\n      this.app.relaunch()\n    }\n    return true\n  }\n\n  static installWithCommandRunner(packageManager: \"dpkg\" | \"apt\", installerPath: string, commandRunner: (commandWithArgs: string[]) => void, logger: Logger) {\n    if (packageManager === \"dpkg\") {\n      try {\n        // Primary: Install unsigned .deb directly with dpkg\n        commandRunner([\"dpkg\", \"-i\", installerPath])\n      } catch (error: any) {\n        // Handle missing dependencies via apt-get\n        logger.warn(error.message ?? error)\n        logger.warn(\"dpkg installation failed, trying to fix broken dependencies with apt-get\")\n        commandRunner([\"apt-get\", \"install\", \"-f\", \"-y\"])\n      }\n    } else if (packageManager === \"apt\") {\n      // Fallback: Use apt for direct install (less safe for unsigned .deb)\n      logger.warn(\"Using apt to install a local .deb. This may fail for unsigned packages unless properly configured.\")\n      commandRunner([\n        \"apt\",\n        \"install\",\n        \"-y\",\n        \"--allow-unauthenticated\", // needed for unsigned .debs\n        \"--allow-downgrades\", // allow lower version installs\n        \"--allow-change-held-packages\",\n        installerPath,\n      ])\n    } else {\n      throw new Error(`Package manager ${packageManager} not supported`)\n    }\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DownloadedUpdateHelper = void 0;
exports.createTempUpdateFile = createTempUpdateFile;
const crypto_1 = require("crypto");
const fs_1 = require("fs");
// @ts-ignore
const isEqual = require("lodash.isequal");
const fs_extra_1 = require("fs-extra");
const path = require("path");
/** @private **/
class DownloadedUpdateHelper {
    constructor(cacheDir) {
        this.cacheDir = cacheDir;
        this._file = null;
        this._packageFile = null;
        this.versionInfo = null;
        this.fileInfo = null;
        this._downloadedFileInfo = null;
    }
    get downloadedFileInfo() {
        return this._downloadedFileInfo;
    }
    get file() {
        return this._file;
    }
    get packageFile() {
        return this._packageFile;
    }
    get cacheDirForPendingUpdate() {
        return path.join(this.cacheDir, "pending");
    }
    async validateDownloadedPath(updateFile, updateInfo, fileInfo, logger) {
        if (this.versionInfo != null && this.file === updateFile && this.fileInfo != null) {
            // update has already been downloaded from this running instance
            // check here only existence, not checksum
            if (isEqual(this.versionInfo, updateInfo) && isEqual(this.fileInfo.info, fileInfo.info) && (await (0, fs_extra_1.pathExists)(updateFile))) {
                return updateFile;
            }
            else {
                return null;
            }
        }
        // update has already been downloaded from some previous app launch
        const cachedUpdateFile = await this.getValidCachedUpdateFile(fileInfo, logger);
        if (cachedUpdateFile === null) {
            return null;
        }
        logger.info(`Update has already been downloaded to ${updateFile}).`);
        this._file = cachedUpdateFile;
        return cachedUpdateFile;
    }
    async setDownloadedFile(downloadedFile, packageFile, versionInfo, fileInfo, updateFileName, isSaveCache) {
        this._file = downloadedFile;
        this._packageFile = packageFile;
        this.versionInfo = versionInfo;
        this.fileInfo = fileInfo;
        this._downloadedFileInfo = {
            fileName: updateFileName,
            sha512: fileInfo.info.sha512,
            isAdminRightsRequired: fileInfo.info.isAdminRightsRequired === true,
        };
        if (isSaveCache) {
            await (0, fs_extra_1.outputJson)(this.getUpdateInfoFile(), this._downloadedFileInfo);
        }
    }
    async clear() {
        this._file = null;
        this._packageFile = null;
        this.versionInfo = null;
        this.fileInfo = null;
        await this.cleanCacheDirForPendingUpdate();
    }
    async cleanCacheDirForPendingUpdate() {
        try {
            // remove stale data
            await (0, fs_extra_1.emptyDir)(this.cacheDirForPendingUpdate);
        }
        catch (_ignore) {
            // ignore
        }
    }
    /**
     * Returns "update-info.json" which is created in the update cache directory's "pending" subfolder after the first update is downloaded.  If the update file does not exist then the cache is cleared and recreated.  If the update file exists then its properties are validated.
     * @param fileInfo
     * @param logger
     */
    async getValidCachedUpdateFile(fileInfo, logger) {
        const updateInfoFilePath = this.getUpdateInfoFile();
        const doesUpdateInfoFileExist = await (0, fs_extra_1.pathExists)(updateInfoFilePath);
        if (!doesUpdateInfoFileExist) {
            return null;
        }
        let cachedInfo;
        try {
            cachedInfo = await (0, fs_extra_1.readJson)(updateInfoFilePath);
        }
        catch (error) {
            let message = `No cached update info available`;
            if (error.code !== "ENOENT") {
                await this.cleanCacheDirForPendingUpdate();
                message += ` (error on read: ${error.message})`;
            }
            logger.info(message);
            return null;
        }
        const isCachedInfoFileNameValid = (cachedInfo === null || cachedInfo === void 0 ? void 0 : cachedInfo.fileName) !== null;
        if (!isCachedInfoFileNameValid) {
            logger.warn(`Cached update info is corrupted: no fileName, directory for cached update will be cleaned`);
            await this.cleanCacheDirForPendingUpdate();
            return null;
        }
        if (fileInfo.info.sha512 !== cachedInfo.sha512) {
            logger.info(`Cached update sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${cachedInfo.sha512}, expected: ${fileInfo.info.sha512}. Directory for cached update will be cleaned`);
            await this.cleanCacheDirForPendingUpdate();
            return null;
        }
        const updateFile = path.join(this.cacheDirForPendingUpdate, cachedInfo.fileName);
        if (!(await (0, fs_extra_1.pathExists)(updateFile))) {
            logger.info("Cached update file doesn't exist");
            return null;
        }
        const sha512 = await hashFile(updateFile);
        if (fileInfo.info.sha512 !== sha512) {
            logger.warn(`Sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${sha512}, expected: ${fileInfo.info.sha512}`);
            await this.cleanCacheDirForPendingUpdate();
            return null;
        }
        this._downloadedFileInfo = cachedInfo;
        return updateFile;
    }
    getUpdateInfoFile() {
        return path.join(this.cacheDirForPendingUpdate, "update-info.json");
    }
}
exports.DownloadedUpdateHelper = DownloadedUpdateHelper;
function hashFile(file, algorithm = "sha512", encoding = "base64", options) {
    return new Promise((resolve, reject) => {
        const hash = (0, crypto_1.createHash)(algorithm);
        hash.on("error", reject).setEncoding(encoding);
        (0, fs_1.createReadStream)(file, { ...options, highWaterMark: 1024 * 1024 /* better to use more memory but hash faster */ })
            .on("error", reject)
            .on("end", () => {
            hash.end();
            resolve(hash.read());
        })
            .pipe(hash, { end: false });
    });
}
async function createTempUpdateFile(name, cacheDir, log) {
    // https://github.com/electron-userland/electron-builder/pull/2474#issuecomment-366481912
    let nameCounter = 0;
    let result = path.join(cacheDir, name);
    for (let i = 0; i < 3; i++) {
        try {
            await (0, fs_extra_1.unlink)(result);
            return result;
        }
        catch (e) {
            if (e.code === "ENOENT") {
                return result;
            }
            log.warn(`Error on remove temp update file: ${e}`);
            result = path.join(cacheDir, `${nameCounter++}-${name}`);
        }
    }
    return result;
}
//# sourceMappingURL=DownloadedUpdateHelper.js.map{"version":3,"file":"DownloadedUpdateHelper.js","sourceRoot":"","sources":["../src/DownloadedUpdateHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import { UpdateInfo } from \"builder-util-runtime\"\nimport { createHash } from \"crypto\"\nimport { createReadStream } from \"fs\"\n// @ts-ignore\nimport * as isEqual from \"lodash.isequal\"\nimport { ResolvedUpdateFileInfo } from \"./types\"\nimport { Logger } from \"./types\"\nimport { pathExists, readJson, emptyDir, outputJson, unlink } from \"fs-extra\"\nimport * as path from \"path\"\n\n/** @private **/\nexport class DownloadedUpdateHelper {\n  private _file: string | null = null\n  private _packageFile: string | null = null\n\n  private versionInfo: UpdateInfo | null = null\n  private fileInfo: ResolvedUpdateFileInfo | null = null\n\n  constructor(readonly cacheDir: string) {}\n\n  private _downloadedFileInfo: CachedUpdateInfo | null = null\n  get downloadedFileInfo(): CachedUpdateInfo | null {\n    return this._downloadedFileInfo\n  }\n\n  get file(): string | null {\n    return this._file\n  }\n\n  get packageFile(): string | null {\n    return this._packageFile\n  }\n\n  get cacheDirForPendingUpdate(): string {\n    return path.join(this.cacheDir, \"pending\")\n  }\n\n  async validateDownloadedPath(updateFile: string, updateInfo: UpdateInfo, fileInfo: ResolvedUpdateFileInfo, logger: Logger): Promise<string | null> {\n    if (this.versionInfo != null && this.file === updateFile && this.fileInfo != null) {\n      // update has already been downloaded from this running instance\n      // check here only existence, not checksum\n      if (isEqual(this.versionInfo, updateInfo) && isEqual(this.fileInfo.info, fileInfo.info) && (await pathExists(updateFile))) {\n        return updateFile\n      } else {\n        return null\n      }\n    }\n\n    // update has already been downloaded from some previous app launch\n    const cachedUpdateFile = await this.getValidCachedUpdateFile(fileInfo, logger)\n    if (cachedUpdateFile === null) {\n      return null\n    }\n    logger.info(`Update has already been downloaded to ${updateFile}).`)\n    this._file = cachedUpdateFile\n    return cachedUpdateFile\n  }\n\n  async setDownloadedFile(\n    downloadedFile: string,\n    packageFile: string | null,\n    versionInfo: UpdateInfo,\n    fileInfo: ResolvedUpdateFileInfo,\n    updateFileName: string,\n    isSaveCache: boolean\n  ): Promise<void> {\n    this._file = downloadedFile\n    this._packageFile = packageFile\n    this.versionInfo = versionInfo\n    this.fileInfo = fileInfo\n    this._downloadedFileInfo = {\n      fileName: updateFileName,\n      sha512: fileInfo.info.sha512,\n      isAdminRightsRequired: fileInfo.info.isAdminRightsRequired === true,\n    }\n\n    if (isSaveCache) {\n      await outputJson(this.getUpdateInfoFile(), this._downloadedFileInfo)\n    }\n  }\n\n  async clear(): Promise<void> {\n    this._file = null\n    this._packageFile = null\n    this.versionInfo = null\n    this.fileInfo = null\n    await this.cleanCacheDirForPendingUpdate()\n  }\n\n  private async cleanCacheDirForPendingUpdate(): Promise<void> {\n    try {\n      // remove stale data\n      await emptyDir(this.cacheDirForPendingUpdate)\n    } catch (_ignore) {\n      // ignore\n    }\n  }\n\n  /**\n   * Returns \"update-info.json\" which is created in the update cache directory's \"pending\" subfolder after the first update is downloaded.  If the update file does not exist then the cache is cleared and recreated.  If the update file exists then its properties are validated.\n   * @param fileInfo\n   * @param logger\n   */\n  private async getValidCachedUpdateFile(fileInfo: ResolvedUpdateFileInfo, logger: Logger): Promise<string | null> {\n    const updateInfoFilePath: string = this.getUpdateInfoFile()\n\n    const doesUpdateInfoFileExist = await pathExists(updateInfoFilePath)\n    if (!doesUpdateInfoFileExist) {\n      return null\n    }\n\n    let cachedInfo: CachedUpdateInfo\n    try {\n      cachedInfo = await readJson(updateInfoFilePath)\n    } catch (error: any) {\n      let message = `No cached update info available`\n      if (error.code !== \"ENOENT\") {\n        await this.cleanCacheDirForPendingUpdate()\n        message += ` (error on read: ${error.message})`\n      }\n      logger.info(message)\n      return null\n    }\n\n    const isCachedInfoFileNameValid = cachedInfo?.fileName !== null\n    if (!isCachedInfoFileNameValid) {\n      logger.warn(`Cached update info is corrupted: no fileName, directory for cached update will be cleaned`)\n      await this.cleanCacheDirForPendingUpdate()\n      return null\n    }\n\n    if (fileInfo.info.sha512 !== cachedInfo.sha512) {\n      logger.info(\n        `Cached update sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${cachedInfo.sha512}, expected: ${fileInfo.info.sha512}. Directory for cached update will be cleaned`\n      )\n      await this.cleanCacheDirForPendingUpdate()\n      return null\n    }\n\n    const updateFile = path.join(this.cacheDirForPendingUpdate, cachedInfo.fileName)\n    if (!(await pathExists(updateFile))) {\n      logger.info(\"Cached update file doesn't exist\")\n      return null\n    }\n\n    const sha512 = await hashFile(updateFile)\n    if (fileInfo.info.sha512 !== sha512) {\n      logger.warn(`Sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${sha512}, expected: ${fileInfo.info.sha512}`)\n      await this.cleanCacheDirForPendingUpdate()\n      return null\n    }\n    this._downloadedFileInfo = cachedInfo\n    return updateFile\n  }\n\n  private getUpdateInfoFile(): string {\n    return path.join(this.cacheDirForPendingUpdate, \"update-info.json\")\n  }\n}\n\ninterface CachedUpdateInfo {\n  fileName: string\n  sha512: string\n  readonly isAdminRightsRequired: boolean\n}\n\nfunction hashFile(file: string, algorithm = \"sha512\", encoding: \"base64\" | \"hex\" = \"base64\", options?: any): Promise<string> {\n  return new Promise<string>((resolve, reject) => {\n    const hash = createHash(algorithm)\n    hash.on(\"error\", reject).setEncoding(encoding)\n\n    createReadStream(file, { ...options, highWaterMark: 1024 * 1024 /* better to use more memory but hash faster */ })\n      .on(\"error\", reject)\n      .on(\"end\", () => {\n        hash.end()\n        resolve(hash.read() as string)\n      })\n      .pipe(hash, { end: false })\n  })\n}\n\nexport async function createTempUpdateFile(name: string, cacheDir: string, log: Logger): Promise<string> {\n  // https://github.com/electron-userland/electron-builder/pull/2474#issuecomment-366481912\n  let nameCounter = 0\n  let result = path.join(cacheDir, name)\n  for (let i = 0; i < 3; i++) {\n    try {\n      await unlink(result)\n      return result\n    } catch (e: any) {\n      if (e.code === \"ENOENT\") {\n        return result\n      }\n\n      log.warn(`Error on remove temp update file: ${e}`)\n      result = path.join(cacheDir, `${nameCounter++}-${name}`)\n    }\n  }\n  return result\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ElectronAppAdapter = void 0;
const path = require("path");
const AppAdapter_1 = require("./AppAdapter");
class ElectronAppAdapter {
    constructor(app = require("electron").app) {
        this.app = app;
    }
    whenReady() {
        return this.app.whenReady();
    }
    get version() {
        return this.app.getVersion();
    }
    get name() {
        return this.app.getName();
    }
    get isPackaged() {
        return this.app.isPackaged === true;
    }
    get appUpdateConfigPath() {
        return this.isPackaged ? path.join(process.resourcesPath, "app-update.yml") : path.join(this.app.getAppPath(), "dev-app-update.yml");
    }
    get userDataPath() {
        return this.app.getPath("userData");
    }
    get baseCachePath() {
        return (0, AppAdapter_1.getAppCacheDir)();
    }
    quit() {
        this.app.quit();
    }
    relaunch() {
        this.app.relaunch();
    }
    onQuit(handler) {
        this.app.once("quit", (_, exitCode) => handler(exitCode));
    }
}
exports.ElectronAppAdapter = ElectronAppAdapter;
//# sourceMappingURL=ElectronAppAdapter.js.map{"version":3,"file":"ElectronAppAdapter.js","sourceRoot":"","sources":["../src/ElectronAppAdapter.ts"],"names":[],"mappings":";;;AAAA,6BAA4B;AAC5B,6CAAyD;AAEzD,MAAa,kBAAkB;IAC7B,YAA6B,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG;QAA7B,QAAG,GAAH,GAAG,CAA0B;IAAG,CAAC;IAE9D,SAAS;QACP,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;IAC7B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAA;IAC9B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAA;IAC3B,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,IAAI,CAAA;IACrC,CAAC;IAED,IAAI,mBAAmB;QACrB,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,oBAAoB,CAAC,CAAA;IACtI,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACrC,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAA,2BAAc,GAAE,CAAA;IACzB,CAAC;IAED,IAAI;QACF,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;IACjB,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;IACrB,CAAC;IAED,MAAM,CAAC,OAAmC;QACxC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAiB,EAAE,QAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IACnF,CAAC;CACF;AA1CD,gDA0CC","sourcesContent":["import * as path from \"path\"\nimport { AppAdapter, getAppCacheDir } from \"./AppAdapter\"\n\nexport class ElectronAppAdapter implements AppAdapter {\n  constructor(private readonly app = require(\"electron\").app) {}\n\n  whenReady(): Promise<void> {\n    return this.app.whenReady()\n  }\n\n  get version(): string {\n    return this.app.getVersion()\n  }\n\n  get name(): string {\n    return this.app.getName()\n  }\n\n  get isPackaged(): boolean {\n    return this.app.isPackaged === true\n  }\n\n  get appUpdateConfigPath(): string {\n    return this.isPackaged ? path.join(process.resourcesPath, \"app-update.yml\") : path.join(this.app.getAppPath(), \"dev-app-update.yml\")\n  }\n\n  get userDataPath(): string {\n    return this.app.getPath(\"userData\")\n  }\n\n  get baseCachePath(): string {\n    return getAppCacheDir()\n  }\n\n  quit(): void {\n    this.app.quit()\n  }\n\n  relaunch(): void {\n    this.app.relaunch()\n  }\n\n  onQuit(handler: (exitCode: number) => void): void {\n    this.app.once(\"quit\", (_: Electron.Event, exitCode: number) => handler(exitCode))\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LinuxUpdater = void 0;
const BaseUpdater_1 = require("./BaseUpdater");
// Matches safe package manager names: alphanumeric, hyphens, underscores only.
// Rejects names with shell metacharacters that could cause command injection.
const SAFE_PM_REGEX = /^[a-zA-Z0-9_-]+$/;
class LinuxUpdater extends BaseUpdater_1.BaseUpdater {
    constructor(options, app) {
        super(options, app);
    }
    /**
     * Returns true if the current process is running as root.
     */
    isRunningAsRoot() {
        var _a;
        return ((_a = process.getuid) === null || _a === void 0 ? void 0 : _a.call(process)) === 0;
    }
    /**
     * Sanitizes the installer path for use with shell:true spawn calls.
     * Backslash-escapes metacharacters that have special meaning in POSIX shell.
     * Note: paths containing single-quotes (') are not supported.
     */
    get installerPath() {
        const raw = super.installerPath;
        if (raw == null) {
            return null;
        }
        return raw
            .replace(/\\/g, "\\\\") // must come first
            .replace(/([`$!" ;|&()<>])/g, "\\$1")
            .replace(/[\n\r]/g, "");
    }
    runCommandWithSudoIfNeeded(commandWithArgs) {
        if (this.isRunningAsRoot()) {
            this._logger.info("Running as root, no need to use sudo");
            return this.spawnSyncLog(commandWithArgs[0], commandWithArgs.slice(1));
        }
        const { name } = this.app;
        // Strip characters that could break shell quoting in the sudo dialog comment string
        const safeName = name.replace(/["`$\\!\n\r;|&<>(){}*?[\]#~]/g, "");
        const installComment = `"${safeName} would like to update"`;
        const sudo = this.sudoWithArgs(installComment);
        this._logger.info(`Running as non-root user, using sudo to install: ${sudo}`);
        let wrapper = `"`;
        // some sudo commands dont want the command to be wrapped in " quotes
        if (/pkexec/i.test(sudo[0]) || sudo[0] === "sudo") {
            wrapper = "";
        }
        return this.spawnSyncLog(sudo[0], [...(sudo.length > 1 ? sudo.slice(1) : []), `${wrapper}/bin/bash`, "-c", `'${commandWithArgs.join(" ")}'${wrapper}`]);
    }
    sudoWithArgs(installComment) {
        const sudo = this.determineSudoCommand();
        const command = [sudo];
        if (/kdesudo/i.test(sudo)) {
            command.push("--comment", installComment);
            command.push("-c");
        }
        else if (/gksudo/i.test(sudo)) {
            command.push("--message", installComment);
        }
        else if (/pkexec/i.test(sudo)) {
            command.push("--disable-internal-agent");
        }
        return command;
    }
    hasCommand(cmd) {
        try {
            this.spawnSyncLog(`command`, ["-v", cmd]);
            return true;
        }
        catch {
            return false;
        }
    }
    determineSudoCommand() {
        const sudos = ["gksudo", "kdesudo", "pkexec", "beesu"];
        for (const sudo of sudos) {
            if (this.hasCommand(sudo)) {
                return sudo;
            }
        }
        return "sudo";
    }
    /**
     * Detects the package manager to use based on the available commands.
     * Allows overriding the default behavior by setting the ELECTRON_BUILDER_LINUX_PACKAGE_MANAGER environment variable.
     * If the environment variable is set, it will be used directly. (This is useful for testing each package manager logic path.)
     * Otherwise, it checks for the presence of the specified package manager commands in the order provided.
     * @param pms - An array of package manager commands to check for, in priority order.
     * @returns The detected package manager command or "unknown" if none are found.
     */
    detectPackageManager(pms) {
        var _a;
        let availablePMs = pms;
        const pmOverride = (_a = process.env.ELECTRON_BUILDER_LINUX_PACKAGE_MANAGER) === null || _a === void 0 ? void 0 : _a.trim();
        if (pmOverride) {
            if (!SAFE_PM_REGEX.test(pmOverride)) {
                this._logger.warn(`ELECTRON_BUILDER_LINUX_PACKAGE_MANAGER "${pmOverride}" contains unsafe characters. Ignoring override.`);
            }
            else {
                availablePMs = [pmOverride];
            }
        }
        // Check for the package manager in the order of priority
        for (const pm of availablePMs) {
            if (this.hasCommand(pm)) {
                return pm;
            }
        }
        // return the first/default package manager in the original list if none are found, this will throw upstream for proper logging
        const searchList = pmOverride ? `ELECTRON_BUILDER_LINUX_PACKAGE_MANAGER override "${pmOverride}", ` : "";
        const defaultPM = pms[0];
        this._logger.warn(`No package manager found in the list: ${searchList}${pms.join(", ")}. Utilizing default: ${defaultPM}`);
        return defaultPM;
    }
}
exports.LinuxUpdater = LinuxUpdater;
//# sourceMappingURL=LinuxUpdater.js.map{"version":3,"file":"LinuxUpdater.js","sourceRoot":"","sources":["../src/LinuxUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions } from \"builder-util-runtime\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { BaseUpdater } from \"./BaseUpdater\"\n\n// Matches safe package manager names: alphanumeric, hyphens, underscores only.\n// Rejects names with shell metacharacters that could cause command injection.\nconst SAFE_PM_REGEX = /^[a-zA-Z0-9_-]+$/\n\nexport abstract class LinuxUpdater extends BaseUpdater {\n  constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  /**\n   * Returns true if the current process is running as root.\n   */\n  protected isRunningAsRoot(): boolean {\n    return process.getuid?.() === 0\n  }\n\n  /**\n   * Sanitizes the installer path for use with shell:true spawn calls.\n   * Backslash-escapes metacharacters that have special meaning in POSIX shell.\n   * Note: paths containing single-quotes (') are not supported.\n   */\n  protected get installerPath(): string | null {\n    const raw = super.installerPath\n    if (raw == null) {\n      return null\n    }\n    return raw\n      .replace(/\\\\/g, \"\\\\\\\\\") // must come first\n      .replace(/([`$!\" ;|&()<>])/g, \"\\\\$1\")\n      .replace(/[\\n\\r]/g, \"\")\n  }\n\n  protected runCommandWithSudoIfNeeded(commandWithArgs: string[]) {\n    if (this.isRunningAsRoot()) {\n      this._logger.info(\"Running as root, no need to use sudo\")\n      return this.spawnSyncLog(commandWithArgs[0], commandWithArgs.slice(1))\n    }\n\n    const { name } = this.app\n    // Strip characters that could break shell quoting in the sudo dialog comment string\n    const safeName = name.replace(/[\"`$\\\\!\\n\\r;|&<>(){}*?[\\]#~]/g, \"\")\n    const installComment = `\"${safeName} would like to update\"`\n    const sudo = this.sudoWithArgs(installComment)\n    this._logger.info(`Running as non-root user, using sudo to install: ${sudo}`)\n    let wrapper = `\"`\n    // some sudo commands dont want the command to be wrapped in \" quotes\n    if (/pkexec/i.test(sudo[0]) || sudo[0] === \"sudo\") {\n      wrapper = \"\"\n    }\n    return this.spawnSyncLog(sudo[0], [...(sudo.length > 1 ? sudo.slice(1) : []), `${wrapper}/bin/bash`, \"-c\", `'${commandWithArgs.join(\" \")}'${wrapper}`])\n  }\n\n  protected sudoWithArgs(installComment: string): string[] {\n    const sudo = this.determineSudoCommand()\n    const command = [sudo]\n    if (/kdesudo/i.test(sudo)) {\n      command.push(\"--comment\", installComment)\n      command.push(\"-c\")\n    } else if (/gksudo/i.test(sudo)) {\n      command.push(\"--message\", installComment)\n    } else if (/pkexec/i.test(sudo)) {\n      command.push(\"--disable-internal-agent\")\n    }\n    return command\n  }\n\n  protected hasCommand(cmd: string): boolean {\n    try {\n      this.spawnSyncLog(`command`, [\"-v\", cmd])\n      return true\n    } catch {\n      return false\n    }\n  }\n\n  protected determineSudoCommand(): string {\n    const sudos = [\"gksudo\", \"kdesudo\", \"pkexec\", \"beesu\"]\n    for (const sudo of sudos) {\n      if (this.hasCommand(sudo)) {\n        return sudo\n      }\n    }\n    return \"sudo\"\n  }\n\n  /**\n   * Detects the package manager to use based on the available commands.\n   * Allows overriding the default behavior by setting the ELECTRON_BUILDER_LINUX_PACKAGE_MANAGER environment variable.\n   * If the environment variable is set, it will be used directly. (This is useful for testing each package manager logic path.)\n   * Otherwise, it checks for the presence of the specified package manager commands in the order provided.\n   * @param pms - An array of package manager commands to check for, in priority order.\n   * @returns The detected package manager command or \"unknown\" if none are found.\n   */\n  protected detectPackageManager(pms: string[]): string {\n    let availablePMs = pms\n    const pmOverride = process.env.ELECTRON_BUILDER_LINUX_PACKAGE_MANAGER?.trim()\n    if (pmOverride) {\n      if (!SAFE_PM_REGEX.test(pmOverride)) {\n        this._logger.warn(`ELECTRON_BUILDER_LINUX_PACKAGE_MANAGER \"${pmOverride}\" contains unsafe characters. Ignoring override.`)\n      } else {\n        availablePMs = [pmOverride]\n      }\n    }\n    // Check for the package manager in the order of priority\n    for (const pm of availablePMs) {\n      if (this.hasCommand(pm)) {\n        return pm\n      }\n    }\n    // return the first/default package manager in the original list if none are found, this will throw upstream for proper logging\n    const searchList = pmOverride ? `ELECTRON_BUILDER_LINUX_PACKAGE_MANAGER override \"${pmOverride}\", ` : \"\"\n    const defaultPM = pms[0]\n    this._logger.warn(`No package manager found in the list: ${searchList}${pms.join(\", \")}. Utilizing default: ${defaultPM}`)\n    return defaultPM\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MacUpdater = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const fs_extra_1 = require("fs-extra");
const fs_1 = require("fs");
const path = require("path");
const http_1 = require("http");
const AppUpdater_1 = require("./AppUpdater");
const Provider_1 = require("./providers/Provider");
const child_process_1 = require("child_process");
const crypto_1 = require("crypto");
class MacUpdater extends AppUpdater_1.AppUpdater {
    constructor(options, app) {
        super(options, app);
        this.nativeUpdater = require("electron").autoUpdater;
        this.squirrelDownloadedUpdate = false;
        this.nativeUpdater.on("error", it => {
            this._logger.warn(it);
            this.emit("error", it);
        });
        this.nativeUpdater.on("update-downloaded", () => {
            this.squirrelDownloadedUpdate = true;
            this.debug("nativeUpdater.update-downloaded");
        });
    }
    /** Filters update files to the appropriate architecture.
     * On arm64 Macs (including Rosetta), arm64 files are preferred when available.
     * On x64 Macs, arm64 files are excluded. */
    static filterFilesForArch(files, isArm64Mac) {
        const isArm64File = (file) => { var _a; return file.url.pathname.includes("arm64") || ((_a = file.info.url) === null || _a === void 0 ? void 0 : _a.includes("arm64")); };
        if (isArm64Mac && files.some(isArm64File)) {
            return files.filter(file => isArm64Mac === isArm64File(file));
        }
        return files.filter(file => !isArm64File(file));
    }
    debug(message) {
        if (this._logger.debug != null) {
            this._logger.debug(message);
        }
    }
    closeServerIfExists() {
        if (this.server) {
            this.debug("Closing proxy server");
            this.server.close(err => {
                if (err) {
                    this.debug("proxy server wasn't already open, probably attempted closing again as a safety check before quit");
                }
            });
        }
    }
    async doDownloadUpdate(downloadUpdateOptions) {
        let files = downloadUpdateOptions.updateInfoAndProvider.provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info);
        const log = this._logger;
        // detect if we are running inside Rosetta emulation
        const sysctlRosettaInfoKey = "sysctl.proc_translated";
        let isRosetta = false;
        try {
            this.debug("Checking for macOS Rosetta environment");
            const result = (0, child_process_1.execFileSync)("sysctl", [sysctlRosettaInfoKey], { encoding: "utf8" });
            isRosetta = result.includes(`${sysctlRosettaInfoKey}: 1`);
            log.info(`Checked for macOS Rosetta environment (isRosetta=${isRosetta})`);
        }
        catch (e) {
            log.warn(`sysctl shell command to check for macOS Rosetta environment failed: ${e}`);
        }
        let isArm64Mac = false;
        try {
            this.debug("Checking for arm64 in uname");
            const result = (0, child_process_1.execFileSync)("uname", ["-a"], { encoding: "utf8" });
            const isArm = result.includes("ARM");
            log.info(`Checked 'uname -a': arm64=${isArm}`);
            isArm64Mac = isArm64Mac || isArm;
        }
        catch (e) {
            log.warn(`uname shell command to check for arm64 failed: ${e}`);
        }
        isArm64Mac = isArm64Mac || process.arch === "arm64" || isRosetta;
        // allow arm64 macs to install universal or rosetta2(x64) - https://github.com/electron-userland/electron-builder/pull/5524
        files = MacUpdater.filterFilesForArch(files, isArm64Mac);
        const zipFileInfo = (0, Provider_1.findFile)(files, "zip", ["pkg", "dmg"]);
        if (zipFileInfo == null) {
            throw (0, builder_util_runtime_1.newError)(`ZIP file not provided: ${(0, builder_util_runtime_1.safeStringifyJson)(files)}`, "ERR_UPDATER_ZIP_FILE_NOT_FOUND");
        }
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const CURRENT_MAC_APP_ZIP_FILE_NAME = "update.zip";
        return this.executeDownload({
            fileExtension: "zip",
            fileInfo: zipFileInfo,
            downloadUpdateOptions,
            task: async (destinationFile, downloadOptions) => {
                const cachedUpdateFilePath = path.join(this.downloadedUpdateHelper.cacheDir, CURRENT_MAC_APP_ZIP_FILE_NAME);
                const canDifferentialDownload = () => {
                    if (!(0, fs_extra_1.pathExistsSync)(cachedUpdateFilePath)) {
                        log.info("Unable to locate previous update.zip for differential download (is this first install?), falling back to full download");
                        return false;
                    }
                    return !downloadUpdateOptions.disableDifferentialDownload;
                };
                let differentialDownloadFailed = true;
                if (canDifferentialDownload()) {
                    differentialDownloadFailed = await this.differentialDownloadInstaller(zipFileInfo, downloadUpdateOptions, destinationFile, provider, CURRENT_MAC_APP_ZIP_FILE_NAME);
                }
                if (differentialDownloadFailed) {
                    await this.httpExecutor.download(zipFileInfo.url, destinationFile, downloadOptions);
                }
            },
            done: async (event) => {
                if (!downloadUpdateOptions.disableDifferentialDownload) {
                    try {
                        const cachedUpdateFilePath = path.join(this.downloadedUpdateHelper.cacheDir, CURRENT_MAC_APP_ZIP_FILE_NAME);
                        await (0, fs_extra_1.copyFile)(event.downloadedFile, cachedUpdateFilePath);
                    }
                    catch (error) {
                        this._logger.warn(`Unable to copy file for caching for future differential downloads: ${error.message}`);
                    }
                }
                return this.updateDownloaded(zipFileInfo, event);
            },
        });
    }
    async updateDownloaded(zipFileInfo, event) {
        var _a;
        const downloadedFile = event.downloadedFile;
        const updateFileSize = (_a = zipFileInfo.info.size) !== null && _a !== void 0 ? _a : (await (0, fs_extra_1.stat)(downloadedFile)).size;
        const log = this._logger;
        const logContext = `fileToProxy=${zipFileInfo.url.href}`;
        this.closeServerIfExists();
        this.debug(`Creating proxy server for native Squirrel.Mac (${logContext})`);
        this.server = (0, http_1.createServer)();
        this.debug(`Proxy server for native Squirrel.Mac is created (${logContext})`);
        this.server.on("close", () => {
            log.info(`Proxy server for native Squirrel.Mac is closed (${logContext})`);
        });
        // must be called after server is listening, otherwise address is null
        const getServerUrl = (s) => {
            const address = s.address();
            if (typeof address === "string") {
                return address;
            }
            return `http://127.0.0.1:${address === null || address === void 0 ? void 0 : address.port}`;
        };
        return await new Promise((resolve, reject) => {
            const pass = (0, crypto_1.randomBytes)(64).toString("base64").replace(/\//g, "_").replace(/\+/g, "-");
            const authInfo = Buffer.from(`autoupdater:${pass}`, "ascii");
            // insecure random is ok
            const fileUrl = `/${(0, crypto_1.randomBytes)(64).toString("hex")}.zip`;
            this.server.on("request", (request, response) => {
                const requestUrl = request.url;
                log.info(`${requestUrl} requested`);
                if (requestUrl === "/") {
                    // check for basic auth header
                    if (!request.headers.authorization || request.headers.authorization.indexOf("Basic ") === -1) {
                        response.statusCode = 401;
                        response.statusMessage = "Invalid Authentication Credentials";
                        response.end();
                        log.warn("No authenthication info");
                        return;
                    }
                    // verify auth credentials
                    const base64Credentials = request.headers.authorization.split(" ")[1];
                    const credentials = Buffer.from(base64Credentials, "base64").toString("ascii");
                    const [username, password] = credentials.split(":");
                    if (username !== "autoupdater" || password !== pass) {
                        response.statusCode = 401;
                        response.statusMessage = "Invalid Authentication Credentials";
                        response.end();
                        log.warn("Invalid authenthication credentials");
                        return;
                    }
                    const data = Buffer.from(`{ "url": "${getServerUrl(this.server)}${fileUrl}" }`);
                    response.writeHead(200, { "Content-Type": "application/json", "Content-Length": data.length });
                    response.end(data);
                    return;
                }
                if (!requestUrl.startsWith(fileUrl)) {
                    log.warn(`${requestUrl} requested, but not supported`);
                    response.writeHead(404);
                    response.end();
                    return;
                }
                log.info(`${fileUrl} requested by Squirrel.Mac, pipe ${downloadedFile}`);
                let errorOccurred = false;
                response.on("finish", () => {
                    if (!errorOccurred) {
                        this.nativeUpdater.removeListener("error", reject);
                        resolve([]);
                    }
                });
                const readStream = (0, fs_1.createReadStream)(downloadedFile);
                readStream.on("error", error => {
                    try {
                        response.end();
                    }
                    catch (e) {
                        log.warn(`cannot end response: ${e}`);
                    }
                    errorOccurred = true;
                    this.nativeUpdater.removeListener("error", reject);
                    reject(new Error(`Cannot pipe "${downloadedFile}": ${error}`));
                });
                response.writeHead(200, {
                    "Content-Type": "application/zip",
                    "Content-Length": updateFileSize,
                });
                readStream.pipe(response);
            });
            this.debug(`Proxy server for native Squirrel.Mac is starting to listen (${logContext})`);
            this.server.listen(0, "127.0.0.1", () => {
                this.debug(`Proxy server for native Squirrel.Mac is listening (address=${getServerUrl(this.server)}, ${logContext})`);
                this.nativeUpdater.setFeedURL({
                    url: getServerUrl(this.server),
                    headers: {
                        "Cache-Control": "no-cache",
                        Authorization: `Basic ${authInfo.toString("base64")}`,
                    },
                });
                // The update has been downloaded and is ready to be served to Squirrel
                this.dispatchUpdateDownloaded(event);
                if (this.autoInstallOnAppQuit) {
                    this.nativeUpdater.once("error", reject);
                    // This will trigger fetching and installing the file on Squirrel side
                    this.nativeUpdater.checkForUpdates();
                }
                else {
                    resolve([]);
                }
            });
        });
    }
    handleUpdateDownloaded() {
        if (this.autoRunAppAfterInstall) {
            this.nativeUpdater.quitAndInstall();
        }
        else {
            this.app.quit();
        }
        this.closeServerIfExists();
    }
    quitAndInstall() {
        if (this.squirrelDownloadedUpdate) {
            // update already fetched by Squirrel, it's ready to install
            this.handleUpdateDownloaded();
        }
        else {
            // Quit and install as soon as Squirrel get the update
            this.nativeUpdater.on("update-downloaded", () => this.handleUpdateDownloaded());
            if (!this.autoInstallOnAppQuit) {
                /**
                 * If this was not `true` previously then MacUpdater.doDownloadUpdate()
                 * would not actually initiate the downloading by electron's autoUpdater
                 */
                this.nativeUpdater.checkForUpdates();
            }
        }
    }
}
exports.MacUpdater = MacUpdater;
//# sourceMappingURL=MacUpdater.js.map{"version":3,"file":"MacUpdater.js","sourceRoot":"","sources":["../src/MacUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions, newError, safeStringifyJson } from \"builder-util-runtime\"\nimport { pathExistsSync, stat, copyFile } from \"fs-extra\"\nimport { createReadStream } from \"fs\"\nimport * as path from \"path\"\nimport { createServer, IncomingMessage, Server, ServerResponse } from \"http\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { AppUpdater, DownloadUpdateOptions } from \"./AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"./main\"\nimport { UpdateDownloadedEvent } from \"./types\"\nimport { findFile } from \"./providers/Provider\"\nimport AutoUpdater = Electron.AutoUpdater\nimport { execFileSync } from \"child_process\"\nimport { randomBytes } from \"crypto\"\n\nexport class MacUpdater extends AppUpdater {\n  private readonly nativeUpdater: AutoUpdater = require(\"electron\").autoUpdater\n\n  private squirrelDownloadedUpdate = false\n\n  private server?: Server\n\n  constructor(options?: AllPublishOptions, app?: AppAdapter) {\n    super(options, app)\n\n    this.nativeUpdater.on(\"error\", it => {\n      this._logger.warn(it)\n      this.emit(\"error\", it)\n    })\n    this.nativeUpdater.on(\"update-downloaded\", () => {\n      this.squirrelDownloadedUpdate = true\n      this.debug(\"nativeUpdater.update-downloaded\")\n    })\n  }\n\n  /** Filters update files to the appropriate architecture.\n   * On arm64 Macs (including Rosetta), arm64 files are preferred when available.\n   * On x64 Macs, arm64 files are excluded. */\n  protected static filterFilesForArch(files: ResolvedUpdateFileInfo[], isArm64Mac: boolean): ResolvedUpdateFileInfo[] {\n    const isArm64File = (file: ResolvedUpdateFileInfo) => file.url.pathname.includes(\"arm64\") || file.info.url?.includes(\"arm64\")\n    if (isArm64Mac && files.some(isArm64File)) {\n      return files.filter(file => isArm64Mac === isArm64File(file))\n    }\n    return files.filter(file => !isArm64File(file))\n  }\n\n  private debug(message: string): void {\n    if (this._logger.debug != null) {\n      this._logger.debug(message)\n    }\n  }\n\n  private closeServerIfExists() {\n    if (this.server) {\n      this.debug(\"Closing proxy server\")\n      this.server.close(err => {\n        if (err) {\n          this.debug(\"proxy server wasn't already open, probably attempted closing again as a safety check before quit\")\n        }\n      })\n    }\n  }\n\n  protected async doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    let files = downloadUpdateOptions.updateInfoAndProvider.provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info)\n\n    const log = this._logger\n\n    // detect if we are running inside Rosetta emulation\n    const sysctlRosettaInfoKey = \"sysctl.proc_translated\"\n    let isRosetta = false\n    try {\n      this.debug(\"Checking for macOS Rosetta environment\")\n      const result = execFileSync(\"sysctl\", [sysctlRosettaInfoKey], { encoding: \"utf8\" })\n      isRosetta = result.includes(`${sysctlRosettaInfoKey}: 1`)\n      log.info(`Checked for macOS Rosetta environment (isRosetta=${isRosetta})`)\n    } catch (e: any) {\n      log.warn(`sysctl shell command to check for macOS Rosetta environment failed: ${e}`)\n    }\n\n    let isArm64Mac = false\n    try {\n      this.debug(\"Checking for arm64 in uname\")\n      const result = execFileSync(\"uname\", [\"-a\"], { encoding: \"utf8\" })\n      const isArm = result.includes(\"ARM\")\n      log.info(`Checked 'uname -a': arm64=${isArm}`)\n      isArm64Mac = isArm64Mac || isArm\n    } catch (e: any) {\n      log.warn(`uname shell command to check for arm64 failed: ${e}`)\n    }\n\n    isArm64Mac = isArm64Mac || process.arch === \"arm64\" || isRosetta\n\n    // allow arm64 macs to install universal or rosetta2(x64) - https://github.com/electron-userland/electron-builder/pull/5524\n    files = MacUpdater.filterFilesForArch(files, isArm64Mac)\n\n    const zipFileInfo = findFile(files, \"zip\", [\"pkg\", \"dmg\"])\n\n    if (zipFileInfo == null) {\n      throw newError(`ZIP file not provided: ${safeStringifyJson(files)}`, \"ERR_UPDATER_ZIP_FILE_NOT_FOUND\")\n    }\n\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const CURRENT_MAC_APP_ZIP_FILE_NAME = \"update.zip\"\n\n    return this.executeDownload({\n      fileExtension: \"zip\",\n      fileInfo: zipFileInfo,\n      downloadUpdateOptions,\n      task: async (destinationFile, downloadOptions) => {\n        const cachedUpdateFilePath = path.join(this.downloadedUpdateHelper!.cacheDir, CURRENT_MAC_APP_ZIP_FILE_NAME)\n        const canDifferentialDownload = () => {\n          if (!pathExistsSync(cachedUpdateFilePath)) {\n            log.info(\"Unable to locate previous update.zip for differential download (is this first install?), falling back to full download\")\n            return false\n          }\n          return !downloadUpdateOptions.disableDifferentialDownload\n        }\n        let differentialDownloadFailed = true\n        if (canDifferentialDownload()) {\n          differentialDownloadFailed = await this.differentialDownloadInstaller(zipFileInfo, downloadUpdateOptions, destinationFile, provider, CURRENT_MAC_APP_ZIP_FILE_NAME)\n        }\n\n        if (differentialDownloadFailed) {\n          await this.httpExecutor.download(zipFileInfo.url, destinationFile, downloadOptions)\n        }\n      },\n      done: async event => {\n        if (!downloadUpdateOptions.disableDifferentialDownload) {\n          try {\n            const cachedUpdateFilePath = path.join(this.downloadedUpdateHelper!.cacheDir, CURRENT_MAC_APP_ZIP_FILE_NAME)\n            await copyFile(event.downloadedFile, cachedUpdateFilePath)\n          } catch (error: any) {\n            this._logger.warn(`Unable to copy file for caching for future differential downloads: ${error.message}`)\n          }\n        }\n        return this.updateDownloaded(zipFileInfo, event)\n      },\n    })\n  }\n\n  private async updateDownloaded(zipFileInfo: ResolvedUpdateFileInfo, event: UpdateDownloadedEvent): Promise<Array<string>> {\n    const downloadedFile = event.downloadedFile\n    const updateFileSize = zipFileInfo.info.size ?? (await stat(downloadedFile)).size\n\n    const log = this._logger\n    const logContext = `fileToProxy=${zipFileInfo.url.href}`\n    this.closeServerIfExists()\n    this.debug(`Creating proxy server for native Squirrel.Mac (${logContext})`)\n    this.server = createServer()\n    this.debug(`Proxy server for native Squirrel.Mac is created (${logContext})`)\n    this.server.on(\"close\", () => {\n      log.info(`Proxy server for native Squirrel.Mac is closed (${logContext})`)\n    })\n\n    // must be called after server is listening, otherwise address is null\n    const getServerUrl = (s: Server): string => {\n      const address = s.address()\n      if (typeof address === \"string\") {\n        return address\n      }\n      return `http://127.0.0.1:${address?.port}`\n    }\n\n    return await new Promise<Array<string>>((resolve, reject) => {\n      const pass = randomBytes(64).toString(\"base64\").replace(/\\//g, \"_\").replace(/\\+/g, \"-\")\n      const authInfo = Buffer.from(`autoupdater:${pass}`, \"ascii\")\n\n      // insecure random is ok\n      const fileUrl = `/${randomBytes(64).toString(\"hex\")}.zip`\n      this.server!.on(\"request\", (request: IncomingMessage, response: ServerResponse) => {\n        const requestUrl = request.url!\n        log.info(`${requestUrl} requested`)\n        if (requestUrl === \"/\") {\n          // check for basic auth header\n          if (!request.headers.authorization || request.headers.authorization.indexOf(\"Basic \") === -1) {\n            response.statusCode = 401\n            response.statusMessage = \"Invalid Authentication Credentials\"\n            response.end()\n            log.warn(\"No authenthication info\")\n            return\n          }\n\n          // verify auth credentials\n          const base64Credentials = request.headers.authorization.split(\" \")[1]\n          const credentials = Buffer.from(base64Credentials, \"base64\").toString(\"ascii\")\n          const [username, password] = credentials.split(\":\")\n          if (username !== \"autoupdater\" || password !== pass) {\n            response.statusCode = 401\n            response.statusMessage = \"Invalid Authentication Credentials\"\n            response.end()\n            log.warn(\"Invalid authenthication credentials\")\n            return\n          }\n\n          const data = Buffer.from(`{ \"url\": \"${getServerUrl(this.server!)}${fileUrl}\" }`)\n          response.writeHead(200, { \"Content-Type\": \"application/json\", \"Content-Length\": data.length })\n          response.end(data)\n          return\n        }\n\n        if (!requestUrl.startsWith(fileUrl)) {\n          log.warn(`${requestUrl} requested, but not supported`)\n          response.writeHead(404)\n          response.end()\n          return\n        }\n\n        log.info(`${fileUrl} requested by Squirrel.Mac, pipe ${downloadedFile}`)\n\n        let errorOccurred = false\n        response.on(\"finish\", () => {\n          if (!errorOccurred) {\n            this.nativeUpdater.removeListener(\"error\", reject)\n            resolve([])\n          }\n        })\n\n        const readStream = createReadStream(downloadedFile)\n        readStream.on(\"error\", error => {\n          try {\n            response.end()\n          } catch (e: any) {\n            log.warn(`cannot end response: ${e}`)\n          }\n          errorOccurred = true\n          this.nativeUpdater.removeListener(\"error\", reject)\n          reject(new Error(`Cannot pipe \"${downloadedFile}\": ${error}`))\n        })\n\n        response.writeHead(200, {\n          \"Content-Type\": \"application/zip\",\n          \"Content-Length\": updateFileSize,\n        })\n        readStream.pipe(response)\n      })\n\n      this.debug(`Proxy server for native Squirrel.Mac is starting to listen (${logContext})`)\n\n      this.server!.listen(0, \"127.0.0.1\", () => {\n        this.debug(`Proxy server for native Squirrel.Mac is listening (address=${getServerUrl(this.server!)}, ${logContext})`)\n        this.nativeUpdater.setFeedURL({\n          url: getServerUrl(this.server!),\n          headers: {\n            \"Cache-Control\": \"no-cache\",\n            Authorization: `Basic ${authInfo.toString(\"base64\")}`,\n          },\n        })\n\n        // The update has been downloaded and is ready to be served to Squirrel\n        this.dispatchUpdateDownloaded(event)\n\n        if (this.autoInstallOnAppQuit) {\n          this.nativeUpdater.once(\"error\", reject)\n          // This will trigger fetching and installing the file on Squirrel side\n          this.nativeUpdater.checkForUpdates()\n        } else {\n          resolve([])\n        }\n      })\n    })\n  }\n\n  private handleUpdateDownloaded() {\n    if (this.autoRunAppAfterInstall) {\n      this.nativeUpdater.quitAndInstall()\n    } else {\n      this.app.quit()\n    }\n    this.closeServerIfExists()\n  }\n\n  quitAndInstall(): void {\n    if (this.squirrelDownloadedUpdate) {\n      // update already fetched by Squirrel, it's ready to install\n      this.handleUpdateDownloaded()\n    } else {\n      // Quit and install as soon as Squirrel get the update\n      this.nativeUpdater.on(\"update-downloaded\", () => this.handleUpdateDownloaded())\n\n      if (!this.autoInstallOnAppQuit) {\n        /**\n         * If this was not `true` previously then MacUpdater.doDownloadUpdate()\n         * would not actually initiate the downloading by electron's autoUpdater\n         */\n        this.nativeUpdater.checkForUpdates()\n      }\n    }\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NsisUpdater = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const path = require("path");
const BaseUpdater_1 = require("./BaseUpdater");
const FileWithEmbeddedBlockMapDifferentialDownloader_1 = require("./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader");
const types_1 = require("./types");
const Provider_1 = require("./providers/Provider");
const fs_extra_1 = require("fs-extra");
const windowsExecutableCodeSignatureVerifier_1 = require("./windowsExecutableCodeSignatureVerifier");
const url_1 = require("url");
class NsisUpdater extends BaseUpdater_1.BaseUpdater {
    constructor(options, app) {
        super(options, app);
        this._verifyUpdateCodeSignature = (publisherNames, unescapedTempUpdateFile) => (0, windowsExecutableCodeSignatureVerifier_1.verifySignature)(publisherNames, unescapedTempUpdateFile, this._logger);
    }
    /**
     * The verifyUpdateCodeSignature. You can pass [win-verify-signature](https://github.com/beyondkmp/win-verify-trust) or another custom verify function: ` (publisherName: string[], path: string) => Promise<string | null>`.
     * The default verify function uses [windowsExecutableCodeSignatureVerifier](https://github.com/electron-userland/electron-builder/blob/master/packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.ts)
     */
    get verifyUpdateCodeSignature() {
        return this._verifyUpdateCodeSignature;
    }
    set verifyUpdateCodeSignature(value) {
        if (value) {
            this._verifyUpdateCodeSignature = value;
        }
    }
    /*** @private */
    doDownloadUpdate(downloadUpdateOptions) {
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const fileInfo = (0, Provider_1.findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "exe");
        return this.executeDownload({
            fileExtension: "exe",
            downloadUpdateOptions,
            fileInfo,
            task: async (destinationFile, downloadOptions, packageFile, removeTempDirIfAny) => {
                const packageInfo = fileInfo.packageInfo;
                const isWebInstaller = packageInfo != null && packageFile != null;
                if (isWebInstaller && downloadUpdateOptions.disableWebInstaller) {
                    throw (0, builder_util_runtime_1.newError)(`Unable to download new version ${downloadUpdateOptions.updateInfoAndProvider.info.version}. Web Installers are disabled`, "ERR_UPDATER_WEB_INSTALLER_DISABLED");
                }
                if (!isWebInstaller && !downloadUpdateOptions.disableWebInstaller) {
                    this._logger.warn("disableWebInstaller is set to false, you should set it to true if you do not plan on using a web installer. This will default to true in a future version.");
                }
                if (isWebInstaller ||
                    downloadUpdateOptions.disableDifferentialDownload ||
                    (await this.differentialDownloadInstaller(fileInfo, downloadUpdateOptions, destinationFile, provider, builder_util_runtime_1.CURRENT_APP_INSTALLER_FILE_NAME))) {
                    await this.httpExecutor.download(fileInfo.url, destinationFile, downloadOptions);
                }
                const signatureVerificationStatus = await this.verifySignature(destinationFile);
                if (signatureVerificationStatus != null) {
                    await removeTempDirIfAny();
                    // noinspection ThrowInsideFinallyBlockJS
                    throw (0, builder_util_runtime_1.newError)(`New version ${downloadUpdateOptions.updateInfoAndProvider.info.version} is not signed by the application owner: ${signatureVerificationStatus}`, "ERR_UPDATER_INVALID_SIGNATURE");
                }
                if (isWebInstaller) {
                    if (await this.differentialDownloadWebPackage(downloadUpdateOptions, packageInfo, packageFile, provider)) {
                        try {
                            await this.httpExecutor.download(new url_1.URL(packageInfo.path), packageFile, {
                                headers: downloadUpdateOptions.requestHeaders,
                                cancellationToken: downloadUpdateOptions.cancellationToken,
                                sha512: packageInfo.sha512,
                            });
                        }
                        catch (e) {
                            try {
                                await (0, fs_extra_1.unlink)(packageFile);
                            }
                            catch (_ignored) {
                                // ignore
                            }
                            throw e;
                        }
                    }
                }
            },
        });
    }
    // $certificateInfo = (Get-AuthenticodeSignature 'xxx\yyy.exe'
    // | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains("CN=siemens.com")})
    // | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }
    async verifySignature(tempUpdateFile) {
        let publisherName;
        try {
            publisherName = (await this.configOnDisk.value).publisherName;
            if (publisherName == null) {
                return null;
            }
        }
        catch (e) {
            if (e.code === "ENOENT") {
                // no app-update.yml
                return null;
            }
            throw e;
        }
        return await this._verifyUpdateCodeSignature(Array.isArray(publisherName) ? publisherName : [publisherName], tempUpdateFile);
    }
    doInstall(options) {
        const installerPath = this.installerPath;
        if (installerPath == null) {
            this.dispatchError(new Error("No update filepath provided, can't quit and install"));
            return false;
        }
        const args = ["--updated"];
        if (options.isSilent) {
            args.push("/S");
        }
        if (options.isForceRunAfter) {
            args.push("--force-run");
        }
        if (this.installDirectory) {
            // maybe check if folder exists
            args.push(`/D=${this.installDirectory}`);
        }
        const packagePath = this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.packageFile;
        if (packagePath != null) {
            // only = form is supported
            args.push(`--package-file=${packagePath}`);
        }
        const callUsingElevation = () => {
            this.spawnLog(path.join(process.resourcesPath, "elevate.exe"), [installerPath].concat(args)).catch(e => this.dispatchError(e));
        };
        if (options.isAdminRightsRequired) {
            this._logger.info("isAdminRightsRequired is set to true, run installer using elevate.exe");
            callUsingElevation();
            return true;
        }
        this.spawnLog(installerPath, args).catch((e) => {
            // https://github.com/electron-userland/electron-builder/issues/1129
            // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors
            const errorCode = e.code;
            this._logger.info(`Cannot run installer: error code: ${errorCode}, error message: "${e.message}", will be executed again using elevate if EACCES, and will try to use electron.shell.openItem if ENOENT`);
            if (errorCode === "UNKNOWN" || errorCode === "EACCES") {
                callUsingElevation();
            }
            else if (errorCode === "ENOENT") {
                require("electron")
                    .shell.openPath(installerPath)
                    .catch((err) => this.dispatchError(err));
            }
            else {
                this.dispatchError(e);
            }
        });
        return true;
    }
    async differentialDownloadWebPackage(downloadUpdateOptions, packageInfo, packagePath, provider) {
        if (packageInfo.blockMapSize == null) {
            return true;
        }
        try {
            const downloadOptions = {
                newUrl: new url_1.URL(packageInfo.path),
                oldFile: path.join(this.downloadedUpdateHelper.cacheDir, builder_util_runtime_1.CURRENT_APP_PACKAGE_FILE_NAME),
                logger: this._logger,
                newFile: packagePath,
                requestHeaders: this.requestHeaders,
                isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,
                cancellationToken: downloadUpdateOptions.cancellationToken,
            };
            if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
            }
            await new FileWithEmbeddedBlockMapDifferentialDownloader_1.FileWithEmbeddedBlockMapDifferentialDownloader(packageInfo, this.httpExecutor, downloadOptions).download();
        }
        catch (e) {
            this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`);
            // during test (developer machine mac or linux) we must throw error
            return process.platform === "win32";
        }
        return false;
    }
}
exports.NsisUpdater = NsisUpdater;
//# sourceMappingURL=NsisUpdater.js.map{"version":3,"file":"NsisUpdater.js","sourceRoot":"","sources":["../src/NsisUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions, newError, PackageFileInfo, CURRENT_APP_INSTALLER_FILE_NAME, CURRENT_APP_PACKAGE_FILE_NAME } from \"builder-util-runtime\"\nimport * as path from \"path\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { BaseUpdater, InstallOptions } from \"./BaseUpdater\"\nimport { DifferentialDownloaderOptions } from \"./differentialDownloader/DifferentialDownloader\"\nimport { FileWithEmbeddedBlockMapDifferentialDownloader } from \"./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader\"\nimport { DOWNLOAD_PROGRESS } from \"./types\"\nimport { VerifyUpdateCodeSignature } from \"./main\"\nimport { findFile, Provider } from \"./providers/Provider\"\nimport { unlink } from \"fs-extra\"\nimport { verifySignature } from \"./windowsExecutableCodeSignatureVerifier\"\nimport { URL } from \"url\"\n\nexport class NsisUpdater extends BaseUpdater {\n  /**\n   * Specify custom install directory path\n   *\n   */\n  installDirectory?: string\n\n  constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  protected _verifyUpdateCodeSignature: VerifyUpdateCodeSignature = (publisherNames: Array<string>, unescapedTempUpdateFile: string) =>\n    verifySignature(publisherNames, unescapedTempUpdateFile, this._logger)\n\n  /**\n   * The verifyUpdateCodeSignature. You can pass [win-verify-signature](https://github.com/beyondkmp/win-verify-trust) or another custom verify function: ` (publisherName: string[], path: string) => Promise<string | null>`.\n   * The default verify function uses [windowsExecutableCodeSignatureVerifier](https://github.com/electron-userland/electron-builder/blob/master/packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.ts)\n   */\n  get verifyUpdateCodeSignature(): VerifyUpdateCodeSignature {\n    return this._verifyUpdateCodeSignature\n  }\n\n  set verifyUpdateCodeSignature(value: VerifyUpdateCodeSignature) {\n    if (value) {\n      this._verifyUpdateCodeSignature = value\n    }\n  }\n\n  /*** @private */\n  protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"exe\")!\n    return this.executeDownload({\n      fileExtension: \"exe\",\n      downloadUpdateOptions,\n      fileInfo,\n      task: async (destinationFile, downloadOptions, packageFile, removeTempDirIfAny) => {\n        const packageInfo = fileInfo.packageInfo\n        const isWebInstaller = packageInfo != null && packageFile != null\n        if (isWebInstaller && downloadUpdateOptions.disableWebInstaller) {\n          throw newError(\n            `Unable to download new version ${downloadUpdateOptions.updateInfoAndProvider.info.version}. Web Installers are disabled`,\n            \"ERR_UPDATER_WEB_INSTALLER_DISABLED\"\n          )\n        }\n        if (!isWebInstaller && !downloadUpdateOptions.disableWebInstaller) {\n          this._logger.warn(\n            \"disableWebInstaller is set to false, you should set it to true if you do not plan on using a web installer. This will default to true in a future version.\"\n          )\n        }\n        if (\n          isWebInstaller ||\n          downloadUpdateOptions.disableDifferentialDownload ||\n          (await this.differentialDownloadInstaller(fileInfo, downloadUpdateOptions, destinationFile, provider, CURRENT_APP_INSTALLER_FILE_NAME))\n        ) {\n          await this.httpExecutor.download(fileInfo.url, destinationFile, downloadOptions)\n        }\n\n        const signatureVerificationStatus = await this.verifySignature(destinationFile)\n        if (signatureVerificationStatus != null) {\n          await removeTempDirIfAny()\n          // noinspection ThrowInsideFinallyBlockJS\n          throw newError(\n            `New version ${downloadUpdateOptions.updateInfoAndProvider.info.version} is not signed by the application owner: ${signatureVerificationStatus}`,\n            \"ERR_UPDATER_INVALID_SIGNATURE\"\n          )\n        }\n\n        if (isWebInstaller) {\n          if (await this.differentialDownloadWebPackage(downloadUpdateOptions, packageInfo, packageFile, provider)) {\n            try {\n              await this.httpExecutor.download(new URL(packageInfo.path), packageFile, {\n                headers: downloadUpdateOptions.requestHeaders,\n                cancellationToken: downloadUpdateOptions.cancellationToken,\n                sha512: packageInfo.sha512,\n              })\n            } catch (e: any) {\n              try {\n                await unlink(packageFile)\n              } catch (_ignored) {\n                // ignore\n              }\n\n              throw e\n            }\n          }\n        }\n      },\n    })\n  }\n\n  // $certificateInfo = (Get-AuthenticodeSignature 'xxx\\yyy.exe'\n  // | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains(\"CN=siemens.com\")})\n  // | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }\n  private async verifySignature(tempUpdateFile: string): Promise<string | null> {\n    let publisherName: Array<string> | string | null\n    try {\n      publisherName = (await this.configOnDisk.value).publisherName\n      if (publisherName == null) {\n        return null\n      }\n    } catch (e: any) {\n      if (e.code === \"ENOENT\") {\n        // no app-update.yml\n        return null\n      }\n      throw e\n    }\n    return await this._verifyUpdateCodeSignature(Array.isArray(publisherName) ? publisherName : [publisherName], tempUpdateFile)\n  }\n\n  protected doInstall(options: InstallOptions): boolean {\n    const installerPath = this.installerPath\n    if (installerPath == null) {\n      this.dispatchError(new Error(\"No update filepath provided, can't quit and install\"))\n      return false\n    }\n\n    const args = [\"--updated\"]\n    if (options.isSilent) {\n      args.push(\"/S\")\n    }\n\n    if (options.isForceRunAfter) {\n      args.push(\"--force-run\")\n    }\n\n    if (this.installDirectory) {\n      // maybe check if folder exists\n      args.push(`/D=${this.installDirectory}`)\n    }\n\n    const packagePath = this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.packageFile\n    if (packagePath != null) {\n      // only = form is supported\n      args.push(`--package-file=${packagePath}`)\n    }\n\n    const callUsingElevation = (): void => {\n      this.spawnLog(path.join(process.resourcesPath, \"elevate.exe\"), [installerPath].concat(args)).catch(e => this.dispatchError(e))\n    }\n\n    if (options.isAdminRightsRequired) {\n      this._logger.info(\"isAdminRightsRequired is set to true, run installer using elevate.exe\")\n      callUsingElevation()\n      return true\n    }\n\n    this.spawnLog(installerPath, args).catch((e: Error) => {\n      // https://github.com/electron-userland/electron-builder/issues/1129\n      // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors\n      const errorCode = (e as NodeJS.ErrnoException).code\n      this._logger.info(\n        `Cannot run installer: error code: ${errorCode}, error message: \"${e.message}\", will be executed again using elevate if EACCES, and will try to use electron.shell.openItem if ENOENT`\n      )\n      if (errorCode === \"UNKNOWN\" || errorCode === \"EACCES\") {\n        callUsingElevation()\n      } else if (errorCode === \"ENOENT\") {\n        require(\"electron\")\n          .shell.openPath(installerPath)\n          .catch((err: Error) => this.dispatchError(err))\n      } else {\n        this.dispatchError(e)\n      }\n    })\n    return true\n  }\n\n  private async differentialDownloadWebPackage(\n    downloadUpdateOptions: DownloadUpdateOptions,\n    packageInfo: PackageFileInfo,\n    packagePath: string,\n    provider: Provider<any>\n  ): Promise<boolean> {\n    if (packageInfo.blockMapSize == null) {\n      return true\n    }\n\n    try {\n      const downloadOptions: DifferentialDownloaderOptions = {\n        newUrl: new URL(packageInfo.path),\n        oldFile: path.join(this.downloadedUpdateHelper!.cacheDir, CURRENT_APP_PACKAGE_FILE_NAME),\n        logger: this._logger,\n        newFile: packagePath,\n        requestHeaders: this.requestHeaders,\n        isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,\n        cancellationToken: downloadUpdateOptions.cancellationToken,\n      }\n\n      if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n        downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n      }\n\n      await new FileWithEmbeddedBlockMapDifferentialDownloader(packageInfo, this.httpExecutor, downloadOptions).download()\n    } catch (e: any) {\n      this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`)\n      // during test (developer machine mac or linux) we must throw error\n      return process.platform === \"win32\"\n    }\n    return false\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PacmanUpdater = void 0;
const types_1 = require("./types");
const Provider_1 = require("./providers/Provider");
const LinuxUpdater_1 = require("./LinuxUpdater");
class PacmanUpdater extends LinuxUpdater_1.LinuxUpdater {
    constructor(options, app) {
        super(options, app);
    }
    /*** @private */
    doDownloadUpdate(downloadUpdateOptions) {
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const fileInfo = (0, Provider_1.findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "pacman", ["AppImage", "deb", "rpm"]);
        return this.executeDownload({
            fileExtension: "pacman",
            fileInfo,
            downloadUpdateOptions,
            task: async (updateFile, downloadOptions) => {
                if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                    downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
                }
                await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions);
            },
        });
    }
    doInstall(options) {
        const installerPath = this.installerPath;
        if (installerPath == null) {
            this.dispatchError(new Error("No update filepath provided, can't quit and install"));
            return false;
        }
        try {
            PacmanUpdater.installWithCommandRunner(installerPath, this.runCommandWithSudoIfNeeded.bind(this), this._logger);
        }
        catch (error) {
            this.dispatchError(error);
            return false;
        }
        if (options.isForceRunAfter) {
            this.app.relaunch(); // note: `app` is undefined in tests since vite doesn't run in electron
        }
        return true;
    }
    static installWithCommandRunner(installerPath, commandRunner, logger) {
        var _a;
        try {
            commandRunner(["pacman", "-U", "--noconfirm", installerPath]);
        }
        catch (error) {
            logger.warn((_a = error.message) !== null && _a !== void 0 ? _a : error);
            logger.warn("pacman installation failed, attempting to update package database and retry");
            try {
                // Update package database (not a full upgrade, just sync)
                commandRunner(["pacman", "-Sy", "--noconfirm"]);
                // Retry installation
                commandRunner(["pacman", "-U", "--noconfirm", installerPath]);
            }
            catch (retryError) {
                logger.error("Retry after pacman -Sy failed");
                throw retryError;
            }
        }
    }
}
exports.PacmanUpdater = PacmanUpdater;
//# sourceMappingURL=PacmanUpdater.js.map{"version":3,"file":"PacmanUpdater.js","sourceRoot":"","sources":["../src/PacmanUpdater.ts"],"names":[],"mappings":";;;AAIA,mCAAmD;AACnD,mDAA+C;AAC/C,iDAA6C;AAE7C,MAAa,aAAc,SAAQ,2BAAY;IAC7C,YAAY,OAAkC,EAAE,GAAgB;QAC9D,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IACrB,CAAC;IAED,gBAAgB;IACN,gBAAgB,CAAC,qBAA4C;QACrE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,qBAAqB,CAAC,QAAQ,CAAA;QACrE,MAAM,QAAQ,GAAG,IAAA,mBAAQ,EAAC,QAAQ,CAAC,YAAY,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,CAAE,CAAA;QACzI,OAAO,IAAI,CAAC,eAAe,CAAC;YAC1B,aAAa,EAAE,QAAQ;YACvB,QAAQ;YACR,qBAAqB;YACrB,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,EAAE;gBAC1C,IAAI,IAAI,CAAC,aAAa,CAAC,yBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9C,eAAe,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,EAAE,CAAC,CAAA;gBACrE,CAAC;gBACD,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,eAAe,CAAC,CAAA;YAC7E,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IAES,SAAS,CAAC,OAAuB;QACzC,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAA;QACxC,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC,CAAA;YACpF,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,CAAC;YACH,aAAa,CAAC,wBAAwB,CAAC,aAAa,EAAE,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QACjH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;YACzB,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA,CAAC,uEAAuE;QAC7F,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,aAAqB,EAAE,aAAkD,EAAE,MAAc;;QACvH,IAAI,CAAC;YACH,aAAa,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAA;QAC/D,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,MAAA,KAAK,CAAC,OAAO,mCAAI,KAAK,CAAC,CAAA;YACnC,MAAM,CAAC,IAAI,CAAC,6EAA6E,CAAC,CAAA;YAE1F,IAAI,CAAC;gBACH,0DAA0D;gBAC1D,aAAa,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAA;gBAC/C,qBAAqB;gBACrB,aAAa,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAA;YAC/D,CAAC;YAAC,OAAO,UAAe,EAAE,CAAC;gBACzB,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAA;gBAC7C,MAAM,UAAU,CAAA;YAClB,CAAC;QACH,CAAC;IACH,CAAC;CACF;AA1DD,sCA0DC","sourcesContent":["import { AllPublishOptions } from \"builder-util-runtime\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { InstallOptions } from \"./BaseUpdater\"\nimport { DOWNLOAD_PROGRESS, Logger } from \"./types\"\nimport { findFile } from \"./providers/Provider\"\nimport { LinuxUpdater } from \"./LinuxUpdater\"\n\nexport class PacmanUpdater extends LinuxUpdater {\n  constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  /*** @private */\n  protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"pacman\", [\"AppImage\", \"deb\", \"rpm\"])!\n    return this.executeDownload({\n      fileExtension: \"pacman\",\n      fileInfo,\n      downloadUpdateOptions,\n      task: async (updateFile, downloadOptions) => {\n        if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n          downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n        }\n        await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions)\n      },\n    })\n  }\n\n  protected doInstall(options: InstallOptions): boolean {\n    const installerPath = this.installerPath\n    if (installerPath == null) {\n      this.dispatchError(new Error(\"No update filepath provided, can't quit and install\"))\n      return false\n    }\n    try {\n      PacmanUpdater.installWithCommandRunner(installerPath, this.runCommandWithSudoIfNeeded.bind(this), this._logger)\n    } catch (error: any) {\n      this.dispatchError(error)\n      return false\n    }\n    if (options.isForceRunAfter) {\n      this.app.relaunch() // note: `app` is undefined in tests since vite doesn't run in electron\n    }\n    return true\n  }\n\n  static installWithCommandRunner(installerPath: string, commandRunner: (commandWithArgs: string[]) => void, logger: Logger) {\n    try {\n      commandRunner([\"pacman\", \"-U\", \"--noconfirm\", installerPath])\n    } catch (error: any) {\n      logger.warn(error.message ?? error)\n      logger.warn(\"pacman installation failed, attempting to update package database and retry\")\n\n      try {\n        // Update package database (not a full upgrade, just sync)\n        commandRunner([\"pacman\", \"-Sy\", \"--noconfirm\"])\n        // Retry installation\n        commandRunner([\"pacman\", \"-U\", \"--noconfirm\", installerPath])\n      } catch (retryError: any) {\n        logger.error(\"Retry after pacman -Sy failed\")\n        throw retryError\n      }\n    }\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RpmUpdater = void 0;
const types_1 = require("./types");
const Provider_1 = require("./providers/Provider");
const LinuxUpdater_1 = require("./LinuxUpdater");
class RpmUpdater extends LinuxUpdater_1.LinuxUpdater {
    constructor(options, app) {
        super(options, app);
    }
    /*** @private */
    doDownloadUpdate(downloadUpdateOptions) {
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const fileInfo = (0, Provider_1.findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "rpm", ["AppImage", "deb", "pacman"]);
        return this.executeDownload({
            fileExtension: "rpm",
            fileInfo,
            downloadUpdateOptions,
            task: async (updateFile, downloadOptions) => {
                if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                    downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
                }
                await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions);
            },
        });
    }
    doInstall(options) {
        const installerPath = this.installerPath;
        if (installerPath == null) {
            this.dispatchError(new Error("No update filepath provided, can't quit and install"));
            return false;
        }
        const priorityList = ["zypper", "dnf", "yum", "rpm"];
        const packageManager = this.detectPackageManager(priorityList);
        try {
            RpmUpdater.installWithCommandRunner(packageManager, installerPath, this.runCommandWithSudoIfNeeded.bind(this), this._logger);
        }
        catch (error) {
            this.dispatchError(error);
            return false;
        }
        if (options.isForceRunAfter) {
            this.app.relaunch();
        }
        return true;
    }
    static installWithCommandRunner(packageManager, installerPath, commandRunner, logger) {
        if (packageManager === "zypper") {
            return commandRunner(["zypper", "--non-interactive", "--no-refresh", "install", "--allow-unsigned-rpm", "-f", installerPath]);
        }
        if (packageManager === "dnf") {
            return commandRunner(["dnf", "install", "--nogpgcheck", "-y", installerPath]);
        }
        if (packageManager === "yum") {
            return commandRunner(["yum", "install", "--nogpgcheck", "-y", installerPath]);
        }
        if (packageManager === "rpm") {
            logger.warn("Installing with rpm only (no dependency resolution).");
            return commandRunner(["rpm", "-Uvh", "--replacepkgs", "--replacefiles", "--nodeps", installerPath]);
        }
        throw new Error(`Package manager ${packageManager} not supported`);
    }
}
exports.RpmUpdater = RpmUpdater;
//# sourceMappingURL=RpmUpdater.js.map{"version":3,"file":"RpmUpdater.js","sourceRoot":"","sources":["../src/RpmUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions } from \"builder-util-runtime\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { InstallOptions } from \"./BaseUpdater\"\nimport { DOWNLOAD_PROGRESS, Logger } from \"./types\"\nimport { findFile } from \"./providers/Provider\"\nimport { LinuxUpdater } from \"./LinuxUpdater\"\n\nexport class RpmUpdater extends LinuxUpdater {\n  constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  /*** @private */\n  protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"rpm\", [\"AppImage\", \"deb\", \"pacman\"])!\n    return this.executeDownload({\n      fileExtension: \"rpm\",\n      fileInfo,\n      downloadUpdateOptions,\n      task: async (updateFile, downloadOptions) => {\n        if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n          downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n        }\n        await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions)\n      },\n    })\n  }\n\n  protected doInstall(options: InstallOptions): boolean {\n    const installerPath = this.installerPath\n    if (installerPath == null) {\n      this.dispatchError(new Error(\"No update filepath provided, can't quit and install\"))\n      return false\n    }\n\n    const priorityList = [\"zypper\", \"dnf\", \"yum\", \"rpm\"]\n    const packageManager = this.detectPackageManager(priorityList)\n    try {\n      RpmUpdater.installWithCommandRunner(packageManager as any, installerPath, this.runCommandWithSudoIfNeeded.bind(this), this._logger)\n    } catch (error: any) {\n      this.dispatchError(error)\n      return false\n    }\n    if (options.isForceRunAfter) {\n      this.app.relaunch()\n    }\n    return true\n  }\n\n  static installWithCommandRunner(packageManager: \"zypper\" | \"dnf\" | \"yum\" | \"rpm\", installerPath: string, commandRunner: (commandWithArgs: string[]) => void, logger: Logger) {\n    if (packageManager === \"zypper\") {\n      return commandRunner([\"zypper\", \"--non-interactive\", \"--no-refresh\", \"install\", \"--allow-unsigned-rpm\", \"-f\", installerPath])\n    }\n    if (packageManager === \"dnf\") {\n      return commandRunner([\"dnf\", \"install\", \"--nogpgcheck\", \"-y\", installerPath])\n    }\n    if (packageManager === \"yum\") {\n      return commandRunner([\"yum\", \"install\", \"--nogpgcheck\", \"-y\", installerPath])\n    }\n    if (packageManager === \"rpm\") {\n      logger.warn(\"Installing with rpm only (no dependency resolution).\")\n      return commandRunner([\"rpm\", \"-Uvh\", \"--replacepkgs\", \"--replacefiles\", \"--nodeps\", installerPath])\n    }\n    throw new Error(`Package manager ${packageManager} not supported`)\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ElectronHttpExecutor = exports.NET_SESSION_NAME = void 0;
exports.getNetSession = getNetSession;
const builder_util_runtime_1 = require("builder-util-runtime");
exports.NET_SESSION_NAME = "electron-updater";
function getNetSession() {
    return require("electron").session.fromPartition(exports.NET_SESSION_NAME, {
        cache: false,
    });
}
class ElectronHttpExecutor extends builder_util_runtime_1.HttpExecutor {
    constructor(proxyLoginCallback) {
        super();
        this.proxyLoginCallback = proxyLoginCallback;
        this.cachedSession = null;
    }
    async download(url, destination, options) {
        return await options.cancellationToken.createPromise((resolve, reject, onCancel) => {
            const requestOptions = {
                headers: options.headers || undefined,
                redirect: "manual",
            };
            (0, builder_util_runtime_1.configureRequestUrl)(url, requestOptions);
            (0, builder_util_runtime_1.configureRequestOptions)(requestOptions);
            this.doDownload(requestOptions, {
                destination,
                options,
                onCancel,
                callback: error => {
                    if (error == null) {
                        resolve(destination);
                    }
                    else {
                        reject(error);
                    }
                },
                responseHandler: null,
            }, 0);
        });
    }
    createRequest(options, callback) {
        // fix (node 7+) for making electron updater work when using AWS private buckets, check if headers contain Host property
        if (options.headers && options.headers.Host) {
            // set host value from headers.Host
            options.host = options.headers.Host;
            // remove header property 'Host', if not removed causes net::ERR_INVALID_ARGUMENT exception
            delete options.headers.Host;
        }
        // differential downloader can call this method very often, so, better to cache session
        if (this.cachedSession == null) {
            this.cachedSession = getNetSession();
        }
        const request = require("electron").net.request({
            ...options,
            session: this.cachedSession,
        });
        request.on("response", callback);
        if (this.proxyLoginCallback != null) {
            request.on("login", this.proxyLoginCallback);
        }
        return request;
    }
    addRedirectHandlers(request, options, reject, redirectCount, handler) {
        request.on("redirect", (statusCode, method, redirectUrl) => {
            // no way to modify request options, abort old and make a new one
            // https://github.com/electron/electron/issues/11505
            request.abort();
            if (redirectCount > this.maxRedirects) {
                reject(this.createMaxRedirectError());
            }
            else {
                handler(builder_util_runtime_1.HttpExecutor.prepareRedirectUrlOptions(redirectUrl, options));
            }
        });
    }
}
exports.ElectronHttpExecutor = ElectronHttpExecutor;
//# sourceMappingURL=electronHttpExecutor.js.map{"version":3,"file":"electronHttpExecutor.js","sourceRoot":"","sources":["../src/electronHttpExecutor.ts"],"names":[],"mappings":"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","sourcesContent":["import { DownloadOptions, HttpExecutor, configureRequestOptions, configureRequestUrl } from \"builder-util-runtime\"\nimport type { AuthInfo } from \"electron\"\nimport { RequestOptions } from \"http\"\nimport Session = Electron.Session\nimport ClientRequest = Electron.ClientRequest\n\nexport type LoginCallback = (username: string, password: string) => void\nexport const NET_SESSION_NAME = \"electron-updater\"\n\nexport function getNetSession(): Session {\n  return require(\"electron\").session.fromPartition(NET_SESSION_NAME, {\n    cache: false,\n  })\n}\n\nexport class ElectronHttpExecutor extends HttpExecutor<Electron.ClientRequest> {\n  private cachedSession: Session | null = null\n\n  constructor(private readonly proxyLoginCallback?: (authInfo: AuthInfo, callback: LoginCallback) => void) {\n    super()\n  }\n\n  async download(url: URL, destination: string, options: DownloadOptions): Promise<string> {\n    return await options.cancellationToken.createPromise<string>((resolve, reject, onCancel) => {\n      const requestOptions = {\n        headers: options.headers || undefined,\n        redirect: \"manual\",\n      }\n      configureRequestUrl(url, requestOptions)\n      configureRequestOptions(requestOptions)\n      this.doDownload(\n        requestOptions,\n        {\n          destination,\n          options,\n          onCancel,\n          callback: error => {\n            if (error == null) {\n              resolve(destination)\n            } else {\n              reject(error)\n            }\n          },\n          responseHandler: null,\n        },\n        0\n      )\n    })\n  }\n\n  createRequest(options: any, callback: (response: any) => void): Electron.ClientRequest {\n    // fix (node 7+) for making electron updater work when using AWS private buckets, check if headers contain Host property\n    if (options.headers && options.headers.Host) {\n      // set host value from headers.Host\n      options.host = options.headers.Host\n      // remove header property 'Host', if not removed causes net::ERR_INVALID_ARGUMENT exception\n      delete options.headers.Host\n    }\n\n    // differential downloader can call this method very often, so, better to cache session\n    if (this.cachedSession == null) {\n      this.cachedSession = getNetSession()\n    }\n\n    const request = require(\"electron\").net.request({\n      ...options,\n      session: this.cachedSession,\n    })\n    request.on(\"response\", callback)\n    if (this.proxyLoginCallback != null) {\n      request.on(\"login\", this.proxyLoginCallback)\n    }\n    return request\n  }\n\n  protected addRedirectHandlers(\n    request: ClientRequest,\n    options: RequestOptions,\n    reject: (error: Error) => void,\n    redirectCount: number,\n    handler: (options: RequestOptions) => void\n  ): void {\n    request.on(\"redirect\", (statusCode: number, method: string, redirectUrl: string) => {\n      // no way to modify request options, abort old and make a new one\n      // https://github.com/electron/electron/issues/11505\n      request.abort()\n\n      if (redirectCount > this.maxRedirects) {\n        reject(this.createMaxRedirectError())\n      } else {\n        handler(HttpExecutor.prepareRedirectUrlOptions(redirectUrl, options))\n      }\n    })\n  }\n}\n"]}"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NsisUpdater = exports.MacUpdater = exports.RpmUpdater = exports.PacmanUpdater = exports.DebUpdater = exports.AppImageUpdater = exports.Provider = exports.NoOpLogger = exports.AppUpdater = exports.BaseUpdater = void 0;
const fs_extra_1 = require("fs-extra");
const path = require("path");
var BaseUpdater_1 = require("./BaseUpdater");
Object.defineProperty(exports, "BaseUpdater", { enumerable: true, get: function () { return BaseUpdater_1.BaseUpdater; } });
var AppUpdater_1 = require("./AppUpdater");
Object.defineProperty(exports, "AppUpdater", { enumerable: true, get: function () { return AppUpdater_1.AppUpdater; } });
Object.defineProperty(exports, "NoOpLogger", { enumerable: true, get: function () { return AppUpdater_1.NoOpLogger; } });
var Provider_1 = require("./providers/Provider");
Object.defineProperty(exports, "Provider", { enumerable: true, get: function () { return Provider_1.Provider; } });
var AppImageUpdater_1 = require("./AppImageUpdater");
Object.defineProperty(exports, "AppImageUpdater", { enumerable: true, get: function () { return AppImageUpdater_1.AppImageUpdater; } });
var DebUpdater_1 = require("./DebUpdater");
Object.defineProperty(exports, "DebUpdater", { enumerable: true, get: function () { return DebUpdater_1.DebUpdater; } });
var PacmanUpdater_1 = require("./PacmanUpdater");
Object.defineProperty(exports, "PacmanUpdater", { enumerable: true, get: function () { return PacmanUpdater_1.PacmanUpdater; } });
var RpmUpdater_1 = require("./RpmUpdater");
Object.defineProperty(exports, "RpmUpdater", { enumerable: true, get: function () { return RpmUpdater_1.RpmUpdater; } });
var MacUpdater_1 = require("./MacUpdater");
Object.defineProperty(exports, "MacUpdater", { enumerable: true, get: function () { return MacUpdater_1.MacUpdater; } });
var NsisUpdater_1 = require("./NsisUpdater");
Object.defineProperty(exports, "NsisUpdater", { enumerable: true, get: function () { return NsisUpdater_1.NsisUpdater; } });
__exportStar(require("./types"), exports);
// autoUpdater to mimic electron bundled autoUpdater
let _autoUpdater;
function doLoadAutoUpdater() {
    // tslint:disable:prefer-conditional-expression
    if (process.platform === "win32") {
        _autoUpdater = new (require("./NsisUpdater").NsisUpdater)();
    }
    else if (process.platform === "darwin") {
        _autoUpdater = new (require("./MacUpdater").MacUpdater)();
    }
    else {
        _autoUpdater = new (require("./AppImageUpdater").AppImageUpdater)();
        try {
            const identity = path.join(process.resourcesPath, "package-type");
            if (!(0, fs_extra_1.existsSync)(identity)) {
                return _autoUpdater;
            }
            const fileType = (0, fs_extra_1.readFileSync)(identity).toString().trim();
            switch (fileType) {
                case "deb":
                    _autoUpdater = new (require("./DebUpdater").DebUpdater)();
                    break;
                case "rpm":
                    _autoUpdater = new (require("./RpmUpdater").RpmUpdater)();
                    break;
                case "pacman":
                    _autoUpdater = new (require("./PacmanUpdater").PacmanUpdater)();
                    break;
                default:
                    break;
            }
        }
        catch (error) {
            console.warn("Unable to detect 'package-type' for autoUpdater (rpm/deb/pacman support). If you'd like to expand support, please consider contributing to electron-builder", error.message);
        }
    }
    return _autoUpdater;
}
Object.defineProperty(exports, "autoUpdater", {
    enumerable: true,
    get: () => {
        return _autoUpdater || doLoadAutoUpdater();
    },
});
//# sourceMappingURL=main.js.map{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uCAAmD;AACnD,6BAA4B;AAI5B,6CAA2C;AAAlC,0GAAA,WAAW,OAAA;AACpB,2CAAqD;AAA5C,wGAAA,UAAU,OAAA;AAAE,wGAAA,UAAU,OAAA;AAC/B,iDAA+C;AAAtC,oGAAA,QAAQ,OAAA;AACjB,qDAAmD;AAA1C,kHAAA,eAAe,OAAA;AACxB,2CAAyC;AAAhC,wGAAA,UAAU,OAAA;AACnB,iDAA+C;AAAtC,8GAAA,aAAa,OAAA;AACtB,2CAAyC;AAAhC,wGAAA,UAAU,OAAA;AACnB,2CAAyC;AAAhC,wGAAA,UAAU,OAAA;AACnB,6CAA2C;AAAlC,0GAAA,WAAW,OAAA;AAEpB,0CAAuB;AAEvB,oDAAoD;AACpD,IAAI,YAAiB,CAAA;AAKrB,SAAS,iBAAiB;IACxB,+CAA+C;IAC/C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,WAAW,CAAC,EAAE,CAAA;IAC7D,CAAC;SAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACzC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,CAAA;IAC3D,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,eAAe,CAAC,EAAE,CAAA;QACnE,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,cAAc,CAAC,CAAA;YACjE,IAAI,CAAC,IAAA,qBAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;gBAC1B,OAAO,YAAY,CAAA;YACrB,CAAC;YACD,MAAM,QAAQ,GAAG,IAAA,uBAAY,EAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAA;YACzD,QAAQ,QAAQ,EAAE,CAAC;gBACjB,KAAK,KAAK;oBACR,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,CAAA;oBACzD,MAAK;gBACP,KAAK,KAAK;oBACR,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,CAAA;oBACzD,MAAK;gBACP,KAAK,QAAQ;oBACX,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,aAAa,CAAC,EAAE,CAAA;oBAC/D,MAAK;gBACP;oBACE,MAAK;YACT,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CACV,6JAA6J,EAC7J,KAAK,CAAC,OAAO,CACd,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE;IAC5C,UAAU,EAAE,IAAI;IAChB,GAAG,EAAE,GAAG,EAAE;QACR,OAAO,YAAY,IAAI,iBAAiB,EAAE,CAAA;IAC5C,CAAC;CACF,CAAC,CAAA","sourcesContent":["import { existsSync, readFileSync } from \"fs-extra\"\nimport * as path from \"path\"\nimport { AppUpdater } from \"./AppUpdater\"\nimport { UpdateInfo } from \"builder-util-runtime\"\n\nexport { BaseUpdater } from \"./BaseUpdater\"\nexport { AppUpdater, NoOpLogger } from \"./AppUpdater\"\nexport { Provider } from \"./providers/Provider\"\nexport { AppImageUpdater } from \"./AppImageUpdater\"\nexport { DebUpdater } from \"./DebUpdater\"\nexport { PacmanUpdater } from \"./PacmanUpdater\"\nexport { RpmUpdater } from \"./RpmUpdater\"\nexport { MacUpdater } from \"./MacUpdater\"\nexport { NsisUpdater } from \"./NsisUpdater\"\n\nexport * from \"./types\"\n\n// autoUpdater to mimic electron bundled autoUpdater\nlet _autoUpdater: any\n\n// required for jsdoc\nexport declare const autoUpdater: AppUpdater\n\nfunction doLoadAutoUpdater(): AppUpdater {\n  // tslint:disable:prefer-conditional-expression\n  if (process.platform === \"win32\") {\n    _autoUpdater = new (require(\"./NsisUpdater\").NsisUpdater)()\n  } else if (process.platform === \"darwin\") {\n    _autoUpdater = new (require(\"./MacUpdater\").MacUpdater)()\n  } else {\n    _autoUpdater = new (require(\"./AppImageUpdater\").AppImageUpdater)()\n    try {\n      const identity = path.join(process.resourcesPath, \"package-type\")\n      if (!existsSync(identity)) {\n        return _autoUpdater\n      }\n      const fileType = readFileSync(identity).toString().trim()\n      switch (fileType) {\n        case \"deb\":\n          _autoUpdater = new (require(\"./DebUpdater\").DebUpdater)()\n          break\n        case \"rpm\":\n          _autoUpdater = new (require(\"./RpmUpdater\").RpmUpdater)()\n          break\n        case \"pacman\":\n          _autoUpdater = new (require(\"./PacmanUpdater\").PacmanUpdater)()\n          break\n        default:\n          break\n      }\n    } catch (error: any) {\n      console.warn(\n        \"Unable to detect 'package-type' for autoUpdater (rpm/deb/pacman support). If you'd like to expand support, please consider contributing to electron-builder\",\n        error.message\n      )\n    }\n  }\n  return _autoUpdater\n}\n\nObject.defineProperty(exports, \"autoUpdater\", {\n  enumerable: true,\n  get: () => {\n    return _autoUpdater || doLoadAutoUpdater()\n  },\n})\n\n/**\n * return null if verify signature succeed\n * return error message if verify signature failed\n */\nexport type VerifyUpdateCodeSignature = (publisherName: string[], path: string) => Promise<string | null>\n\nexport type VerifyUpdateSupport = (updateInfo: UpdateInfo) => boolean | Promise<boolean>\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isUrlProbablySupportMultiRangeRequests = isUrlProbablySupportMultiRangeRequests;
exports.createClient = createClient;
const builder_util_runtime_1 = require("builder-util-runtime");
const BitbucketProvider_1 = require("./providers/BitbucketProvider");
const GenericProvider_1 = require("./providers/GenericProvider");
const GitHubProvider_1 = require("./providers/GitHubProvider");
const GitLabProvider_1 = require("./providers/GitLabProvider");
const KeygenProvider_1 = require("./providers/KeygenProvider");
const PrivateGitHubProvider_1 = require("./providers/PrivateGitHubProvider");
function isUrlProbablySupportMultiRangeRequests(url) {
    return !url.includes("s3.amazonaws.com");
}
function createClient(data, updater, runtimeOptions) {
    // noinspection SuspiciousTypeOfGuard
    if (typeof data === "string") {
        throw (0, builder_util_runtime_1.newError)("Please pass PublishConfiguration object", "ERR_UPDATER_INVALID_PROVIDER_CONFIGURATION");
    }
    const provider = data.provider;
    switch (provider) {
        case "github": {
            const githubOptions = data;
            const token = (githubOptions.private ? process.env["GH_TOKEN"] || process.env["GITHUB_TOKEN"] : null) || githubOptions.token;
            if (token == null) {
                return new GitHubProvider_1.GitHubProvider(githubOptions, updater, runtimeOptions);
            }
            else {
                return new PrivateGitHubProvider_1.PrivateGitHubProvider(githubOptions, updater, token, runtimeOptions);
            }
        }
        case "bitbucket":
            return new BitbucketProvider_1.BitbucketProvider(data, updater, runtimeOptions);
        case "gitlab":
            return new GitLabProvider_1.GitLabProvider(data, updater, runtimeOptions);
        case "keygen":
            return new KeygenProvider_1.KeygenProvider(data, updater, runtimeOptions);
        case "s3":
        case "spaces":
            return new GenericProvider_1.GenericProvider({
                provider: "generic",
                url: (0, builder_util_runtime_1.getS3LikeProviderBaseUrl)(data),
                channel: data.channel || null,
            }, updater, {
                ...runtimeOptions,
                // https://github.com/minio/minio/issues/5285#issuecomment-350428955
                isUseMultipleRangeRequest: false,
            });
        case "generic": {
            const options = data;
            return new GenericProvider_1.GenericProvider(options, updater, {
                ...runtimeOptions,
                isUseMultipleRangeRequest: options.useMultipleRangeRequest !== false && isUrlProbablySupportMultiRangeRequests(options.url),
            });
        }
        case "custom": {
            const options = data;
            const constructor = options.updateProvider;
            if (!constructor) {
                throw (0, builder_util_runtime_1.newError)("Custom provider not specified", "ERR_UPDATER_INVALID_PROVIDER_CONFIGURATION");
            }
            return new constructor(options, updater, runtimeOptions);
        }
        default:
            throw (0, builder_util_runtime_1.newError)(`Unsupported provider: ${provider}`, "ERR_UPDATER_UNSUPPORTED_PROVIDER");
    }
}
//# sourceMappingURL=providerFactory.js.map{"version":3,"file":"providerFactory.js","sourceRoot":"","sources":["../src/providerFactory.ts"],"names":[],"mappings":";;AAsBA,wFAEC;AAED,oCA+DC;AAzFD,+DAY6B;AAE7B,qEAAiE;AACjE,iEAA6D;AAC7D,+DAA2D;AAC3D,+DAA2D;AAC3D,+DAA2D;AAC3D,6EAAyE;AAGzE,SAAgB,sCAAsC,CAAC,GAAW;IAChE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAA;AAC1C,CAAC;AAED,SAAgB,YAAY,CAAC,IAA8C,EAAE,OAAmB,EAAE,cAAsC;IACtI,qCAAqC;IACrC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAA,+BAAQ,EAAC,yCAAyC,EAAE,4CAA4C,CAAC,CAAA;IACzG,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;IAC9B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,aAAa,GAAG,IAAqB,CAAA;YAC3C,MAAM,KAAK,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,KAAK,CAAA;YAC5H,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;gBAClB,OAAO,IAAI,+BAAc,CAAC,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;YACnE,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,6CAAqB,CAAC,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,CAAA;YACjF,CAAC;QACH,CAAC;QAED,KAAK,WAAW;YACd,OAAO,IAAI,qCAAiB,CAAC,IAAwB,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;QAEjF,KAAK,QAAQ;YACX,OAAO,IAAI,+BAAc,CAAC,IAAqB,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;QAE3E,KAAK,QAAQ;YACX,OAAO,IAAI,+BAAc,CAAC,IAAqB,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;QAE3E,KAAK,IAAI,CAAC;QACV,KAAK,QAAQ;YACX,OAAO,IAAI,iCAAe,CACxB;gBACE,QAAQ,EAAE,SAAS;gBACnB,GAAG,EAAE,IAAA,+CAAwB,EAAC,IAAI,CAAC;gBACnC,OAAO,EAAG,IAAsB,CAAC,OAAO,IAAI,IAAI;aACjD,EACD,OAAO,EACP;gBACE,GAAG,cAAc;gBACjB,oEAAoE;gBACpE,yBAAyB,EAAE,KAAK;aACjC,CACF,CAAA;QAEH,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,OAAO,GAAG,IAA4B,CAAA;YAC5C,OAAO,IAAI,iCAAe,CAAC,OAAO,EAAE,OAAO,EAAE;gBAC3C,GAAG,cAAc;gBACjB,yBAAyB,EAAE,OAAO,CAAC,uBAAuB,KAAK,KAAK,IAAI,sCAAsC,CAAC,OAAO,CAAC,GAAG,CAAC;aAC5H,CAAC,CAAA;QACJ,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,OAAO,GAAG,IAA4B,CAAA;YAC5C,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,CAAA;YAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,IAAA,+BAAQ,EAAC,+BAA+B,EAAE,4CAA4C,CAAC,CAAA;YAC/F,CAAC;YACD,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;QAC1D,CAAC;QAED;YACE,MAAM,IAAA,+BAAQ,EAAC,yBAAyB,QAAQ,EAAE,EAAE,kCAAkC,CAAC,CAAA;IAC3F,CAAC;AACH,CAAC","sourcesContent":["import {\n  AllPublishOptions,\n  BaseS3Options,\n  BitbucketOptions,\n  CustomPublishOptions,\n  GenericServerOptions,\n  getS3LikeProviderBaseUrl,\n  GithubOptions,\n  GitlabOptions,\n  KeygenOptions,\n  newError,\n  PublishConfiguration,\n} from \"builder-util-runtime\"\nimport { AppUpdater } from \"./AppUpdater\"\nimport { BitbucketProvider } from \"./providers/BitbucketProvider\"\nimport { GenericProvider } from \"./providers/GenericProvider\"\nimport { GitHubProvider } from \"./providers/GitHubProvider\"\nimport { GitLabProvider } from \"./providers/GitLabProvider\"\nimport { KeygenProvider } from \"./providers/KeygenProvider\"\nimport { PrivateGitHubProvider } from \"./providers/PrivateGitHubProvider\"\nimport { Provider, ProviderRuntimeOptions } from \"./providers/Provider\"\n\nexport function isUrlProbablySupportMultiRangeRequests(url: string): boolean {\n  return !url.includes(\"s3.amazonaws.com\")\n}\n\nexport function createClient(data: PublishConfiguration | AllPublishOptions, updater: AppUpdater, runtimeOptions: ProviderRuntimeOptions): Provider<any> {\n  // noinspection SuspiciousTypeOfGuard\n  if (typeof data === \"string\") {\n    throw newError(\"Please pass PublishConfiguration object\", \"ERR_UPDATER_INVALID_PROVIDER_CONFIGURATION\")\n  }\n\n  const provider = data.provider\n  switch (provider) {\n    case \"github\": {\n      const githubOptions = data as GithubOptions\n      const token = (githubOptions.private ? process.env[\"GH_TOKEN\"] || process.env[\"GITHUB_TOKEN\"] : null) || githubOptions.token\n      if (token == null) {\n        return new GitHubProvider(githubOptions, updater, runtimeOptions)\n      } else {\n        return new PrivateGitHubProvider(githubOptions, updater, token, runtimeOptions)\n      }\n    }\n\n    case \"bitbucket\":\n      return new BitbucketProvider(data as BitbucketOptions, updater, runtimeOptions)\n\n    case \"gitlab\":\n      return new GitLabProvider(data as GitlabOptions, updater, runtimeOptions)\n\n    case \"keygen\":\n      return new KeygenProvider(data as KeygenOptions, updater, runtimeOptions)\n\n    case \"s3\":\n    case \"spaces\":\n      return new GenericProvider(\n        {\n          provider: \"generic\",\n          url: getS3LikeProviderBaseUrl(data),\n          channel: (data as BaseS3Options).channel || null,\n        },\n        updater,\n        {\n          ...runtimeOptions,\n          // https://github.com/minio/minio/issues/5285#issuecomment-350428955\n          isUseMultipleRangeRequest: false,\n        }\n      )\n\n    case \"generic\": {\n      const options = data as GenericServerOptions\n      return new GenericProvider(options, updater, {\n        ...runtimeOptions,\n        isUseMultipleRangeRequest: options.useMultipleRangeRequest !== false && isUrlProbablySupportMultiRangeRequests(options.url),\n      })\n    }\n\n    case \"custom\": {\n      const options = data as CustomPublishOptions\n      const constructor = options.updateProvider\n      if (!constructor) {\n        throw newError(\"Custom provider not specified\", \"ERR_UPDATER_INVALID_PROVIDER_CONFIGURATION\")\n      }\n      return new constructor(options, updater, runtimeOptions)\n    }\n\n    default:\n      throw newError(`Unsupported provider: ${provider}`, \"ERR_UPDATER_UNSUPPORTED_PROVIDER\")\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpdaterSignal = exports.UPDATE_DOWNLOADED = exports.DOWNLOAD_PROGRESS = exports.CancellationToken = void 0;
exports.addHandler = addHandler;
const builder_util_runtime_1 = require("builder-util-runtime");
Object.defineProperty(exports, "CancellationToken", { enumerable: true, get: function () { return builder_util_runtime_1.CancellationToken; } });
exports.DOWNLOAD_PROGRESS = "download-progress";
exports.UPDATE_DOWNLOADED = "update-downloaded";
class UpdaterSignal {
    constructor(emitter) {
        this.emitter = emitter;
    }
    /**
     * Emitted when an authenticating proxy is [asking for user credentials](https://github.com/electron/electron/blob/master/docs/api/client-request.md#event-login).
     */
    login(handler) {
        addHandler(this.emitter, "login", handler);
    }
    progress(handler) {
        addHandler(this.emitter, exports.DOWNLOAD_PROGRESS, handler);
    }
    updateDownloaded(handler) {
        addHandler(this.emitter, exports.UPDATE_DOWNLOADED, handler);
    }
    updateCancelled(handler) {
        addHandler(this.emitter, "update-cancelled", handler);
    }
}
exports.UpdaterSignal = UpdaterSignal;
const isLogEvent = false;
function addHandler(emitter, event, handler) {
    if (isLogEvent) {
        emitter.on(event, (...args) => {
            console.log("%s %s", event, args);
            handler(...args);
        });
    }
    else {
        emitter.on(event, handler);
    }
}
//# sourceMappingURL=types.js.map{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AA6CA,gCASC;AAtDD,+DAAmH;AAK1G,kGALA,wCAAiB,OAKA;AAEb,QAAA,iBAAiB,GAAG,mBAAmB,CAAA;AACvC,QAAA,iBAAiB,GAAG,mBAAmB,CAAA;AAYpD,MAAa,aAAa;IACxB,YAAoB,OAAqB;QAArB,YAAO,GAAP,OAAO,CAAc;IAAG,CAAC;IAE7C;;OAEG;IACH,KAAK,CAAC,OAAqB;QACzB,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAC5C,CAAC;IAED,QAAQ,CAAC,OAAqC;QAC5C,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,yBAAiB,EAAE,OAAO,CAAC,CAAA;IACtD,CAAC;IAED,gBAAgB,CAAC,OAA8C;QAC7D,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,yBAAiB,EAAE,OAAO,CAAC,CAAA;IACtD,CAAC;IAED,eAAe,CAAC,OAAmC;QACjD,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAA;IACvD,CAAC;CACF;AArBD,sCAqBC;AAED,MAAM,UAAU,GAAG,KAAK,CAAA;AAExB,SAAgB,UAAU,CAAC,OAAqB,EAAE,KAAoB,EAAE,OAAsC;IAC5G,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,IAAgB,EAAE,EAAE;YACxC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;YACjC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;QAClB,CAAC,CAAC,CAAA;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAC5B,CAAC;AACH,CAAC","sourcesContent":["import { CancellationToken, PackageFileInfo, ProgressInfo, UpdateFileInfo, UpdateInfo } from \"builder-util-runtime\"\nimport { EventEmitter } from \"events\"\nimport { URL } from \"url\"\nimport { LoginCallback } from \"./electronHttpExecutor\"\n\nexport { CancellationToken, PackageFileInfo, ProgressInfo, UpdateFileInfo, UpdateInfo }\n\nexport const DOWNLOAD_PROGRESS = \"download-progress\"\nexport const UPDATE_DOWNLOADED = \"update-downloaded\"\n\nexport interface Logger {\n  info(message?: any): void\n\n  warn(message?: any): void\n\n  error(message?: any): void\n\n  debug?(message: string): void\n}\n\nexport class UpdaterSignal {\n  constructor(private emitter: EventEmitter) {}\n\n  /**\n   * Emitted when an authenticating proxy is [asking for user credentials](https://github.com/electron/electron/blob/master/docs/api/client-request.md#event-login).\n   */\n  login(handler: LoginHandler): void {\n    addHandler(this.emitter, \"login\", handler)\n  }\n\n  progress(handler: (info: ProgressInfo) => void): void {\n    addHandler(this.emitter, DOWNLOAD_PROGRESS, handler)\n  }\n\n  updateDownloaded(handler: (info: UpdateDownloadedEvent) => void): void {\n    addHandler(this.emitter, UPDATE_DOWNLOADED, handler)\n  }\n\n  updateCancelled(handler: (info: UpdateInfo) => void): void {\n    addHandler(this.emitter, \"update-cancelled\", handler)\n  }\n}\n\nconst isLogEvent = false\n\nexport function addHandler(emitter: EventEmitter, event: UpdaterEvents, handler: (...args: Array<any>) => void): void {\n  if (isLogEvent) {\n    emitter.on(event, (...args: Array<any>) => {\n      console.log(\"%s %s\", event, args)\n      handler(...args)\n    })\n  } else {\n    emitter.on(event, handler)\n  }\n}\n\nexport interface UpdateCheckResult {\n  readonly isUpdateAvailable: boolean\n\n  readonly updateInfo: UpdateInfo\n\n  readonly downloadPromise?: Promise<Array<string>> | null\n\n  readonly cancellationToken?: CancellationToken\n\n  /** @deprecated */\n  readonly versionInfo: UpdateInfo\n}\n\nexport interface UpdateDownloadedEvent extends UpdateInfo {\n  downloadedFile: string\n}\n\nexport interface ResolvedUpdateFileInfo {\n  readonly url: URL\n  readonly info: UpdateFileInfo\n\n  packageInfo?: PackageFileInfo\n}\n\nexport type UpdaterEvents = \"login\" | \"checking-for-update\" | \"update-available\" | \"update-not-available\" | \"update-cancelled\" | \"download-progress\" | \"update-downloaded\" | \"error\"\n\nexport type LoginHandler = (authInfo: any, callback: LoginCallback) => void\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.newBaseUrl = newBaseUrl;
exports.newUrlFromBase = newUrlFromBase;
exports.getChannelFilename = getChannelFilename;
// if baseUrl path doesn't ends with /, this path will be not prepended to passed pathname for new URL(input, base)
const url_1 = require("url");
/** @internal */
function newBaseUrl(url) {
    const result = new url_1.URL(url);
    if (!result.pathname.endsWith("/")) {
        result.pathname += "/";
    }
    return result;
}
// addRandomQueryToAvoidCaching is false by default because in most cases URL already contains version number,
// so, it makes sense only for Generic Provider for channel files
function newUrlFromBase(pathname, baseUrl, addRandomQueryToAvoidCaching = false) {
    const result = new url_1.URL(pathname, baseUrl);
    // search is not propagated (search is an empty string if not specified)
    const search = baseUrl.search;
    if (search != null && search.length !== 0) {
        result.search = search;
    }
    else if (addRandomQueryToAvoidCaching) {
        result.search = `noCache=${Date.now().toString(32)}`;
    }
    return result;
}
function getChannelFilename(channel) {
    return `${channel}.yml`;
}
//# sourceMappingURL=util.js.map{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAIA,gCAMC;AAID,wCAUC;AAED,gDAEC;AA5BD,mHAAmH;AACnH,6BAAyB;AAEzB,gBAAgB;AAChB,SAAgB,UAAU,CAAC,GAAW;IACpC,MAAM,MAAM,GAAG,IAAI,SAAG,CAAC,GAAG,CAAC,CAAA;IAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,QAAQ,IAAI,GAAG,CAAA;IACxB,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,8GAA8G;AAC9G,iEAAiE;AACjE,SAAgB,cAAc,CAAC,QAAgB,EAAE,OAAY,EAAE,4BAA4B,GAAG,KAAK;IACjG,MAAM,MAAM,GAAG,IAAI,SAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACzC,wEAAwE;IACxE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAC7B,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1C,MAAM,CAAC,MAAM,GAAG,MAAM,CAAA;IACxB,CAAC;SAAM,IAAI,4BAA4B,EAAE,CAAC;QACxC,MAAM,CAAC,MAAM,GAAG,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAA;IACtD,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAgB,kBAAkB,CAAC,OAAe;IAChD,OAAO,GAAG,OAAO,MAAM,CAAA;AACzB,CAAC","sourcesContent":["// if baseUrl path doesn't ends with /, this path will be not prepended to passed pathname for new URL(input, base)\nimport { URL } from \"url\"\n\n/** @internal */\nexport function newBaseUrl(url: string): URL {\n  const result = new URL(url)\n  if (!result.pathname.endsWith(\"/\")) {\n    result.pathname += \"/\"\n  }\n  return result\n}\n\n// addRandomQueryToAvoidCaching is false by default because in most cases URL already contains version number,\n// so, it makes sense only for Generic Provider for channel files\nexport function newUrlFromBase(pathname: string, baseUrl: URL, addRandomQueryToAvoidCaching = false): URL {\n  const result = new URL(pathname, baseUrl)\n  // search is not propagated (search is an empty string if not specified)\n  const search = baseUrl.search\n  if (search != null && search.length !== 0) {\n    result.search = search\n  } else if (addRandomQueryToAvoidCaching) {\n    result.search = `noCache=${Date.now().toString(32)}`\n  }\n  return result\n}\n\nexport function getChannelFilename(channel: string): string {\n  return `${channel}.yml`\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifySignature = verifySignature;
const builder_util_runtime_1 = require("builder-util-runtime");
const child_process_1 = require("child_process");
const os = require("os");
const path = require("path");
function preparePowerShellExec(command, timeout) {
    // https://github.com/electron-userland/electron-builder/issues/2421
    // https://github.com/electron-userland/electron-builder/issues/2535
    // Resetting PSModulePath is necessary https://github.com/electron-userland/electron-builder/issues/7127
    // semicolon wont terminate the set command and run chcp thus leading to verification errors on certificats with special chars like german umlauts, so rather
    //   join commands using & https://github.com/electron-userland/electron-builder/issues/8162
    const executable = `set "PSModulePath=" & chcp 65001 >NUL & powershell.exe`;
    const args = ["-NoProfile", "-NonInteractive", "-InputFormat", "None", "-Command", command];
    const options = {
        shell: true,
        timeout,
    };
    return [executable, args, options];
}
// $certificateInfo = (Get-AuthenticodeSignature 'xxx\yyy.exe'
// | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains("CN=siemens.com")})
// | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }
function verifySignature(publisherNames, unescapedTempUpdateFile, logger) {
    return new Promise((resolve, reject) => {
        // Escape quotes and backticks in filenames to prevent user from breaking the
        // arguments and perform a remote command injection.
        //
        // Consider example powershell command:
        // ```powershell
        // Get-AuthenticodeSignature 'C:\\path\\my-bad-';calc;'filename.exe'
        // ```
        // The above would work expected and find the file name, however, it will also execute `;calc;`
        // command and start the calculator app.
        //
        // From Powershell quoting rules:
        // https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7
        // * Double quotes `"` are treated literally within single-quoted strings;
        // * Single quotes can be escaped by doubling them: 'don''t' -> don't;
        //
        // Also note that at this point the file has already been written to the disk, thus we are
        // guaranteed that the path will not contain any illegal characters like <>:"/\|?*
        // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
        const tempUpdateFile = unescapedTempUpdateFile.replace(/'/g, "''");
        logger.info(`Verifying signature ${tempUpdateFile}`);
        (0, child_process_1.execFile)(...preparePowerShellExec(`"Get-AuthenticodeSignature -LiteralPath '${tempUpdateFile}' | ConvertTo-Json -Compress"`, 20 * 1000), (error, stdout, stderr) => {
            var _a;
            try {
                if (error != null || stderr) {
                    handleError(logger, error, stderr, reject);
                    resolve(null);
                    return;
                }
                const data = parseOut(stdout);
                if (data.Status === 0) {
                    try {
                        const normlaizedUpdateFilePath = path.normalize(data.Path);
                        const normalizedTempUpdateFile = path.normalize(unescapedTempUpdateFile);
                        logger.info(`LiteralPath: ${normlaizedUpdateFilePath}. Update Path: ${normalizedTempUpdateFile}`);
                        if (normlaizedUpdateFilePath !== normalizedTempUpdateFile) {
                            handleError(logger, new Error(`LiteralPath of ${normlaizedUpdateFilePath} is different than ${normalizedTempUpdateFile}`), stderr, reject);
                            resolve(null);
                            return;
                        }
                    }
                    catch (error) {
                        logger.warn(`Unable to verify LiteralPath of update asset due to missing data.Path. Skipping this step of validation. Message: ${(_a = error.message) !== null && _a !== void 0 ? _a : error.stack}`);
                    }
                    const subject = (0, builder_util_runtime_1.parseDn)(data.SignerCertificate.Subject);
                    let match = false;
                    for (const name of publisherNames) {
                        const dn = (0, builder_util_runtime_1.parseDn)(name);
                        if (dn.size) {
                            // if we have a full DN, compare all values
                            const allKeys = Array.from(dn.keys());
                            match = allKeys.every(key => {
                                return dn.get(key) === subject.get(key);
                            });
                        }
                        else if (name === subject.get("CN")) {
                            logger.warn(`Signature validated using only CN ${name}. Please add your full Distinguished Name (DN) to publisherNames configuration`);
                            match = true;
                        }
                        if (match) {
                            resolve(null);
                            return;
                        }
                    }
                }
                const result = `publisherNames: ${publisherNames.join(" | ")}, raw info: ` + JSON.stringify(data, (name, value) => (name === "RawData" ? undefined : value), 2);
                logger.warn(`Sign verification failed, installer signed with incorrect certificate: ${result}`);
                resolve(result);
            }
            catch (e) {
                handleError(logger, e, null, reject);
                resolve(null);
                return;
            }
        });
    });
}
function parseOut(out) {
    const data = JSON.parse(out);
    delete data.PrivateKey;
    delete data.IsOSBinary;
    delete data.SignatureType;
    const signerCertificate = data.SignerCertificate;
    if (signerCertificate != null) {
        delete signerCertificate.Archived;
        delete signerCertificate.Extensions;
        delete signerCertificate.Handle;
        delete signerCertificate.HasPrivateKey;
        // duplicates data.SignerCertificate (contains RawData)
        delete signerCertificate.SubjectName;
    }
    return data;
}
function handleError(logger, error, stderr, reject) {
    if (isOldWin6()) {
        logger.warn(`Cannot execute Get-AuthenticodeSignature: ${error || stderr}. Ignoring signature validation due to unsupported powershell version. Please upgrade to powershell 3 or higher.`);
        return;
    }
    try {
        (0, child_process_1.execFileSync)(...preparePowerShellExec("ConvertTo-Json test", 10 * 1000));
    }
    catch (testError) {
        logger.warn(`Cannot execute ConvertTo-Json: ${testError.message}. Ignoring signature validation due to unsupported powershell version. Please upgrade to powershell 3 or higher.`);
        return;
    }
    if (error != null) {
        reject(error);
    }
    if (stderr) {
        reject(new Error(`Cannot execute Get-AuthenticodeSignature, stderr: ${stderr}. Failing signature validation due to unknown stderr.`));
    }
}
function isOldWin6() {
    const winVersion = os.release();
    return winVersion.startsWith("6.") && !winVersion.startsWith("6.3");
}
//# sourceMappingURL=windowsExecutableCodeSignatureVerifier.js.map{"version":3,"file":"windowsExecutableCodeSignatureVerifier.js","sourceRoot":"","sources":["../src/windowsExecutableCodeSignatureVerifier.ts"],"names":[],"mappings":"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","sourcesContent":["import { parseDn } from \"builder-util-runtime\"\nimport { execFile, execFileSync, ExecFileOptions } from \"child_process\"\nimport * as os from \"os\"\nimport { Logger } from \"./types\"\nimport * as path from \"path\"\n\nfunction preparePowerShellExec(command: string, timeout?: number) {\n  // https://github.com/electron-userland/electron-builder/issues/2421\n  // https://github.com/electron-userland/electron-builder/issues/2535\n  // Resetting PSModulePath is necessary https://github.com/electron-userland/electron-builder/issues/7127\n  // semicolon wont terminate the set command and run chcp thus leading to verification errors on certificats with special chars like german umlauts, so rather\n  //   join commands using & https://github.com/electron-userland/electron-builder/issues/8162\n  const executable = `set \"PSModulePath=\" & chcp 65001 >NUL & powershell.exe`\n  const args = [\"-NoProfile\", \"-NonInteractive\", \"-InputFormat\", \"None\", \"-Command\", command]\n  const options: ExecFileOptions = {\n    shell: true,\n    timeout,\n  }\n  return [executable, args, options] as const\n}\n\n// $certificateInfo = (Get-AuthenticodeSignature 'xxx\\yyy.exe'\n// | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains(\"CN=siemens.com\")})\n// | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }\nexport function verifySignature(publisherNames: Array<string>, unescapedTempUpdateFile: string, logger: Logger): Promise<string | null> {\n  return new Promise<string | null>((resolve, reject) => {\n    // Escape quotes and backticks in filenames to prevent user from breaking the\n    // arguments and perform a remote command injection.\n    //\n    // Consider example powershell command:\n    // ```powershell\n    // Get-AuthenticodeSignature 'C:\\\\path\\\\my-bad-';calc;'filename.exe'\n    // ```\n    // The above would work expected and find the file name, however, it will also execute `;calc;`\n    // command and start the calculator app.\n    //\n    // From Powershell quoting rules:\n    // https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7\n    // * Double quotes `\"` are treated literally within single-quoted strings;\n    // * Single quotes can be escaped by doubling them: 'don''t' -> don't;\n    //\n    // Also note that at this point the file has already been written to the disk, thus we are\n    // guaranteed that the path will not contain any illegal characters like <>:\"/\\|?*\n    // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file\n    const tempUpdateFile = unescapedTempUpdateFile.replace(/'/g, \"''\")\n    logger.info(`Verifying signature ${tempUpdateFile}`)\n\n    execFile(...preparePowerShellExec(`\"Get-AuthenticodeSignature -LiteralPath '${tempUpdateFile}' | ConvertTo-Json -Compress\"`, 20 * 1000), (error, stdout, stderr) => {\n      try {\n        if (error != null || stderr) {\n          handleError(logger, error, stderr, reject)\n          resolve(null)\n          return\n        }\n        const data = parseOut(stdout)\n        if (data.Status === 0) {\n          try {\n            const normlaizedUpdateFilePath = path.normalize(data.Path)\n            const normalizedTempUpdateFile = path.normalize(unescapedTempUpdateFile)\n            logger.info(`LiteralPath: ${normlaizedUpdateFilePath}. Update Path: ${normalizedTempUpdateFile}`)\n            if (normlaizedUpdateFilePath !== normalizedTempUpdateFile) {\n              handleError(logger, new Error(`LiteralPath of ${normlaizedUpdateFilePath} is different than ${normalizedTempUpdateFile}`), stderr, reject)\n              resolve(null)\n              return\n            }\n          } catch (error: any) {\n            logger.warn(`Unable to verify LiteralPath of update asset due to missing data.Path. Skipping this step of validation. Message: ${error.message ?? error.stack}`)\n          }\n          const subject = parseDn(data.SignerCertificate.Subject)\n          let match = false\n          for (const name of publisherNames) {\n            const dn = parseDn(name)\n            if (dn.size) {\n              // if we have a full DN, compare all values\n              const allKeys = Array.from(dn.keys())\n              match = allKeys.every(key => {\n                return dn.get(key) === subject.get(key)\n              })\n            } else if (name === subject.get(\"CN\")!) {\n              logger.warn(`Signature validated using only CN ${name}. Please add your full Distinguished Name (DN) to publisherNames configuration`)\n              match = true\n            }\n            if (match) {\n              resolve(null)\n              return\n            }\n          }\n        }\n\n        const result = `publisherNames: ${publisherNames.join(\" | \")}, raw info: ` + JSON.stringify(data, (name, value) => (name === \"RawData\" ? undefined : value), 2)\n        logger.warn(`Sign verification failed, installer signed with incorrect certificate: ${result}`)\n        resolve(result)\n      } catch (e: any) {\n        handleError(logger, e, null, reject)\n        resolve(null)\n        return\n      }\n    })\n  })\n}\n\nfunction parseOut(out: string): any {\n  const data = JSON.parse(out)\n  delete data.PrivateKey\n  delete data.IsOSBinary\n  delete data.SignatureType\n  const signerCertificate = data.SignerCertificate\n  if (signerCertificate != null) {\n    delete signerCertificate.Archived\n    delete signerCertificate.Extensions\n    delete signerCertificate.Handle\n    delete signerCertificate.HasPrivateKey\n    // duplicates data.SignerCertificate (contains RawData)\n    delete signerCertificate.SubjectName\n  }\n  return data\n}\n\nfunction handleError(logger: Logger, error: Error | null, stderr: string | null, reject: (reason: any) => void): void {\n  if (isOldWin6()) {\n    logger.warn(\n      `Cannot execute Get-AuthenticodeSignature: ${error || stderr}. Ignoring signature validation due to unsupported powershell version. Please upgrade to powershell 3 or higher.`\n    )\n    return\n  }\n\n  try {\n    execFileSync(...preparePowerShellExec(\"ConvertTo-Json test\", 10 * 1000))\n  } catch (testError: any) {\n    logger.warn(\n      `Cannot execute ConvertTo-Json: ${testError.message}. Ignoring signature validation due to unsupported powershell version. Please upgrade to powershell 3 or higher.`\n    )\n    return\n  }\n\n  if (error != null) {\n    reject(error)\n  }\n\n  if (stderr) {\n    reject(new Error(`Cannot execute Get-AuthenticodeSignature, stderr: ${stderr}. Failing signature validation due to unknown stderr.`))\n  }\n}\n\nfunction isOldWin6(): boolean {\n  const winVersion = os.release()\n  return winVersion.startsWith(\"6.\") && !winVersion.startsWith(\"6.3\")\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BitbucketProvider = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const util_1 = require("../util");
const Provider_1 = require("./Provider");
class BitbucketProvider extends Provider_1.Provider {
    constructor(configuration, updater, runtimeOptions) {
        super({
            ...runtimeOptions,
            isUseMultipleRangeRequest: false,
        });
        this.configuration = configuration;
        this.updater = updater;
        const { owner, slug } = configuration;
        this.baseUrl = (0, util_1.newBaseUrl)(`https://api.bitbucket.org/2.0/repositories/${owner}/${slug}/downloads`);
    }
    get channel() {
        return this.updater.channel || this.configuration.channel || "latest";
    }
    async getLatestVersion() {
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        const channelFile = (0, util_1.getChannelFilename)(this.getCustomChannelName(this.channel));
        const channelUrl = (0, util_1.newUrlFromBase)(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery);
        try {
            const updateInfo = await this.httpRequest(channelUrl, undefined, cancellationToken);
            return (0, Provider_1.parseUpdateInfo)(updateInfo, channelFile, channelUrl);
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Unable to find latest version on ${this.toString()}, please ensure release exists: ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
    }
    resolveFiles(updateInfo) {
        return (0, Provider_1.resolveFiles)(updateInfo, this.baseUrl);
    }
    toString() {
        const { owner, slug } = this.configuration;
        return `Bitbucket (owner: ${owner}, slug: ${slug}, channel: ${this.channel})`;
    }
}
exports.BitbucketProvider = BitbucketProvider;
//# sourceMappingURL=BitbucketProvider.js.map{"version":3,"file":"BitbucketProvider.js","sourceRoot":"","sources":["../../src/providers/BitbucketProvider.ts"],"names":[],"mappings":";;;AAAA,+DAAgG;AAGhG,kCAAwE;AACxE,yCAA4F;AAE5F,MAAa,iBAAkB,SAAQ,mBAAoB;IAGzD,YACmB,aAA+B,EAC/B,OAAmB,EACpC,cAAsC;QAEtC,KAAK,CAAC;YACJ,GAAG,cAAc;YACjB,yBAAyB,EAAE,KAAK;SACjC,CAAC,CAAA;QAPe,kBAAa,GAAb,aAAa,CAAkB;QAC/B,YAAO,GAAP,OAAO,CAAY;QAOpC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,aAAa,CAAA;QACrC,IAAI,CAAC,OAAO,GAAG,IAAA,iBAAU,EAAC,8CAA8C,KAAK,IAAI,IAAI,YAAY,CAAC,CAAA;IACpG,CAAC;IAED,IAAY,OAAO;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,IAAI,QAAQ,CAAA;IACvE,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,iBAAiB,GAAG,IAAI,wCAAiB,EAAE,CAAA;QACjD,MAAM,WAAW,GAAG,IAAA,yBAAkB,EAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;QAC/E,MAAM,UAAU,GAAG,IAAA,qBAAc,EAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;QAC5F,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAA;YACnF,OAAO,IAAA,0BAAe,EAAC,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,CAAA;QAC7D,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,MAAM,IAAA,+BAAQ,EAAC,oCAAoC,IAAI,CAAC,QAAQ,EAAE,mCAAmC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,sCAAsC,CAAC,CAAA;QACtK,CAAC;IACH,CAAC;IAED,YAAY,CAAC,UAAsB;QACjC,OAAO,IAAA,uBAAY,EAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC/C,CAAC;IAED,QAAQ;QACN,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,aAAa,CAAA;QAC1C,OAAO,qBAAqB,KAAK,WAAW,IAAI,cAAc,IAAI,CAAC,OAAO,GAAG,CAAA;IAC/E,CAAC;CACF;AAxCD,8CAwCC","sourcesContent":["import { CancellationToken, BitbucketOptions, newError, UpdateInfo } from \"builder-util-runtime\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from \"./Provider\"\n\nexport class BitbucketProvider extends Provider<UpdateInfo> {\n  private readonly baseUrl: URL\n\n  constructor(\n    private readonly configuration: BitbucketOptions,\n    private readonly updater: AppUpdater,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super({\n      ...runtimeOptions,\n      isUseMultipleRangeRequest: false,\n    })\n    const { owner, slug } = configuration\n    this.baseUrl = newBaseUrl(`https://api.bitbucket.org/2.0/repositories/${owner}/${slug}/downloads`)\n  }\n\n  private get channel(): string {\n    return this.updater.channel || this.configuration.channel || \"latest\"\n  }\n\n  async getLatestVersion(): Promise<UpdateInfo> {\n    const cancellationToken = new CancellationToken()\n    const channelFile = getChannelFilename(this.getCustomChannelName(this.channel))\n    const channelUrl = newUrlFromBase(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery)\n    try {\n      const updateInfo = await this.httpRequest(channelUrl, undefined, cancellationToken)\n      return parseUpdateInfo(updateInfo, channelFile, channelUrl)\n    } catch (e: any) {\n      throw newError(`Unable to find latest version on ${this.toString()}, please ensure release exists: ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n    }\n  }\n\n  resolveFiles(updateInfo: UpdateInfo): Array<ResolvedUpdateFileInfo> {\n    return resolveFiles(updateInfo, this.baseUrl)\n  }\n\n  toString() {\n    const { owner, slug } = this.configuration\n    return `Bitbucket (owner: ${owner}, slug: ${slug}, channel: ${this.channel})`\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenericProvider = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const util_1 = require("../util");
const Provider_1 = require("./Provider");
class GenericProvider extends Provider_1.Provider {
    constructor(configuration, updater, runtimeOptions) {
        super(runtimeOptions);
        this.configuration = configuration;
        this.updater = updater;
        this.baseUrl = (0, util_1.newBaseUrl)(this.configuration.url);
    }
    get channel() {
        const result = this.updater.channel || this.configuration.channel;
        return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result);
    }
    async getLatestVersion() {
        const channelFile = (0, util_1.getChannelFilename)(this.channel);
        const channelUrl = (0, util_1.newUrlFromBase)(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery);
        for (let attemptNumber = 0;; attemptNumber++) {
            try {
                return (0, Provider_1.parseUpdateInfo)(await this.httpRequest(channelUrl), channelFile, channelUrl);
            }
            catch (e) {
                if (e instanceof builder_util_runtime_1.HttpError && e.statusCode === 404) {
                    throw (0, builder_util_runtime_1.newError)(`Cannot find channel "${channelFile}" update info: ${e.stack || e.message}`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
                }
                else if (e.code === "ECONNREFUSED") {
                    if (attemptNumber < 3) {
                        await new Promise((resolve, reject) => {
                            try {
                                setTimeout(resolve, 1000 * attemptNumber);
                            }
                            catch (e) {
                                reject(e);
                            }
                        });
                        continue;
                    }
                }
                throw e;
            }
        }
    }
    resolveFiles(updateInfo) {
        return (0, Provider_1.resolveFiles)(updateInfo, this.baseUrl);
    }
}
exports.GenericProvider = GenericProvider;
//# sourceMappingURL=GenericProvider.js.map{"version":3,"file":"GenericProvider.js","sourceRoot":"","sources":["../../src/providers/GenericProvider.ts"],"names":[],"mappings":";;;AAAA,+DAA4F;AAG5F,kCAAwE;AACxE,yCAA4F;AAE5F,MAAa,eAAgB,SAAQ,mBAAoB;IAGvD,YACmB,aAAmC,EACnC,OAAmB,EACpC,cAAsC;QAEtC,KAAK,CAAC,cAAc,CAAC,CAAA;QAJJ,kBAAa,GAAb,aAAa,CAAsB;QACnC,YAAO,GAAP,OAAO,CAAY;QAJrB,YAAO,GAAG,IAAA,iBAAU,EAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IAQ7D,CAAC;IAED,IAAY,OAAO;QACjB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,CAAA;QACjE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAA;IAC1F,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,WAAW,GAAG,IAAA,yBAAkB,EAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACpD,MAAM,UAAU,GAAG,IAAA,qBAAc,EAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;QAC5F,KAAK,IAAI,aAAa,GAAG,CAAC,GAAI,aAAa,EAAE,EAAE,CAAC;YAC9C,IAAI,CAAC;gBACH,OAAO,IAAA,0BAAe,EAAC,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,CAAA;YACrF,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,IAAI,CAAC,YAAY,gCAAS,IAAI,CAAC,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;oBACnD,MAAM,IAAA,+BAAQ,EAAC,wBAAwB,WAAW,kBAAkB,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,oCAAoC,CAAC,CAAA;gBACnI,CAAC;qBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBACrC,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;wBACtB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;4BACpC,IAAI,CAAC;gCACH,UAAU,CAAC,OAAO,EAAE,IAAI,GAAG,aAAa,CAAC,CAAA;4BAC3C,CAAC;4BAAC,OAAO,CAAM,EAAE,CAAC;gCAChB,MAAM,CAAC,CAAC,CAAC,CAAA;4BACX,CAAC;wBACH,CAAC,CAAC,CAAA;wBACF,SAAQ;oBACV,CAAC;gBACH,CAAC;gBACD,MAAM,CAAC,CAAA;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAED,YAAY,CAAC,UAAsB;QACjC,OAAO,IAAA,uBAAY,EAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC/C,CAAC;CACF;AA7CD,0CA6CC","sourcesContent":["import { GenericServerOptions, HttpError, newError, UpdateInfo } from \"builder-util-runtime\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from \"./Provider\"\n\nexport class GenericProvider extends Provider<UpdateInfo> {\n  private readonly baseUrl = newBaseUrl(this.configuration.url)\n\n  constructor(\n    private readonly configuration: GenericServerOptions,\n    private readonly updater: AppUpdater,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super(runtimeOptions)\n  }\n\n  private get channel(): string {\n    const result = this.updater.channel || this.configuration.channel\n    return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result)\n  }\n\n  async getLatestVersion(): Promise<UpdateInfo> {\n    const channelFile = getChannelFilename(this.channel)\n    const channelUrl = newUrlFromBase(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery)\n    for (let attemptNumber = 0; ; attemptNumber++) {\n      try {\n        return parseUpdateInfo(await this.httpRequest(channelUrl), channelFile, channelUrl)\n      } catch (e: any) {\n        if (e instanceof HttpError && e.statusCode === 404) {\n          throw newError(`Cannot find channel \"${channelFile}\" update info: ${e.stack || e.message}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n        } else if (e.code === \"ECONNREFUSED\") {\n          if (attemptNumber < 3) {\n            await new Promise((resolve, reject) => {\n              try {\n                setTimeout(resolve, 1000 * attemptNumber)\n              } catch (e: any) {\n                reject(e)\n              }\n            })\n            continue\n          }\n        }\n        throw e\n      }\n    }\n  }\n\n  resolveFiles(updateInfo: UpdateInfo): Array<ResolvedUpdateFileInfo> {\n    return resolveFiles(updateInfo, this.baseUrl)\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GitHubProvider = exports.BaseGitHubProvider = void 0;
exports.computeReleaseNotes = computeReleaseNotes;
const builder_util_runtime_1 = require("builder-util-runtime");
const semver = require("semver");
const url_1 = require("url");
const util_1 = require("../util");
const Provider_1 = require("./Provider");
const hrefRegExp = /\/tag\/(v?[^/]+)$/;
class BaseGitHubProvider extends Provider_1.Provider {
    constructor(options, defaultHost, runtimeOptions) {
        super({
            ...runtimeOptions,
            /* because GitHib uses S3 */
            isUseMultipleRangeRequest: false,
        });
        this.options = options;
        this.baseUrl = (0, util_1.newBaseUrl)((0, builder_util_runtime_1.githubUrl)(options, defaultHost));
        const apiHost = defaultHost === "github.com" ? "api.github.com" : defaultHost;
        this.baseApiUrl = (0, util_1.newBaseUrl)((0, builder_util_runtime_1.githubUrl)(options, apiHost));
    }
    computeGithubBasePath(result) {
        // https://github.com/electron-userland/electron-builder/issues/1903#issuecomment-320881211
        const host = this.options.host;
        return host && !["github.com", "api.github.com"].includes(host) ? `/api/v3${result}` : result;
    }
}
exports.BaseGitHubProvider = BaseGitHubProvider;
class GitHubProvider extends BaseGitHubProvider {
    constructor(options, updater, runtimeOptions) {
        super(options, "github.com", runtimeOptions);
        this.options = options;
        this.updater = updater;
    }
    get channel() {
        const result = this.updater.channel || this.options.channel;
        return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result);
    }
    async getLatestVersion() {
        var _a, _b, _c, _d, _e;
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        const feedXml = (await this.httpRequest((0, util_1.newUrlFromBase)(`${this.basePath}.atom`, this.baseUrl), {
            accept: "application/xml, application/atom+xml, text/xml, */*",
        }, cancellationToken));
        const feed = (0, builder_util_runtime_1.parseXml)(feedXml);
        // noinspection TypeScriptValidateJSTypes
        let latestRelease = feed.element("entry", false, `No published versions on GitHub`);
        let tag = null;
        try {
            if (this.updater.allowPrerelease) {
                const currentChannel = ((_a = this.updater) === null || _a === void 0 ? void 0 : _a.channel) || ((_b = semver.prerelease(this.updater.currentVersion)) === null || _b === void 0 ? void 0 : _b[0]) || null;
                if (currentChannel === null) {
                    // allowPrerelease=true with no explicit channel and stable current version:
                    // pick the first entry from the Atom feed, which may be a prerelease
                    // noinspection TypeScriptValidateJSTypes
                    tag = hrefRegExp.exec(latestRelease.element("link").attribute("href"))[1];
                }
                else {
                    for (const element of feed.getElements("entry")) {
                        // noinspection TypeScriptValidateJSTypes
                        const hrefElement = hrefRegExp.exec(element.element("link").attribute("href"));
                        // If this is null then something is wrong and skip this release
                        if (hrefElement === null) {
                            continue;
                        }
                        // This Release's Tag
                        const hrefTag = hrefElement[1];
                        if (!semver.valid(hrefTag)) {
                            continue;
                        }
                        //Get Channel from this release's tag
                        const hrefChannel = ((_c = semver.prerelease(hrefTag)) === null || _c === void 0 ? void 0 : _c[0]) || null;
                        const shouldFetchVersion = !currentChannel || ["alpha", "beta"].includes(currentChannel);
                        const isCustomChannel = hrefChannel !== null && !["alpha", "beta"].includes(String(hrefChannel));
                        // Allow moving from alpha to beta but not down
                        const channelMismatch = currentChannel === "beta" && hrefChannel === "alpha";
                        if (shouldFetchVersion && !isCustomChannel && !channelMismatch) {
                            tag = hrefTag;
                            latestRelease = element;
                            break;
                        }
                        const isNextPreRelease = hrefChannel && hrefChannel === currentChannel;
                        if (isNextPreRelease) {
                            tag = hrefTag;
                            latestRelease = element;
                            break;
                        }
                    }
                }
            }
            else {
                tag = await this.getLatestTagName(cancellationToken);
                for (const element of feed.getElements("entry")) {
                    // noinspection TypeScriptValidateJSTypes
                    const hrefMatch = hrefRegExp.exec(element.element("link").attribute("href"));
                    if (hrefMatch == null) {
                        continue;
                    }
                    if (hrefMatch[1] === tag) {
                        latestRelease = element;
                        break;
                    }
                }
            }
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Cannot parse releases feed: ${e.stack || e.message},\nXML:\n${feedXml}`, "ERR_UPDATER_INVALID_RELEASE_FEED");
        }
        if (tag == null) {
            throw (0, builder_util_runtime_1.newError)(`No published versions on GitHub`, "ERR_UPDATER_NO_PUBLISHED_VERSIONS");
        }
        let rawData;
        let channelFile = "";
        let channelFileUrl = "";
        const fetchData = async (channelName) => {
            channelFile = (0, util_1.getChannelFilename)(channelName);
            channelFileUrl = (0, util_1.newUrlFromBase)(this.getBaseDownloadPath(String(tag), channelFile), this.baseUrl);
            const requestOptions = this.createRequestOptions(channelFileUrl);
            try {
                return (await this.executor.request(requestOptions, cancellationToken));
            }
            catch (e) {
                if (e instanceof builder_util_runtime_1.HttpError && e.statusCode === 404) {
                    throw (0, builder_util_runtime_1.newError)(`Cannot find ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
                }
                throw e;
            }
        };
        try {
            let channel = this.channel;
            if (this.updater.allowPrerelease && ((_d = semver.prerelease(tag)) === null || _d === void 0 ? void 0 : _d[0])) {
                channel = this.getCustomChannelName(String((_e = semver.prerelease(tag)) === null || _e === void 0 ? void 0 : _e[0]));
            }
            rawData = await fetchData(channel);
        }
        catch (e) {
            if (this.updater.allowPrerelease) {
                // Allow fallback to `latest.yml`
                rawData = await fetchData(this.getDefaultChannelName());
            }
            else {
                throw e;
            }
        }
        const result = (0, Provider_1.parseUpdateInfo)(rawData, channelFile, channelFileUrl);
        if (result.releaseName == null) {
            result.releaseName = latestRelease.elementValueOrEmpty("title");
        }
        if (result.releaseNotes == null) {
            result.releaseNotes = computeReleaseNotes(this.updater.currentVersion, this.updater.fullChangelog, feed, latestRelease);
        }
        return {
            tag: tag,
            ...result,
        };
    }
    async getLatestTagName(cancellationToken) {
        const options = this.options;
        // do not use API for GitHub to avoid limit, only for custom host or GitHub Enterprise
        const url = options.host == null || options.host === "github.com"
            ? (0, util_1.newUrlFromBase)(`${this.basePath}/latest`, this.baseUrl)
            : new url_1.URL(`${this.computeGithubBasePath(`/repos/${options.owner}/${options.repo}/releases`)}/latest`, this.baseApiUrl);
        try {
            const rawData = await this.httpRequest(url, { Accept: "application/json" }, cancellationToken);
            if (rawData == null) {
                return null;
            }
            const releaseInfo = JSON.parse(rawData);
            return releaseInfo.tag_name;
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
    }
    get basePath() {
        return `/${this.options.owner}/${this.options.repo}/releases`;
    }
    resolveFiles(updateInfo) {
        // still replace space to - due to backward compatibility
        return (0, Provider_1.resolveFiles)(updateInfo, this.baseUrl, p => this.getBaseDownloadPath(updateInfo.tag, p.replace(/ /g, "-")));
    }
    getBaseDownloadPath(tag, fileName) {
        return `${this.basePath}/download/${tag}/${fileName}`;
    }
}
exports.GitHubProvider = GitHubProvider;
function getNoteValue(parent) {
    const result = parent.elementValueOrEmpty("content");
    // GitHub reports empty notes as <content>No content.</content>
    return result === "No content." ? "" : result;
}
function computeReleaseNotes(currentVersion, isFullChangelog, feed, latestRelease) {
    if (!isFullChangelog) {
        return getNoteValue(latestRelease);
    }
    const releaseVersionRegExp = /\/tag\/v?([^/]+)$/;
    let latestVersion = undefined;
    try {
        latestVersion = releaseVersionRegExp.exec(latestRelease.element("link").attribute("href"))[1];
        latestVersion = semver.valid(latestVersion) ? latestVersion : undefined;
    }
    catch {
        // If we cannot parse the latest release version, return null — notes cannot be determined
    }
    if (latestVersion == null) {
        return null;
    }
    const releaseNotes = [];
    for (const release of feed.getElements("entry")) {
        let versionRelease;
        try {
            const match = releaseVersionRegExp.exec(release.element("link").attribute("href"));
            if (!match) {
                continue;
            }
            versionRelease = match[1];
        }
        catch {
            continue;
        }
        // skip non-semver tags (e.g. doc/website releases in monorepos)
        if (!semver.valid(versionRelease)) {
            continue;
        }
        const isGreaterThanCurrent = semver.gt(versionRelease, currentVersion.raw);
        const isLessOrEqualThanLatest = semver.lte(versionRelease, latestVersion);
        if (isGreaterThanCurrent && isLessOrEqualThanLatest) {
            releaseNotes.push({
                version: versionRelease,
                note: getNoteValue(release),
            });
        }
    }
    return releaseNotes.sort((a, b) => semver.rcompare(a.version, b.version));
}
//# sourceMappingURL=GitHubProvider.js.map{"version":3,"file":"GitHubProvider.js","sourceRoot":"","sources":["../../src/providers/GitHubProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { CancellationToken, GithubOptions, githubUrl, HttpError, newError, parseXml, ReleaseNoteInfo, UpdateInfo, XElement } from \"builder-util-runtime\"\nimport * as semver from \"semver\"\nimport { URL } from \"url\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from \"./Provider\"\n\nconst hrefRegExp = /\\/tag\\/(v?[^/]+)$/\n\ninterface GithubUpdateInfo extends UpdateInfo {\n  tag: string\n}\nexport abstract class BaseGitHubProvider<T extends UpdateInfo> extends Provider<T> {\n  // so, we don't need to parse port (because node http doesn't support host as url does)\n  protected readonly baseUrl: URL\n  protected readonly baseApiUrl: URL\n\n  protected constructor(\n    protected readonly options: GithubOptions,\n    defaultHost: string,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super({\n      ...runtimeOptions,\n      /* because GitHib uses S3 */\n      isUseMultipleRangeRequest: false,\n    })\n\n    this.baseUrl = newBaseUrl(githubUrl(options, defaultHost))\n    const apiHost = defaultHost === \"github.com\" ? \"api.github.com\" : defaultHost\n    this.baseApiUrl = newBaseUrl(githubUrl(options, apiHost))\n  }\n\n  protected computeGithubBasePath(result: string): string {\n    // https://github.com/electron-userland/electron-builder/issues/1903#issuecomment-320881211\n    const host = this.options.host\n    return host && ![\"github.com\", \"api.github.com\"].includes(host) ? `/api/v3${result}` : result\n  }\n}\n\nexport class GitHubProvider extends BaseGitHubProvider<GithubUpdateInfo> {\n  constructor(\n    protected readonly options: GithubOptions,\n    private readonly updater: AppUpdater,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super(options, \"github.com\", runtimeOptions)\n  }\n\n  private get channel(): string {\n    const result = this.updater.channel || this.options.channel\n    return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result)\n  }\n\n  async getLatestVersion(): Promise<GithubUpdateInfo> {\n    const cancellationToken = new CancellationToken()\n\n    const feedXml: string = (await this.httpRequest(\n      newUrlFromBase(`${this.basePath}.atom`, this.baseUrl),\n      {\n        accept: \"application/xml, application/atom+xml, text/xml, */*\",\n      },\n      cancellationToken\n    ))!\n\n    const feed = parseXml(feedXml)\n    // noinspection TypeScriptValidateJSTypes\n    let latestRelease = feed.element(\"entry\", false, `No published versions on GitHub`)\n    let tag: string | null = null\n    try {\n      if (this.updater.allowPrerelease) {\n        const currentChannel = this.updater?.channel || (semver.prerelease(this.updater.currentVersion)?.[0] as string) || null\n\n        if (currentChannel === null) {\n          // allowPrerelease=true with no explicit channel and stable current version:\n          // pick the first entry from the Atom feed, which may be a prerelease\n          // noinspection TypeScriptValidateJSTypes\n          tag = hrefRegExp.exec(latestRelease.element(\"link\").attribute(\"href\"))![1]\n        } else {\n          for (const element of feed.getElements(\"entry\")) {\n            // noinspection TypeScriptValidateJSTypes\n            const hrefElement = hrefRegExp.exec(element.element(\"link\").attribute(\"href\"))!\n\n            // If this is null then something is wrong and skip this release\n            if (hrefElement === null) {\n              continue\n            }\n\n            // This Release's Tag\n            const hrefTag = hrefElement[1]\n            if (!semver.valid(hrefTag)) {\n              continue\n            }\n\n            //Get Channel from this release's tag\n            const hrefChannel = (semver.prerelease(hrefTag)?.[0] as string) || null\n\n            const shouldFetchVersion = !currentChannel || [\"alpha\", \"beta\"].includes(currentChannel)\n            const isCustomChannel = hrefChannel !== null && ![\"alpha\", \"beta\"].includes(String(hrefChannel))\n            // Allow moving from alpha to beta but not down\n            const channelMismatch = currentChannel === \"beta\" && hrefChannel === \"alpha\"\n\n            if (shouldFetchVersion && !isCustomChannel && !channelMismatch) {\n              tag = hrefTag\n              latestRelease = element\n              break\n            }\n\n            const isNextPreRelease = hrefChannel && hrefChannel === currentChannel\n            if (isNextPreRelease) {\n              tag = hrefTag\n              latestRelease = element\n              break\n            }\n          }\n        }\n      } else {\n        tag = await this.getLatestTagName(cancellationToken)\n        for (const element of feed.getElements(\"entry\")) {\n          // noinspection TypeScriptValidateJSTypes\n          const hrefMatch = hrefRegExp.exec(element.element(\"link\").attribute(\"href\"))\n          if (hrefMatch == null) {\n            continue\n          }\n          if (hrefMatch[1] === tag) {\n            latestRelease = element\n            break\n          }\n        }\n      }\n    } catch (e: any) {\n      throw newError(`Cannot parse releases feed: ${e.stack || e.message},\\nXML:\\n${feedXml}`, \"ERR_UPDATER_INVALID_RELEASE_FEED\")\n    }\n\n    if (tag == null) {\n      throw newError(`No published versions on GitHub`, \"ERR_UPDATER_NO_PUBLISHED_VERSIONS\")\n    }\n\n    let rawData: string\n    let channelFile = \"\"\n    let channelFileUrl: any = \"\"\n    const fetchData = async (channelName: string) => {\n      channelFile = getChannelFilename(channelName)\n      channelFileUrl = newUrlFromBase(this.getBaseDownloadPath(String(tag), channelFile), this.baseUrl)\n      const requestOptions = this.createRequestOptions(channelFileUrl)\n      try {\n        return (await this.executor.request(requestOptions, cancellationToken))!\n      } catch (e: any) {\n        if (e instanceof HttpError && e.statusCode === 404) {\n          throw newError(`Cannot find ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n        }\n        throw e\n      }\n    }\n\n    try {\n      let channel = this.channel\n      if (this.updater.allowPrerelease && semver.prerelease(tag)?.[0]) {\n        channel = this.getCustomChannelName(String(semver.prerelease(tag)?.[0]))\n      }\n      rawData = await fetchData(channel)\n    } catch (e: any) {\n      if (this.updater.allowPrerelease) {\n        // Allow fallback to `latest.yml`\n        rawData = await fetchData(this.getDefaultChannelName())\n      } else {\n        throw e\n      }\n    }\n\n    const result = parseUpdateInfo(rawData, channelFile, channelFileUrl)\n    if (result.releaseName == null) {\n      result.releaseName = latestRelease.elementValueOrEmpty(\"title\")\n    }\n\n    if (result.releaseNotes == null) {\n      result.releaseNotes = computeReleaseNotes(this.updater.currentVersion, this.updater.fullChangelog, feed, latestRelease)\n    }\n    return {\n      tag: tag,\n      ...result,\n    }\n  }\n\n  private async getLatestTagName(cancellationToken: CancellationToken): Promise<string | null> {\n    const options = this.options\n    // do not use API for GitHub to avoid limit, only for custom host or GitHub Enterprise\n    const url =\n      options.host == null || options.host === \"github.com\"\n        ? newUrlFromBase(`${this.basePath}/latest`, this.baseUrl)\n        : new URL(`${this.computeGithubBasePath(`/repos/${options.owner}/${options.repo}/releases`)}/latest`, this.baseApiUrl)\n    try {\n      const rawData = await this.httpRequest(url, { Accept: \"application/json\" }, cancellationToken)\n      if (rawData == null) {\n        return null\n      }\n\n      const releaseInfo: GithubReleaseInfo = JSON.parse(rawData)\n      return releaseInfo.tag_name\n    } catch (e: any) {\n      throw newError(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n    }\n  }\n\n  private get basePath(): string {\n    return `/${this.options.owner}/${this.options.repo}/releases`\n  }\n\n  resolveFiles(updateInfo: GithubUpdateInfo): Array<ResolvedUpdateFileInfo> {\n    // still replace space to - due to backward compatibility\n    return resolveFiles(updateInfo, this.baseUrl, p => this.getBaseDownloadPath(updateInfo.tag, p.replace(/ /g, \"-\")))\n  }\n\n  private getBaseDownloadPath(tag: string, fileName: string): string {\n    return `${this.basePath}/download/${tag}/${fileName}`\n  }\n}\n\ninterface GithubReleaseInfo {\n  readonly tag_name: string\n}\n\nfunction getNoteValue(parent: XElement): string {\n  const result = parent.elementValueOrEmpty(\"content\")\n  // GitHub reports empty notes as <content>No content.</content>\n  return result === \"No content.\" ? \"\" : result\n}\n\nexport function computeReleaseNotes(currentVersion: semver.SemVer, isFullChangelog: boolean, feed: XElement, latestRelease: XElement): string | Array<ReleaseNoteInfo> | null {\n  if (!isFullChangelog) {\n    return getNoteValue(latestRelease)\n  }\n\n  const releaseVersionRegExp = /\\/tag\\/v?([^/]+)$/\n\n  let latestVersion: string | undefined = undefined\n  try {\n    latestVersion = releaseVersionRegExp.exec(latestRelease.element(\"link\").attribute(\"href\"))![1]\n    latestVersion = semver.valid(latestVersion) ? latestVersion : undefined\n  } catch {\n    // If we cannot parse the latest release version, return null — notes cannot be determined\n  }\n\n  if (latestVersion == null) {\n    return null\n  }\n\n  const releaseNotes: Array<ReleaseNoteInfo> = []\n  for (const release of feed.getElements(\"entry\")) {\n    let versionRelease: string\n    try {\n      const match = releaseVersionRegExp.exec(release.element(\"link\").attribute(\"href\"))\n      if (!match) {\n        continue\n      }\n      versionRelease = match[1]\n    } catch {\n      continue\n    }\n    // skip non-semver tags (e.g. doc/website releases in monorepos)\n    if (!semver.valid(versionRelease)) {\n      continue\n    }\n\n    const isGreaterThanCurrent = semver.gt(versionRelease, currentVersion.raw)\n    const isLessOrEqualThanLatest = semver.lte(versionRelease, latestVersion)\n    if (isGreaterThanCurrent && isLessOrEqualThanLatest) {\n      releaseNotes.push({\n        version: versionRelease,\n        note: getNoteValue(release),\n      })\n    }\n  }\n  return releaseNotes.sort((a, b) => semver.rcompare(a.version, b.version))\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GitLabProvider = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const url_1 = require("url");
// @ts-ignore
const escapeRegExp = require("lodash.escaperegexp");
const util_1 = require("../util");
const Provider_1 = require("./Provider");
class GitLabProvider extends Provider_1.Provider {
    /**
     * Normalizes filenames by replacing spaces and underscores with dashes.
     *
     * This is a workaround to handle filename formatting differences between tools:
     * - electron-builder formats filenames like "test file.txt" as "test-file.txt"
     * - GitLab may provide asset URLs using underscores, such as "test_file.txt"
     *
     * Because of this mismatch, we can't reliably extract the correct filename from
     * the asset path without normalization. This function ensures consistent matching
     * across different filename formats by converting all spaces and underscores to dashes.
     *
     * @param filename The filename to normalize
     * @returns The normalized filename with spaces and underscores replaced by dashes
     */
    normalizeFilename(filename) {
        return filename.replace(/ |_/g, "-");
    }
    constructor(options, updater, runtimeOptions) {
        super({
            ...runtimeOptions,
            // GitLab might not support multiple range requests efficiently
            isUseMultipleRangeRequest: false,
        });
        this.options = options;
        this.updater = updater;
        // Cache the latest version info to avoid unnecessary HTTP requests
        this.cachedLatestVersion = null;
        const defaultHost = "gitlab.com";
        const host = options.host || defaultHost;
        this.baseApiUrl = (0, util_1.newBaseUrl)(`https://${host}/api/v4`);
    }
    createRequestOptions(url, headers) {
        const result = super.createRequestOptions(url, headers);
        result.redirect = "manual";
        return result;
    }
    get channel() {
        const result = this.updater.channel || this.options.channel;
        return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result);
    }
    async getLatestVersion() {
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        // Get latest release from GitLab API using the permalink/latest endpoint
        const latestReleaseUrl = (0, util_1.newUrlFromBase)(`projects/${this.options.projectId}/releases/permalink/latest`, this.baseApiUrl);
        const header = { Accept: "application/json", ...this.setAuthHeaderForToken(this.options.token || null) };
        let releaseResponse;
        try {
            releaseResponse = await this.httpRequest(latestReleaseUrl, header, cancellationToken);
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Unable to find latest release on GitLab (${latestReleaseUrl}): ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
        if (!releaseResponse) {
            throw (0, builder_util_runtime_1.newError)("No published releases on GitLab", "ERR_UPDATER_NO_PUBLISHED_VERSIONS");
        }
        let latestRelease;
        try {
            latestRelease = JSON.parse(releaseResponse);
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Unable to parse latest release response from GitLab (${latestReleaseUrl}): response was not valid JSON: ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
        if (latestRelease.upcoming_release) {
            throw (0, builder_util_runtime_1.newError)("Latest GitLab release is scheduled but not yet published", "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
        const tag = latestRelease.tag_name;
        // Look for channel file in release assets
        let rawData = null;
        let channelFile = "";
        let channelFileUrl = null;
        const fetchChannelData = async (channelName) => {
            channelFile = (0, util_1.getChannelFilename)(channelName);
            // Find the channel file in GitLab release assets
            const channelAsset = latestRelease.assets.links.find(asset => asset.name === channelFile);
            if (!channelAsset) {
                throw (0, builder_util_runtime_1.newError)(`Cannot find ${channelFile} in the latest release assets`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
            }
            channelFileUrl = new url_1.URL(channelAsset.direct_asset_url);
            const authHeaders = this.setAuthHeaderForToken(this.options.token || null);
            const headers = Object.keys(authHeaders).length ? authHeaders : undefined;
            try {
                const result = await this.httpRequest(channelFileUrl, headers, cancellationToken);
                if (!result) {
                    throw (0, builder_util_runtime_1.newError)(`Empty response from ${channelFileUrl}`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
                }
                return result;
            }
            catch (e) {
                if (e instanceof builder_util_runtime_1.HttpError && e.statusCode === 404) {
                    throw (0, builder_util_runtime_1.newError)(`Cannot find ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
                }
                throw e;
            }
        };
        try {
            rawData = await fetchChannelData(this.channel);
        }
        catch (e) {
            // If custom channel fails, try default channel as fallback
            if (this.channel !== this.getDefaultChannelName()) {
                rawData = await fetchChannelData(this.getDefaultChannelName());
            }
            else {
                throw e;
            }
        }
        if (!rawData) {
            throw (0, builder_util_runtime_1.newError)(`Unable to parse channel data from ${channelFile}`, "ERR_UPDATER_INVALID_UPDATE_INFO");
        }
        const result = (0, Provider_1.parseUpdateInfo)(rawData, channelFile, channelFileUrl);
        // Set release name from GitLab if not present
        if (result.releaseName == null) {
            result.releaseName = latestRelease.name;
        }
        // Set release notes from GitLab description if not present
        if (result.releaseNotes == null) {
            result.releaseNotes = latestRelease.description || null;
        }
        const gitlabUpdateInfo = {
            tag: tag,
            assets: this.convertAssetsToMap(latestRelease.assets),
            ...result,
        };
        // Cache the latest version info
        this.cachedLatestVersion = gitlabUpdateInfo;
        return gitlabUpdateInfo;
    }
    /**
     * Utility function to convert GitlabReleaseAsset to Map<string, string>
     * Maps asset names to their download URLs
     */
    convertAssetsToMap(assets) {
        const assetsMap = new Map();
        for (const asset of assets.links) {
            assetsMap.set(this.normalizeFilename(asset.name), asset.direct_asset_url);
        }
        return assetsMap;
    }
    /**
     * Find blockmap file URL in assets map for a specific filename
     */
    findBlockMapInAssets(assets, filename) {
        const possibleBlockMapNames = [`${filename}.blockmap`, `${this.normalizeFilename(filename)}.blockmap`];
        for (const blockMapName of possibleBlockMapNames) {
            const assetUrl = assets.get(blockMapName);
            if (assetUrl) {
                return new url_1.URL(assetUrl);
            }
        }
        return null;
    }
    async fetchReleaseInfoByVersion(version) {
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        // Try v-prefixed version first, then fallback to plain version
        const possibleReleaseIds = [`v${version}`, version];
        for (const releaseId of possibleReleaseIds) {
            const releaseUrl = (0, util_1.newUrlFromBase)(`projects/${this.options.projectId}/releases/${encodeURIComponent(releaseId)}`, this.baseApiUrl);
            try {
                const header = { Accept: "application/json", ...this.setAuthHeaderForToken(this.options.token || null) };
                const releaseResponse = await this.httpRequest(releaseUrl, header, cancellationToken);
                if (releaseResponse) {
                    const release = JSON.parse(releaseResponse);
                    return release;
                }
            }
            catch (e) {
                // If it's a 404 error, try the next release ID format
                if (e instanceof builder_util_runtime_1.HttpError && e.statusCode === 404) {
                    continue;
                }
                // For other errors, throw immediately
                throw (0, builder_util_runtime_1.newError)(`Unable to find release ${releaseId} on GitLab (${releaseUrl}): ${e.stack || e.message}`, "ERR_UPDATER_RELEASE_NOT_FOUND");
            }
        }
        // If we get here, none of the release ID formats worked
        throw (0, builder_util_runtime_1.newError)(`Unable to find release with version ${version} (tried: ${possibleReleaseIds.join(", ")}) on GitLab`, "ERR_UPDATER_RELEASE_NOT_FOUND");
    }
    setAuthHeaderForToken(token) {
        const headers = {};
        if (token != null) {
            // If the token starts with "Bearer", it is an OAuth application secret
            // Note that the original gitlab token would not start with "Bearer"
            // it might start with "gloas-", if so user needs to add "Bearer " prefix to the token
            if (token.startsWith("Bearer")) {
                headers.authorization = token;
            }
            else {
                headers["PRIVATE-TOKEN"] = token;
            }
        }
        return headers;
    }
    /**
     * Get version info for blockmap files, using cache when possible
     */
    async getVersionInfoForBlockMap(version) {
        // Check if we can use cached version info
        if (this.cachedLatestVersion && this.cachedLatestVersion.version === version) {
            return this.cachedLatestVersion.assets;
        }
        // Fetch version info if not cached or version doesn't match
        const versionInfo = await this.fetchReleaseInfoByVersion(version);
        if (versionInfo && versionInfo.assets) {
            return this.convertAssetsToMap(versionInfo.assets);
        }
        return null;
    }
    /**
     * Find blockmap URLs from version assets
     */
    async findBlockMapUrlsFromAssets(oldVersion, newVersion, baseFilename) {
        let newBlockMapUrl = null;
        let oldBlockMapUrl = null;
        // Get new version assets
        const newVersionAssets = await this.getVersionInfoForBlockMap(newVersion);
        if (newVersionAssets) {
            newBlockMapUrl = this.findBlockMapInAssets(newVersionAssets, baseFilename);
        }
        // Get old version assets
        const oldVersionAssets = await this.getVersionInfoForBlockMap(oldVersion);
        if (oldVersionAssets) {
            const oldFilename = baseFilename.replace(new RegExp(escapeRegExp(newVersion), "g"), oldVersion);
            oldBlockMapUrl = this.findBlockMapInAssets(oldVersionAssets, oldFilename);
        }
        return [oldBlockMapUrl, newBlockMapUrl];
    }
    async getBlockMapFiles(baseUrl, oldVersion, newVersion, oldBlockMapFileBaseUrl = null) {
        // If is `project_upload`, find blockmap files from corresponding gitLab assets
        // Because each asset has an unique path that includes an identified hash code,
        // e.g. https://gitlab.com/-/project/71361100/uploads/051f27a925eaf679f2ad688105362acc/latest.yml
        if (this.options.uploadTarget === "project_upload") {
            // Get the base filename from the URL to find corresponding blockmap files
            const baseFilename = baseUrl.pathname.split("/").pop() || "";
            // Try to find blockmap files in GitLab assets
            const [oldBlockMapUrl, newBlockMapUrl] = await this.findBlockMapUrlsFromAssets(oldVersion, newVersion, baseFilename);
            if (!newBlockMapUrl) {
                throw (0, builder_util_runtime_1.newError)(`Cannot find blockmap file for ${newVersion} in GitLab assets`, "ERR_UPDATER_BLOCKMAP_FILE_NOT_FOUND");
            }
            if (!oldBlockMapUrl) {
                throw (0, builder_util_runtime_1.newError)(`Cannot find blockmap file for ${oldVersion} in GitLab assets`, "ERR_UPDATER_BLOCKMAP_FILE_NOT_FOUND");
            }
            return [oldBlockMapUrl, newBlockMapUrl];
        }
        else {
            return super.getBlockMapFiles(baseUrl, oldVersion, newVersion, oldBlockMapFileBaseUrl);
        }
    }
    resolveFiles(updateInfo) {
        return (0, Provider_1.getFileList)(updateInfo).map((fileInfo) => {
            // Try both original and normalized filename formats
            const possibleNames = [
                fileInfo.url, // Original filename
                this.normalizeFilename(fileInfo.url), // Normalized filename (spaces/underscores → dashes)
            ];
            const matchingAssetName = possibleNames.find(name => updateInfo.assets.has(name));
            const assetUrl = matchingAssetName ? updateInfo.assets.get(matchingAssetName) : undefined;
            if (!assetUrl) {
                throw (0, builder_util_runtime_1.newError)(`Cannot find asset "${fileInfo.url}" in GitLab release assets. Available assets: ${Array.from(updateInfo.assets.keys()).join(", ")}`, "ERR_UPDATER_ASSET_NOT_FOUND");
            }
            return {
                url: new url_1.URL(assetUrl),
                info: fileInfo,
            };
        });
    }
    toString() {
        return `GitLab (projectId: ${this.options.projectId}, channel: ${this.channel})`;
    }
}
exports.GitLabProvider = GitLabProvider;
//# sourceMappingURL=GitLabProvider.js.map{"version":3,"file":"GitLabProvider.js","sourceRoot":"","sources":["../../src/providers/GitLabProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { CancellationToken, GitlabOptions, HttpError, newError, UpdateFileInfo, UpdateInfo, GitlabReleaseInfo, GitlabReleaseAsset } from \"builder-util-runtime\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { URL } from \"url\"\n// @ts-ignore\nimport * as escapeRegExp from \"lodash.escaperegexp\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { getFileList, parseUpdateInfo, Provider, ProviderRuntimeOptions } from \"./Provider\"\n\ninterface GitlabUpdateInfo extends UpdateInfo {\n  tag: string\n  assets: Map<string, string> // filename -> download URL mapping\n}\n\nexport class GitLabProvider extends Provider<GitlabUpdateInfo> {\n  private readonly baseApiUrl: URL\n  // Cache the latest version info to avoid unnecessary HTTP requests\n  private cachedLatestVersion: GitlabUpdateInfo | null = null\n\n  /**\n   * Normalizes filenames by replacing spaces and underscores with dashes.\n   *\n   * This is a workaround to handle filename formatting differences between tools:\n   * - electron-builder formats filenames like \"test file.txt\" as \"test-file.txt\"\n   * - GitLab may provide asset URLs using underscores, such as \"test_file.txt\"\n   *\n   * Because of this mismatch, we can't reliably extract the correct filename from\n   * the asset path without normalization. This function ensures consistent matching\n   * across different filename formats by converting all spaces and underscores to dashes.\n   *\n   * @param filename The filename to normalize\n   * @returns The normalized filename with spaces and underscores replaced by dashes\n   */\n  private normalizeFilename(filename: string): string {\n    return filename.replace(/ |_/g, \"-\")\n  }\n\n  constructor(\n    private readonly options: GitlabOptions,\n    private readonly updater: AppUpdater,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super({\n      ...runtimeOptions,\n      // GitLab might not support multiple range requests efficiently\n      isUseMultipleRangeRequest: false,\n    })\n\n    const defaultHost = \"gitlab.com\"\n    const host = options.host || defaultHost\n\n    this.baseApiUrl = newBaseUrl(`https://${host}/api/v4`)\n  }\n\n  protected createRequestOptions(url: URL, headers?: OutgoingHttpHeaders | null): RequestOptions {\n    const result = super.createRequestOptions(url, headers)\n    ;(result as any).redirect = \"manual\"\n    return result\n  }\n\n  private get channel(): string {\n    const result = this.updater.channel || this.options.channel\n    return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result)\n  }\n\n  async getLatestVersion(): Promise<GitlabUpdateInfo> {\n    const cancellationToken = new CancellationToken()\n\n    // Get latest release from GitLab API using the permalink/latest endpoint\n    const latestReleaseUrl = newUrlFromBase(`projects/${this.options.projectId}/releases/permalink/latest`, this.baseApiUrl)\n\n    const header = { Accept: \"application/json\", ...this.setAuthHeaderForToken(this.options.token || null) }\n    let releaseResponse: string | null\n    try {\n      releaseResponse = await this.httpRequest(latestReleaseUrl, header, cancellationToken)\n    } catch (e: any) {\n      throw newError(`Unable to find latest release on GitLab (${latestReleaseUrl}): ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n    }\n\n    if (!releaseResponse) {\n      throw newError(\"No published releases on GitLab\", \"ERR_UPDATER_NO_PUBLISHED_VERSIONS\")\n    }\n\n    let latestRelease: GitlabReleaseInfo\n    try {\n      latestRelease = JSON.parse(releaseResponse)\n    } catch (e: any) {\n      throw newError(\n        `Unable to parse latest release response from GitLab (${latestReleaseUrl}): response was not valid JSON: ${e.stack || e.message}`,\n        \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\"\n      )\n    }\n\n    if (latestRelease.upcoming_release) {\n      throw newError(\"Latest GitLab release is scheduled but not yet published\", \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n    }\n\n    const tag = latestRelease.tag_name\n\n    // Look for channel file in release assets\n    let rawData: string | null = null\n    let channelFile = \"\"\n    let channelFileUrl: URL | null = null\n\n    const fetchChannelData = async (channelName: string): Promise<string> => {\n      channelFile = getChannelFilename(channelName)\n\n      // Find the channel file in GitLab release assets\n      const channelAsset = latestRelease.assets.links.find(asset => asset.name === channelFile)\n\n      if (!channelAsset) {\n        throw newError(`Cannot find ${channelFile} in the latest release assets`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n      }\n\n      channelFileUrl = new URL(channelAsset.direct_asset_url)\n      const authHeaders = this.setAuthHeaderForToken(this.options.token || null)\n      const headers = Object.keys(authHeaders).length ? authHeaders : undefined\n\n      try {\n        const result = await this.httpRequest(channelFileUrl, headers, cancellationToken)\n        if (!result) {\n          throw newError(`Empty response from ${channelFileUrl}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n        }\n        return result\n      } catch (e: any) {\n        if (e instanceof HttpError && e.statusCode === 404) {\n          throw newError(`Cannot find ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n        }\n        throw e\n      }\n    }\n\n    try {\n      rawData = await fetchChannelData(this.channel)\n    } catch (e: any) {\n      // If custom channel fails, try default channel as fallback\n      if (this.channel !== this.getDefaultChannelName()) {\n        rawData = await fetchChannelData(this.getDefaultChannelName())\n      } else {\n        throw e\n      }\n    }\n\n    if (!rawData) {\n      throw newError(`Unable to parse channel data from ${channelFile}`, \"ERR_UPDATER_INVALID_UPDATE_INFO\")\n    }\n\n    const result = parseUpdateInfo(rawData, channelFile, channelFileUrl!)\n\n    // Set release name from GitLab if not present\n    if (result.releaseName == null) {\n      result.releaseName = latestRelease.name\n    }\n\n    // Set release notes from GitLab description if not present\n    if (result.releaseNotes == null) {\n      result.releaseNotes = latestRelease.description || null\n    }\n\n    const gitlabUpdateInfo = {\n      tag: tag,\n      assets: this.convertAssetsToMap(latestRelease.assets),\n      ...result,\n    }\n\n    // Cache the latest version info\n    this.cachedLatestVersion = gitlabUpdateInfo\n\n    return gitlabUpdateInfo\n  }\n\n  /**\n   * Utility function to convert GitlabReleaseAsset to Map<string, string>\n   * Maps asset names to their download URLs\n   */\n  private convertAssetsToMap(assets: GitlabReleaseAsset): Map<string, string> {\n    const assetsMap = new Map<string, string>()\n    for (const asset of assets.links) {\n      assetsMap.set(this.normalizeFilename(asset.name), asset.direct_asset_url)\n    }\n    return assetsMap\n  }\n\n  /**\n   * Find blockmap file URL in assets map for a specific filename\n   */\n  private findBlockMapInAssets(assets: Map<string, string>, filename: string): URL | null {\n    const possibleBlockMapNames = [`${filename}.blockmap`, `${this.normalizeFilename(filename)}.blockmap`]\n\n    for (const blockMapName of possibleBlockMapNames) {\n      const assetUrl = assets.get(blockMapName)\n      if (assetUrl) {\n        return new URL(assetUrl)\n      }\n    }\n    return null\n  }\n\n  private async fetchReleaseInfoByVersion(version: string): Promise<GitlabReleaseInfo | null> {\n    const cancellationToken = new CancellationToken()\n\n    // Try v-prefixed version first, then fallback to plain version\n    const possibleReleaseIds = [`v${version}`, version]\n\n    for (const releaseId of possibleReleaseIds) {\n      const releaseUrl = newUrlFromBase(`projects/${this.options.projectId}/releases/${encodeURIComponent(releaseId)}`, this.baseApiUrl)\n\n      try {\n        const header = { Accept: \"application/json\", ...this.setAuthHeaderForToken(this.options.token || null) }\n        const releaseResponse = await this.httpRequest(releaseUrl, header, cancellationToken)\n\n        if (releaseResponse) {\n          const release: GitlabReleaseInfo = JSON.parse(releaseResponse)\n          return release\n        }\n      } catch (e: any) {\n        // If it's a 404 error, try the next release ID format\n        if (e instanceof HttpError && e.statusCode === 404) {\n          continue\n        }\n        // For other errors, throw immediately\n        throw newError(`Unable to find release ${releaseId} on GitLab (${releaseUrl}): ${e.stack || e.message}`, \"ERR_UPDATER_RELEASE_NOT_FOUND\")\n      }\n    }\n\n    // If we get here, none of the release ID formats worked\n    throw newError(`Unable to find release with version ${version} (tried: ${possibleReleaseIds.join(\", \")}) on GitLab`, \"ERR_UPDATER_RELEASE_NOT_FOUND\")\n  }\n\n  private setAuthHeaderForToken(token: string | null): { [key: string]: string } {\n    const headers: { [key: string]: string } = {}\n\n    if (token != null) {\n      // If the token starts with \"Bearer\", it is an OAuth application secret\n      // Note that the original gitlab token would not start with \"Bearer\"\n      // it might start with \"gloas-\", if so user needs to add \"Bearer \" prefix to the token\n      if (token.startsWith(\"Bearer\")) {\n        headers.authorization = token\n      } else {\n        headers[\"PRIVATE-TOKEN\"] = token\n      }\n    }\n\n    return headers\n  }\n\n  /**\n   * Get version info for blockmap files, using cache when possible\n   */\n  private async getVersionInfoForBlockMap(version: string): Promise<Map<string, string> | null> {\n    // Check if we can use cached version info\n    if (this.cachedLatestVersion && this.cachedLatestVersion.version === version) {\n      return this.cachedLatestVersion.assets\n    }\n\n    // Fetch version info if not cached or version doesn't match\n    const versionInfo = await this.fetchReleaseInfoByVersion(version)\n    if (versionInfo && versionInfo.assets) {\n      return this.convertAssetsToMap(versionInfo.assets)\n    }\n\n    return null\n  }\n\n  /**\n   * Find blockmap URLs from version assets\n   */\n  private async findBlockMapUrlsFromAssets(oldVersion: string, newVersion: string, baseFilename: string): Promise<[URL | null, URL | null]> {\n    let newBlockMapUrl: URL | null = null\n    let oldBlockMapUrl: URL | null = null\n\n    // Get new version assets\n    const newVersionAssets = await this.getVersionInfoForBlockMap(newVersion)\n    if (newVersionAssets) {\n      newBlockMapUrl = this.findBlockMapInAssets(newVersionAssets, baseFilename)\n    }\n\n    // Get old version assets\n    const oldVersionAssets = await this.getVersionInfoForBlockMap(oldVersion)\n    if (oldVersionAssets) {\n      const oldFilename = baseFilename.replace(new RegExp(escapeRegExp(newVersion), \"g\"), oldVersion)\n      oldBlockMapUrl = this.findBlockMapInAssets(oldVersionAssets, oldFilename)\n    }\n\n    return [oldBlockMapUrl, newBlockMapUrl]\n  }\n\n  async getBlockMapFiles(baseUrl: URL, oldVersion: string, newVersion: string, oldBlockMapFileBaseUrl: string | null = null): Promise<URL[]> {\n    // If is `project_upload`, find blockmap files from corresponding gitLab assets\n    // Because each asset has an unique path that includes an identified hash code,\n    // e.g. https://gitlab.com/-/project/71361100/uploads/051f27a925eaf679f2ad688105362acc/latest.yml\n    if (this.options.uploadTarget === \"project_upload\") {\n      // Get the base filename from the URL to find corresponding blockmap files\n      const baseFilename = baseUrl.pathname.split(\"/\").pop() || \"\"\n\n      // Try to find blockmap files in GitLab assets\n      const [oldBlockMapUrl, newBlockMapUrl] = await this.findBlockMapUrlsFromAssets(oldVersion, newVersion, baseFilename)\n\n      if (!newBlockMapUrl) {\n        throw newError(`Cannot find blockmap file for ${newVersion} in GitLab assets`, \"ERR_UPDATER_BLOCKMAP_FILE_NOT_FOUND\")\n      }\n\n      if (!oldBlockMapUrl) {\n        throw newError(`Cannot find blockmap file for ${oldVersion} in GitLab assets`, \"ERR_UPDATER_BLOCKMAP_FILE_NOT_FOUND\")\n      }\n\n      return [oldBlockMapUrl, newBlockMapUrl]\n    } else {\n      return super.getBlockMapFiles(baseUrl, oldVersion, newVersion, oldBlockMapFileBaseUrl)\n    }\n  }\n\n  resolveFiles(updateInfo: GitlabUpdateInfo): Array<ResolvedUpdateFileInfo> {\n    return getFileList(updateInfo).map((fileInfo: UpdateFileInfo) => {\n      // Try both original and normalized filename formats\n      const possibleNames = [\n        fileInfo.url, // Original filename\n        this.normalizeFilename(fileInfo.url), // Normalized filename (spaces/underscores → dashes)\n      ]\n\n      const matchingAssetName = possibleNames.find(name => updateInfo.assets.has(name))\n      const assetUrl = matchingAssetName ? updateInfo.assets.get(matchingAssetName) : undefined\n\n      if (!assetUrl) {\n        throw newError(\n          `Cannot find asset \"${fileInfo.url}\" in GitLab release assets. Available assets: ${Array.from(updateInfo.assets.keys()).join(\", \")}`,\n          \"ERR_UPDATER_ASSET_NOT_FOUND\"\n        )\n      }\n\n      return {\n        url: new URL(assetUrl),\n        info: fileInfo,\n      }\n    })\n  }\n\n  toString(): string {\n    return `GitLab (projectId: ${this.options.projectId}, channel: ${this.channel})`\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KeygenProvider = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const util_1 = require("../util");
const Provider_1 = require("./Provider");
class KeygenProvider extends Provider_1.Provider {
    constructor(configuration, updater, runtimeOptions) {
        super({
            ...runtimeOptions,
            isUseMultipleRangeRequest: false,
        });
        this.configuration = configuration;
        this.updater = updater;
        this.defaultHostname = "api.keygen.sh";
        const host = this.configuration.host || this.defaultHostname;
        this.baseUrl = (0, util_1.newBaseUrl)(`https://${host}/v1/accounts/${this.configuration.account}/artifacts?product=${this.configuration.product}`);
    }
    get channel() {
        return this.updater.channel || this.configuration.channel || "stable";
    }
    async getLatestVersion() {
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        const channelFile = (0, util_1.getChannelFilename)(this.getCustomChannelName(this.channel));
        const channelUrl = (0, util_1.newUrlFromBase)(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery);
        try {
            const updateInfo = await this.httpRequest(channelUrl, {
                Accept: "application/vnd.api+json",
                "Keygen-Version": "1.1",
            }, cancellationToken);
            return (0, Provider_1.parseUpdateInfo)(updateInfo, channelFile, channelUrl);
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Unable to find latest version on ${this.toString()}, please ensure release exists: ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
    }
    resolveFiles(updateInfo) {
        return (0, Provider_1.resolveFiles)(updateInfo, this.baseUrl);
    }
    toString() {
        const { account, product, platform } = this.configuration;
        return `Keygen (account: ${account}, product: ${product}, platform: ${platform}, channel: ${this.channel})`;
    }
}
exports.KeygenProvider = KeygenProvider;
//# sourceMappingURL=KeygenProvider.js.map{"version":3,"file":"KeygenProvider.js","sourceRoot":"","sources":["../../src/providers/KeygenProvider.ts"],"names":[],"mappings":";;;AAAA,+DAA6F;AAG7F,kCAAwE;AACxE,yCAA4F;AAE5F,MAAa,cAAe,SAAQ,mBAAoB;IAItD,YACmB,aAA4B,EAC5B,OAAmB,EACpC,cAAsC;QAEtC,KAAK,CAAC;YACJ,GAAG,cAAc;YACjB,yBAAyB,EAAE,KAAK;SACjC,CAAC,CAAA;QAPe,kBAAa,GAAb,aAAa,CAAe;QAC5B,YAAO,GAAP,OAAO,CAAY;QALrB,oBAAe,GAAG,eAAe,CAAA;QAYhD,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,CAAA;QAC5D,IAAI,CAAC,OAAO,GAAG,IAAA,iBAAU,EAAC,WAAW,IAAI,gBAAgB,IAAI,CAAC,aAAa,CAAC,OAAO,sBAAsB,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAA;IACxI,CAAC;IAED,IAAY,OAAO;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,IAAI,QAAQ,CAAA;IACvE,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,iBAAiB,GAAG,IAAI,wCAAiB,EAAE,CAAA;QACjD,MAAM,WAAW,GAAG,IAAA,yBAAkB,EAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;QAC/E,MAAM,UAAU,GAAG,IAAA,qBAAc,EAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;QAC5F,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,CACvC,UAAU,EACV;gBACE,MAAM,EAAE,0BAA0B;gBAClC,gBAAgB,EAAE,KAAK;aACxB,EACD,iBAAiB,CAClB,CAAA;YACD,OAAO,IAAA,0BAAe,EAAC,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,CAAA;QAC7D,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,MAAM,IAAA,+BAAQ,EAAC,oCAAoC,IAAI,CAAC,QAAQ,EAAE,mCAAmC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,sCAAsC,CAAC,CAAA;QACtK,CAAC;IACH,CAAC;IAED,YAAY,CAAC,UAAsB;QACjC,OAAO,IAAA,uBAAY,EAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC/C,CAAC;IAED,QAAQ;QACN,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,aAAa,CAAA;QACzD,OAAO,oBAAoB,OAAO,cAAc,OAAO,eAAe,QAAQ,cAAc,IAAI,CAAC,OAAO,GAAG,CAAA;IAC7G,CAAC;CACF;AAhDD,wCAgDC","sourcesContent":["import { CancellationToken, KeygenOptions, newError, UpdateInfo } from \"builder-util-runtime\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from \"./Provider\"\n\nexport class KeygenProvider extends Provider<UpdateInfo> {\n  private readonly defaultHostname = \"api.keygen.sh\"\n  private readonly baseUrl: URL\n\n  constructor(\n    private readonly configuration: KeygenOptions,\n    private readonly updater: AppUpdater,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super({\n      ...runtimeOptions,\n      isUseMultipleRangeRequest: false,\n    })\n    const host = this.configuration.host || this.defaultHostname\n    this.baseUrl = newBaseUrl(`https://${host}/v1/accounts/${this.configuration.account}/artifacts?product=${this.configuration.product}`)\n  }\n\n  private get channel(): string {\n    return this.updater.channel || this.configuration.channel || \"stable\"\n  }\n\n  async getLatestVersion(): Promise<UpdateInfo> {\n    const cancellationToken = new CancellationToken()\n    const channelFile = getChannelFilename(this.getCustomChannelName(this.channel))\n    const channelUrl = newUrlFromBase(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery)\n    try {\n      const updateInfo = await this.httpRequest(\n        channelUrl,\n        {\n          Accept: \"application/vnd.api+json\",\n          \"Keygen-Version\": \"1.1\",\n        },\n        cancellationToken\n      )\n      return parseUpdateInfo(updateInfo, channelFile, channelUrl)\n    } catch (e: any) {\n      throw newError(`Unable to find latest version on ${this.toString()}, please ensure release exists: ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n    }\n  }\n\n  resolveFiles(updateInfo: UpdateInfo): Array<ResolvedUpdateFileInfo> {\n    return resolveFiles(updateInfo, this.baseUrl)\n  }\n\n  toString() {\n    const { account, product, platform } = this.configuration\n    return `Keygen (account: ${account}, product: ${product}, platform: ${platform}, channel: ${this.channel})`\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PrivateGitHubProvider = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const js_yaml_1 = require("js-yaml");
const path = require("path");
const url_1 = require("url");
const util_1 = require("../util");
const GitHubProvider_1 = require("./GitHubProvider");
const Provider_1 = require("./Provider");
class PrivateGitHubProvider extends GitHubProvider_1.BaseGitHubProvider {
    constructor(options, updater, token, runtimeOptions) {
        super(options, "api.github.com", runtimeOptions);
        this.updater = updater;
        this.token = token;
    }
    createRequestOptions(url, headers) {
        const result = super.createRequestOptions(url, headers);
        result.redirect = "manual";
        return result;
    }
    async getLatestVersion() {
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        const channelFile = (0, util_1.getChannelFilename)(this.getDefaultChannelName());
        const releaseInfo = await this.getLatestVersionInfo(cancellationToken);
        const asset = releaseInfo.assets.find(it => it.name === channelFile);
        if (asset == null) {
            // html_url must be always, but just to be sure
            throw (0, builder_util_runtime_1.newError)(`Cannot find ${channelFile} in the release ${releaseInfo.html_url || releaseInfo.name}`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
        }
        const url = new url_1.URL(asset.url);
        let result;
        try {
            result = (0, js_yaml_1.load)((await this.httpRequest(url, this.configureHeaders("application/octet-stream"), cancellationToken)));
        }
        catch (e) {
            if (e instanceof builder_util_runtime_1.HttpError && e.statusCode === 404) {
                throw (0, builder_util_runtime_1.newError)(`Cannot find ${channelFile} in the latest release artifacts (${url}): ${e.stack || e.message}`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
            }
            throw e;
        }
        ;
        result.assets = releaseInfo.assets;
        return result;
    }
    get fileExtraDownloadHeaders() {
        return this.configureHeaders("application/octet-stream");
    }
    configureHeaders(accept) {
        return {
            accept,
            authorization: `token ${this.token}`,
        };
    }
    async getLatestVersionInfo(cancellationToken) {
        const allowPrerelease = this.updater.allowPrerelease;
        let basePath = this.basePath;
        if (!allowPrerelease) {
            basePath = `${basePath}/latest`;
        }
        const url = (0, util_1.newUrlFromBase)(basePath, this.baseUrl);
        try {
            const version = JSON.parse((await this.httpRequest(url, this.configureHeaders("application/vnd.github.v3+json"), cancellationToken)));
            // only `latest` can return a single ReleaseInfo. Otherwise, a list of ReleaseInfo is returned and we need to find the latest one ourselves
            if (allowPrerelease) {
                const candidates = version.filter(it => !it.draft);
                return candidates.find(it => it.prerelease) || candidates[0];
            }
            else {
                return version;
            }
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
    }
    get basePath() {
        return this.computeGithubBasePath(`/repos/${this.options.owner}/${this.options.repo}/releases`);
    }
    resolveFiles(updateInfo) {
        return (0, Provider_1.getFileList)(updateInfo).map(it => {
            const name = path.posix.basename(it.url).replace(/ /g, "-");
            const asset = updateInfo.assets.find(it => it != null && it.name === name);
            if (asset == null) {
                throw (0, builder_util_runtime_1.newError)(`Cannot find asset "${name}" in: ${JSON.stringify(updateInfo.assets, null, 2)}`, "ERR_UPDATER_ASSET_NOT_FOUND");
            }
            return {
                url: new url_1.URL(asset.url),
                info: it,
            };
        });
    }
}
exports.PrivateGitHubProvider = PrivateGitHubProvider;
//# sourceMappingURL=PrivateGitHubProvider.js.map{"version":3,"file":"PrivateGitHubProvider.js","sourceRoot":"","sources":["../../src/providers/PrivateGitHubProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { CancellationToken, GithubOptions, HttpError, newError, UpdateInfo } from \"builder-util-runtime\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { load } from \"js-yaml\"\nimport * as path from \"path\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { URL } from \"url\"\nimport { getChannelFilename, newUrlFromBase } from \"../util\"\nimport { BaseGitHubProvider } from \"./GitHubProvider\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getFileList, ProviderRuntimeOptions } from \"./Provider\"\n\nexport interface PrivateGitHubUpdateInfo extends UpdateInfo {\n  assets: Array<Asset>\n}\n\nexport class PrivateGitHubProvider extends BaseGitHubProvider<PrivateGitHubUpdateInfo> {\n  constructor(\n    options: GithubOptions,\n    private readonly updater: AppUpdater,\n    private readonly token: string,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super(options, \"api.github.com\", runtimeOptions)\n  }\n\n  protected createRequestOptions(url: URL, headers?: OutgoingHttpHeaders | null): RequestOptions {\n    const result = super.createRequestOptions(url, headers)\n    ;(result as any).redirect = \"manual\"\n    return result\n  }\n\n  async getLatestVersion(): Promise<PrivateGitHubUpdateInfo> {\n    const cancellationToken = new CancellationToken()\n    const channelFile = getChannelFilename(this.getDefaultChannelName())\n\n    const releaseInfo = await this.getLatestVersionInfo(cancellationToken)\n    const asset = releaseInfo.assets.find(it => it.name === channelFile)\n    if (asset == null) {\n      // html_url must be always, but just to be sure\n      throw newError(`Cannot find ${channelFile} in the release ${releaseInfo.html_url || releaseInfo.name}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n    }\n\n    const url = new URL(asset.url)\n    let result: any\n    try {\n      result = load((await this.httpRequest(url, this.configureHeaders(\"application/octet-stream\"), cancellationToken))!)\n    } catch (e: any) {\n      if (e instanceof HttpError && e.statusCode === 404) {\n        throw newError(`Cannot find ${channelFile} in the latest release artifacts (${url}): ${e.stack || e.message}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n      }\n      throw e\n    }\n\n    ;(result as PrivateGitHubUpdateInfo).assets = releaseInfo.assets\n    return result\n  }\n\n  get fileExtraDownloadHeaders(): OutgoingHttpHeaders | null {\n    return this.configureHeaders(\"application/octet-stream\")\n  }\n\n  private configureHeaders(accept: string) {\n    return {\n      accept,\n      authorization: `token ${this.token}`,\n    }\n  }\n\n  private async getLatestVersionInfo(cancellationToken: CancellationToken): Promise<ReleaseInfo> {\n    const allowPrerelease = this.updater.allowPrerelease\n    let basePath = this.basePath\n    if (!allowPrerelease) {\n      basePath = `${basePath}/latest`\n    }\n\n    const url = newUrlFromBase(basePath, this.baseUrl)\n    try {\n      const version = JSON.parse((await this.httpRequest(url, this.configureHeaders(\"application/vnd.github.v3+json\"), cancellationToken))!)\n      // only `latest` can return a single ReleaseInfo. Otherwise, a list of ReleaseInfo is returned and we need to find the latest one ourselves\n      if (allowPrerelease) {\n        const candidates = (version as Array<ReleaseInfo>).filter(it => !it.draft)\n        return candidates.find(it => it.prerelease) || candidates[0]\n      } else {\n        return version\n      }\n    } catch (e: any) {\n      throw newError(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n    }\n  }\n\n  private get basePath(): string {\n    return this.computeGithubBasePath(`/repos/${this.options.owner}/${this.options.repo}/releases`)\n  }\n\n  resolveFiles(updateInfo: PrivateGitHubUpdateInfo): Array<ResolvedUpdateFileInfo> {\n    return getFileList(updateInfo).map(it => {\n      const name = path.posix.basename(it.url).replace(/ /g, \"-\")\n      const asset = updateInfo.assets.find(it => it != null && it.name === name)\n      if (asset == null) {\n        throw newError(`Cannot find asset \"${name}\" in: ${JSON.stringify(updateInfo.assets, null, 2)}`, \"ERR_UPDATER_ASSET_NOT_FOUND\")\n      }\n\n      return {\n        url: new URL(asset.url),\n        info: it,\n      }\n    })\n  }\n}\n\ninterface ReleaseInfo {\n  name: string\n  html_url: string\n  draft: boolean\n  prerelease: boolean\n  assets: Array<Asset>\n}\n\nexport interface Asset {\n  name: string\n  url: string\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Provider = void 0;
exports.findFile = findFile;
exports.parseUpdateInfo = parseUpdateInfo;
exports.getFileList = getFileList;
exports.resolveFiles = resolveFiles;
const builder_util_runtime_1 = require("builder-util-runtime");
const js_yaml_1 = require("js-yaml");
const url_1 = require("url");
const util_1 = require("../util");
// @ts-ignore
const escapeRegExp = require("lodash.escaperegexp");
class Provider {
    constructor(runtimeOptions) {
        this.runtimeOptions = runtimeOptions;
        this.requestHeaders = null;
        this.executor = runtimeOptions.executor;
    }
    // By default, the blockmap file is in the same directory as the main file
    // But some providers may have a different blockmap file, so we need to override this method
    getBlockMapFiles(baseUrl, oldVersion, newVersion, oldBlockMapFileBaseUrl = null) {
        const newBlockMapUrl = (0, util_1.newUrlFromBase)(`${baseUrl.pathname}.blockmap`, baseUrl);
        const oldBlockMapUrl = (0, util_1.newUrlFromBase)(`${baseUrl.pathname.replace(new RegExp(escapeRegExp(newVersion), "g"), oldVersion)}.blockmap`, oldBlockMapFileBaseUrl ? new url_1.URL(oldBlockMapFileBaseUrl) : baseUrl);
        return [oldBlockMapUrl, newBlockMapUrl];
    }
    get isUseMultipleRangeRequest() {
        return this.runtimeOptions.isUseMultipleRangeRequest !== false;
    }
    getChannelFilePrefix() {
        if (this.runtimeOptions.platform === "linux") {
            const arch = process.env["TEST_UPDATER_ARCH"] || process.arch;
            const archSuffix = arch === "x64" ? "" : `-${arch}`;
            return "-linux" + archSuffix;
        }
        else {
            return this.runtimeOptions.platform === "darwin" ? "-mac" : "";
        }
    }
    // due to historical reasons for windows we use channel name without platform specifier
    getDefaultChannelName() {
        return this.getCustomChannelName("latest");
    }
    getCustomChannelName(channel) {
        return `${channel}${this.getChannelFilePrefix()}`;
    }
    get fileExtraDownloadHeaders() {
        return null;
    }
    setRequestHeaders(value) {
        this.requestHeaders = value;
    }
    /**
     * Method to perform API request only to resolve update info, but not to download update.
     */
    httpRequest(url, headers, cancellationToken) {
        return this.executor.request(this.createRequestOptions(url, headers), cancellationToken);
    }
    createRequestOptions(url, headers) {
        const result = {};
        if (this.requestHeaders == null) {
            if (headers != null) {
                result.headers = headers;
            }
        }
        else {
            result.headers = headers == null ? this.requestHeaders : { ...this.requestHeaders, ...headers };
        }
        (0, builder_util_runtime_1.configureRequestUrl)(url, result);
        return result;
    }
}
exports.Provider = Provider;
function findFile(files, extension, not) {
    var _a;
    if (files.length === 0) {
        throw (0, builder_util_runtime_1.newError)("No files provided", "ERR_UPDATER_NO_FILES_PROVIDED");
    }
    const filteredFiles = files.filter(it => it.url.pathname.toLowerCase().endsWith(`.${extension.toLowerCase()}`));
    const result = (_a = filteredFiles.find(it => [it.url.pathname, it.info.url].some(n => n.includes(process.arch)))) !== null && _a !== void 0 ? _a : filteredFiles.shift();
    if (result) {
        return result;
    }
    else if (not == null) {
        return files[0];
    }
    else {
        return files.find(fileInfo => !not.some(ext => fileInfo.url.pathname.toLowerCase().endsWith(`.${ext.toLowerCase()}`)));
    }
}
function parseUpdateInfo(rawData, channelFile, channelFileUrl) {
    if (rawData == null) {
        throw (0, builder_util_runtime_1.newError)(`Cannot parse update info from ${channelFile} in the latest release artifacts (${channelFileUrl}): rawData: null`, "ERR_UPDATER_INVALID_UPDATE_INFO");
    }
    let result;
    try {
        result = (0, js_yaml_1.load)(rawData);
    }
    catch (e) {
        throw (0, builder_util_runtime_1.newError)(`Cannot parse update info from ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}, rawData: ${rawData}`, "ERR_UPDATER_INVALID_UPDATE_INFO");
    }
    return result;
}
function getFileList(updateInfo) {
    const files = updateInfo.files;
    if (files != null && files.length > 0) {
        return files;
    }
    // noinspection JSDeprecatedSymbols
    if (updateInfo.path != null) {
        // noinspection JSDeprecatedSymbols
        return [
            {
                url: updateInfo.path,
                sha2: updateInfo.sha2,
                sha512: updateInfo.sha512,
            },
        ];
    }
    else {
        throw (0, builder_util_runtime_1.newError)(`No files provided: ${(0, builder_util_runtime_1.safeStringifyJson)(updateInfo)}`, "ERR_UPDATER_NO_FILES_PROVIDED");
    }
}
function resolveFiles(updateInfo, baseUrl, pathTransformer = (p) => p) {
    const files = getFileList(updateInfo);
    const result = files.map(fileInfo => {
        if (fileInfo.sha2 == null && fileInfo.sha512 == null) {
            throw (0, builder_util_runtime_1.newError)(`Update info doesn't contain nor sha256 neither sha512 checksum: ${(0, builder_util_runtime_1.safeStringifyJson)(fileInfo)}`, "ERR_UPDATER_NO_CHECKSUM");
        }
        return {
            url: (0, util_1.newUrlFromBase)(pathTransformer(fileInfo.url), baseUrl),
            info: fileInfo,
        };
    });
    const packages = updateInfo.packages;
    const packageInfo = packages == null ? null : packages[process.arch] || packages.ia32;
    if (packageInfo != null) {
        ;
        result[0].packageInfo = {
            ...packageInfo,
            path: (0, util_1.newUrlFromBase)(pathTransformer(packageInfo.path), baseUrl).href,
        };
    }
    return result;
}
//# sourceMappingURL=Provider.js.map{"version":3,"file":"Provider.js","sourceRoot":"","sources":["../../src/providers/Provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { CancellationToken, configureRequestUrl, newError, safeStringifyJson, UpdateFileInfo, UpdateInfo, WindowsUpdateInfo } from \"builder-util-runtime\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { load } from \"js-yaml\"\nimport { URL } from \"url\"\nimport { ElectronHttpExecutor } from \"../electronHttpExecutor\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { newUrlFromBase } from \"../util\"\n// @ts-ignore\nimport * as escapeRegExp from \"lodash.escaperegexp\"\n\nexport type ProviderPlatform = \"darwin\" | \"linux\" | \"win32\"\n\nexport interface ProviderRuntimeOptions {\n  isUseMultipleRangeRequest: boolean\n  platform: ProviderPlatform\n\n  executor: ElectronHttpExecutor\n}\n\nexport abstract class Provider<T extends UpdateInfo> {\n  private requestHeaders: OutgoingHttpHeaders | null = null\n  protected readonly executor: ElectronHttpExecutor\n\n  protected constructor(private readonly runtimeOptions: ProviderRuntimeOptions) {\n    this.executor = runtimeOptions.executor\n  }\n\n  // By default, the blockmap file is in the same directory as the main file\n  // But some providers may have a different blockmap file, so we need to override this method\n  getBlockMapFiles(baseUrl: URL, oldVersion: string, newVersion: string, oldBlockMapFileBaseUrl: string | null = null): URL[] | Promise<URL[]> {\n    const newBlockMapUrl = newUrlFromBase(`${baseUrl.pathname}.blockmap`, baseUrl)\n    const oldBlockMapUrl = newUrlFromBase(\n      `${baseUrl.pathname.replace(new RegExp(escapeRegExp(newVersion), \"g\"), oldVersion)}.blockmap`,\n      oldBlockMapFileBaseUrl ? new URL(oldBlockMapFileBaseUrl) : baseUrl\n    )\n\n    return [oldBlockMapUrl, newBlockMapUrl]\n  }\n\n  get isUseMultipleRangeRequest(): boolean {\n    return this.runtimeOptions.isUseMultipleRangeRequest !== false\n  }\n\n  private getChannelFilePrefix(): string {\n    if (this.runtimeOptions.platform === \"linux\") {\n      const arch = process.env[\"TEST_UPDATER_ARCH\"] || process.arch\n      const archSuffix = arch === \"x64\" ? \"\" : `-${arch}`\n      return \"-linux\" + archSuffix\n    } else {\n      return this.runtimeOptions.platform === \"darwin\" ? \"-mac\" : \"\"\n    }\n  }\n\n  // due to historical reasons for windows we use channel name without platform specifier\n  protected getDefaultChannelName(): string {\n    return this.getCustomChannelName(\"latest\")\n  }\n\n  protected getCustomChannelName(channel: string): string {\n    return `${channel}${this.getChannelFilePrefix()}`\n  }\n\n  get fileExtraDownloadHeaders(): OutgoingHttpHeaders | null {\n    return null\n  }\n\n  setRequestHeaders(value: OutgoingHttpHeaders | null): void {\n    this.requestHeaders = value\n  }\n\n  abstract getLatestVersion(): Promise<T>\n\n  abstract resolveFiles(updateInfo: T): Array<ResolvedUpdateFileInfo>\n\n  /**\n   * Method to perform API request only to resolve update info, but not to download update.\n   */\n  protected httpRequest(url: URL, headers?: OutgoingHttpHeaders | null, cancellationToken?: CancellationToken): Promise<string | null> {\n    return this.executor.request(this.createRequestOptions(url, headers), cancellationToken)\n  }\n\n  protected createRequestOptions(url: URL, headers?: OutgoingHttpHeaders | null): RequestOptions {\n    const result: RequestOptions = {}\n    if (this.requestHeaders == null) {\n      if (headers != null) {\n        result.headers = headers\n      }\n    } else {\n      result.headers = headers == null ? this.requestHeaders : { ...this.requestHeaders, ...headers }\n    }\n\n    configureRequestUrl(url, result)\n    return result\n  }\n}\n\nexport function findFile(files: Array<ResolvedUpdateFileInfo>, extension: string, not?: Array<string>): ResolvedUpdateFileInfo | null | undefined {\n  if (files.length === 0) {\n    throw newError(\"No files provided\", \"ERR_UPDATER_NO_FILES_PROVIDED\")\n  }\n\n  const filteredFiles = files.filter(it => it.url.pathname.toLowerCase().endsWith(`.${extension.toLowerCase()}`))\n  const result = filteredFiles.find(it => [it.url.pathname, it.info.url].some(n => n.includes(process.arch))) ?? filteredFiles.shift()\n\n  if (result) {\n    return result\n  } else if (not == null) {\n    return files[0]\n  } else {\n    return files.find(fileInfo => !not.some(ext => fileInfo.url.pathname.toLowerCase().endsWith(`.${ext.toLowerCase()}`)))\n  }\n}\n\nexport function parseUpdateInfo(rawData: string | null, channelFile: string, channelFileUrl: URL): UpdateInfo {\n  if (rawData == null) {\n    throw newError(`Cannot parse update info from ${channelFile} in the latest release artifacts (${channelFileUrl}): rawData: null`, \"ERR_UPDATER_INVALID_UPDATE_INFO\")\n  }\n\n  let result: UpdateInfo\n  try {\n    result = load(rawData) as UpdateInfo\n  } catch (e: any) {\n    throw newError(\n      `Cannot parse update info from ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}, rawData: ${rawData}`,\n      \"ERR_UPDATER_INVALID_UPDATE_INFO\"\n    )\n  }\n  return result\n}\n\nexport function getFileList(updateInfo: UpdateInfo): Array<UpdateFileInfo> {\n  const files = updateInfo.files\n  if (files != null && files.length > 0) {\n    return files\n  }\n\n  // noinspection JSDeprecatedSymbols\n  if (updateInfo.path != null) {\n    // noinspection JSDeprecatedSymbols\n    return [\n      {\n        url: updateInfo.path,\n        sha2: (updateInfo as any).sha2,\n        sha512: updateInfo.sha512,\n      } as any,\n    ]\n  } else {\n    throw newError(`No files provided: ${safeStringifyJson(updateInfo)}`, \"ERR_UPDATER_NO_FILES_PROVIDED\")\n  }\n}\n\nexport function resolveFiles(updateInfo: UpdateInfo, baseUrl: URL, pathTransformer: (p: string) => string = (p: string): string => p): Array<ResolvedUpdateFileInfo> {\n  const files = getFileList(updateInfo)\n  const result: Array<ResolvedUpdateFileInfo> = files.map(fileInfo => {\n    if ((fileInfo as any).sha2 == null && fileInfo.sha512 == null) {\n      throw newError(`Update info doesn't contain nor sha256 neither sha512 checksum: ${safeStringifyJson(fileInfo)}`, \"ERR_UPDATER_NO_CHECKSUM\")\n    }\n    return {\n      url: newUrlFromBase(pathTransformer(fileInfo.url), baseUrl),\n      info: fileInfo,\n    }\n  })\n\n  const packages = (updateInfo as WindowsUpdateInfo).packages\n  const packageInfo = packages == null ? null : packages[process.arch] || packages.ia32\n  if (packageInfo != null) {\n    ;(result[0] as any).packageInfo = {\n      ...packageInfo,\n      path: newUrlFromBase(pathTransformer(packageInfo.path), baseUrl).href,\n    }\n  }\n  return result\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataSplitter = void 0;
exports.copyData = copyData;
const builder_util_runtime_1 = require("builder-util-runtime");
const fs_1 = require("fs");
const stream_1 = require("stream");
const downloadPlanBuilder_1 = require("./downloadPlanBuilder");
const DOUBLE_CRLF = Buffer.from("\r\n\r\n");
var ReadState;
(function (ReadState) {
    ReadState[ReadState["INIT"] = 0] = "INIT";
    ReadState[ReadState["HEADER"] = 1] = "HEADER";
    ReadState[ReadState["BODY"] = 2] = "BODY";
})(ReadState || (ReadState = {}));
function copyData(task, out, oldFileFd, reject, resolve) {
    const readStream = (0, fs_1.createReadStream)("", {
        fd: oldFileFd,
        autoClose: false,
        start: task.start,
        // end is inclusive
        end: task.end - 1,
    });
    readStream.on("error", reject);
    readStream.once("end", resolve);
    readStream.pipe(out, {
        end: false,
    });
}
class DataSplitter extends stream_1.Writable {
    constructor(out, options, partIndexToTaskIndex, boundary, partIndexToLength, finishHandler, grandTotalBytes, onProgress) {
        super();
        this.out = out;
        this.options = options;
        this.partIndexToTaskIndex = partIndexToTaskIndex;
        this.partIndexToLength = partIndexToLength;
        this.finishHandler = finishHandler;
        this.grandTotalBytes = grandTotalBytes;
        this.onProgress = onProgress;
        // properties for progress update calculations
        this.start = Date.now(); // download start time used to calculate average rate
        this.nextUpdate = this.start + 1000; // timestamp of next update to prevent updates more often than once per second
        this.transferred = 0; // total number of bytes transferred
        this.delta = 0; // number of bytes transferred since last update, reset after each update
        this.partIndex = -1;
        this.headerListBuffer = null;
        this.readState = ReadState.INIT;
        this.ignoreByteCount = 0;
        this.remainingPartDataCount = 0;
        this.actualPartLength = 0;
        this.boundaryLength = boundary.length + 4; /* size of \r\n-- */
        // first chunk doesn't start with \r\n
        this.ignoreByteCount = this.boundaryLength - 2;
    }
    get isFinished() {
        return this.partIndex === this.partIndexToLength.length;
    }
    // noinspection JSUnusedGlobalSymbols
    _write(data, encoding, callback) {
        if (this.isFinished) {
            console.error(`Trailing ignored data: ${data.length} bytes`);
            return;
        }
        this.handleData(data)
            .then(() => {
            if (this.onProgress) {
                const now = Date.now();
                if ((now >= this.nextUpdate || this.transferred === this.grandTotalBytes) && this.grandTotalBytes && (now - this.start) / 1000) {
                    this.nextUpdate = now + 1000;
                    this.onProgress({
                        total: this.grandTotalBytes,
                        delta: this.delta,
                        transferred: this.transferred,
                        percent: (this.transferred / this.grandTotalBytes) * 100,
                        bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),
                    });
                    this.delta = 0;
                }
            }
            callback();
        })
            .catch(callback);
    }
    async handleData(chunk) {
        let start = 0;
        if (this.ignoreByteCount !== 0 && this.remainingPartDataCount !== 0) {
            throw (0, builder_util_runtime_1.newError)("Internal error", "ERR_DATA_SPLITTER_BYTE_COUNT_MISMATCH");
        }
        if (this.ignoreByteCount > 0) {
            const toIgnore = Math.min(this.ignoreByteCount, chunk.length);
            this.ignoreByteCount -= toIgnore;
            start = toIgnore;
        }
        else if (this.remainingPartDataCount > 0) {
            const toRead = Math.min(this.remainingPartDataCount, chunk.length);
            this.remainingPartDataCount -= toRead;
            await this.processPartData(chunk, 0, toRead);
            start = toRead;
        }
        if (start === chunk.length) {
            return;
        }
        if (this.readState === ReadState.HEADER) {
            const headerListEnd = this.searchHeaderListEnd(chunk, start);
            if (headerListEnd === -1) {
                return;
            }
            start = headerListEnd;
            this.readState = ReadState.BODY;
            // header list is ignored, we don't need it
            this.headerListBuffer = null;
        }
        while (true) {
            if (this.readState === ReadState.BODY) {
                this.readState = ReadState.INIT;
            }
            else {
                this.partIndex++;
                let taskIndex = this.partIndexToTaskIndex.get(this.partIndex);
                if (taskIndex == null) {
                    if (this.isFinished) {
                        taskIndex = this.options.end;
                    }
                    else {
                        throw (0, builder_util_runtime_1.newError)("taskIndex is null", "ERR_DATA_SPLITTER_TASK_INDEX_IS_NULL");
                    }
                }
                const prevTaskIndex = this.partIndex === 0 ? this.options.start : this.partIndexToTaskIndex.get(this.partIndex - 1) + 1; /* prev part is download, next maybe copy */
                if (prevTaskIndex < taskIndex) {
                    await this.copyExistingData(prevTaskIndex, taskIndex);
                }
                else if (prevTaskIndex > taskIndex) {
                    throw (0, builder_util_runtime_1.newError)("prevTaskIndex must be < taskIndex", "ERR_DATA_SPLITTER_TASK_INDEX_ASSERT_FAILED");
                }
                if (this.isFinished) {
                    this.onPartEnd();
                    this.finishHandler();
                    return;
                }
                start = this.searchHeaderListEnd(chunk, start);
                if (start === -1) {
                    this.readState = ReadState.HEADER;
                    return;
                }
            }
            const partLength = this.partIndexToLength[this.partIndex];
            const end = start + partLength;
            const effectiveEnd = Math.min(end, chunk.length);
            await this.processPartStarted(chunk, start, effectiveEnd);
            this.remainingPartDataCount = partLength - (effectiveEnd - start);
            if (this.remainingPartDataCount > 0) {
                return;
            }
            start = end + this.boundaryLength;
            if (start >= chunk.length) {
                this.ignoreByteCount = this.boundaryLength - (chunk.length - end);
                return;
            }
        }
    }
    copyExistingData(index, end) {
        return new Promise((resolve, reject) => {
            const w = () => {
                if (index === end) {
                    resolve();
                    return;
                }
                const task = this.options.tasks[index];
                if (task.kind !== downloadPlanBuilder_1.OperationKind.COPY) {
                    reject(new Error("Task kind must be COPY"));
                    return;
                }
                copyData(task, this.out, this.options.oldFileFd, reject, () => {
                    index++;
                    w();
                });
            };
            w();
        });
    }
    searchHeaderListEnd(chunk, readOffset) {
        const headerListEnd = chunk.indexOf(DOUBLE_CRLF, readOffset);
        if (headerListEnd !== -1) {
            return headerListEnd + DOUBLE_CRLF.length;
        }
        // not all headers data were received, save to buffer
        const partialChunk = readOffset === 0 ? chunk : chunk.slice(readOffset);
        if (this.headerListBuffer == null) {
            this.headerListBuffer = partialChunk;
        }
        else {
            this.headerListBuffer = Buffer.concat([this.headerListBuffer, partialChunk]);
        }
        return -1;
    }
    onPartEnd() {
        const expectedLength = this.partIndexToLength[this.partIndex - 1];
        if (this.actualPartLength !== expectedLength) {
            throw (0, builder_util_runtime_1.newError)(`Expected length: ${expectedLength} differs from actual: ${this.actualPartLength}`, "ERR_DATA_SPLITTER_LENGTH_MISMATCH");
        }
        this.actualPartLength = 0;
    }
    processPartStarted(data, start, end) {
        if (this.partIndex !== 0) {
            this.onPartEnd();
        }
        return this.processPartData(data, start, end);
    }
    processPartData(data, start, end) {
        this.actualPartLength += end - start;
        this.transferred += end - start;
        this.delta += end - start;
        const out = this.out;
        if (out.write(start === 0 && data.length === end ? data : data.slice(start, end))) {
            return Promise.resolve();
        }
        else {
            return new Promise((resolve, reject) => {
                out.on("error", reject);
                out.once("drain", () => {
                    out.removeListener("error", reject);
                    resolve();
                });
            });
        }
    }
}
exports.DataSplitter = DataSplitter;
//# sourceMappingURL=DataSplitter.js.map{"version":3,"file":"DataSplitter.js","sourceRoot":"","sources":["../../src/differentialDownloader/DataSplitter.ts"],"names":[],"mappings":"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","sourcesContent":["import { newError } from \"builder-util-runtime\"\nimport { createReadStream } from \"fs\"\nimport { Writable } from \"stream\"\nimport { Operation, OperationKind } from \"./downloadPlanBuilder\"\nimport { ProgressInfo } from \"./ProgressDifferentialDownloadCallbackTransform\"\n\nconst DOUBLE_CRLF = Buffer.from(\"\\r\\n\\r\\n\")\n\nenum ReadState {\n  INIT,\n  HEADER,\n  BODY,\n}\n\nexport interface PartListDataTask {\n  readonly oldFileFd: number\n  readonly tasks: Array<Operation>\n  readonly start: number\n  readonly end: number\n}\n\nexport function copyData(task: Operation, out: Writable, oldFileFd: number, reject: (error: Error) => void, resolve: () => void): void {\n  const readStream = createReadStream(\"\", {\n    fd: oldFileFd,\n    autoClose: false,\n    start: task.start,\n    // end is inclusive\n    end: task.end - 1,\n  })\n  readStream.on(\"error\", reject)\n  readStream.once(\"end\", resolve)\n  readStream.pipe(out, {\n    end: false,\n  })\n}\n\nexport class DataSplitter extends Writable {\n  // properties for progress update calculations\n  private start = Date.now() // download start time used to calculate average rate\n  private nextUpdate = this.start + 1000 // timestamp of next update to prevent updates more often than once per second\n  private transferred = 0 // total number of bytes transferred\n  private delta = 0 // number of bytes transferred since last update, reset after each update\n\n  partIndex = -1\n\n  private headerListBuffer: Buffer | null = null\n  private readState = ReadState.INIT\n  private ignoreByteCount = 0\n  private remainingPartDataCount = 0\n\n  private readonly boundaryLength: number\n\n  constructor(\n    private readonly out: Writable,\n    private readonly options: PartListDataTask,\n    private readonly partIndexToTaskIndex: Map<number, number>,\n    boundary: string,\n    private readonly partIndexToLength: Array<number>,\n    private readonly finishHandler: () => any,\n    private readonly grandTotalBytes: number,\n    private readonly onProgress?: (info: ProgressInfo) => any\n  ) {\n    super()\n\n    this.boundaryLength = boundary.length + 4 /* size of \\r\\n-- */\n    // first chunk doesn't start with \\r\\n\n    this.ignoreByteCount = this.boundaryLength - 2\n  }\n\n  get isFinished(): boolean {\n    return this.partIndex === this.partIndexToLength.length\n  }\n\n  // noinspection JSUnusedGlobalSymbols\n  _write(data: Buffer, encoding: string, callback: (error?: Error) => void): void {\n    if (this.isFinished) {\n      console.error(`Trailing ignored data: ${data.length} bytes`)\n      return\n    }\n\n    this.handleData(data)\n      .then(() => {\n        if (this.onProgress) {\n          const now = Date.now()\n          if ((now >= this.nextUpdate || this.transferred === this.grandTotalBytes) && this.grandTotalBytes && (now - this.start) / 1000) {\n            this.nextUpdate = now + 1000\n\n            this.onProgress({\n              total: this.grandTotalBytes,\n              delta: this.delta,\n              transferred: this.transferred,\n              percent: (this.transferred / this.grandTotalBytes) * 100,\n              bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),\n            })\n            this.delta = 0\n          }\n        }\n\n        callback()\n      })\n      .catch(callback)\n  }\n\n  private async handleData(chunk: Buffer): Promise<undefined> {\n    let start = 0\n\n    if (this.ignoreByteCount !== 0 && this.remainingPartDataCount !== 0) {\n      throw newError(\"Internal error\", \"ERR_DATA_SPLITTER_BYTE_COUNT_MISMATCH\")\n    }\n\n    if (this.ignoreByteCount > 0) {\n      const toIgnore = Math.min(this.ignoreByteCount, chunk.length)\n      this.ignoreByteCount -= toIgnore\n      start = toIgnore\n    } else if (this.remainingPartDataCount > 0) {\n      const toRead = Math.min(this.remainingPartDataCount, chunk.length)\n      this.remainingPartDataCount -= toRead\n      await this.processPartData(chunk, 0, toRead)\n      start = toRead\n    }\n\n    if (start === chunk.length) {\n      return\n    }\n\n    if (this.readState === ReadState.HEADER) {\n      const headerListEnd = this.searchHeaderListEnd(chunk, start)\n      if (headerListEnd === -1) {\n        return\n      }\n\n      start = headerListEnd\n      this.readState = ReadState.BODY\n      // header list is ignored, we don't need it\n      this.headerListBuffer = null\n    }\n\n    while (true) {\n      if (this.readState === ReadState.BODY) {\n        this.readState = ReadState.INIT\n      } else {\n        this.partIndex++\n\n        let taskIndex = this.partIndexToTaskIndex.get(this.partIndex)\n        if (taskIndex == null) {\n          if (this.isFinished) {\n            taskIndex = this.options.end\n          } else {\n            throw newError(\"taskIndex is null\", \"ERR_DATA_SPLITTER_TASK_INDEX_IS_NULL\")\n          }\n        }\n\n        const prevTaskIndex = this.partIndex === 0 ? this.options.start : this.partIndexToTaskIndex.get(this.partIndex - 1)! + 1 /* prev part is download, next maybe copy */\n        if (prevTaskIndex < taskIndex) {\n          await this.copyExistingData(prevTaskIndex, taskIndex)\n        } else if (prevTaskIndex > taskIndex) {\n          throw newError(\"prevTaskIndex must be < taskIndex\", \"ERR_DATA_SPLITTER_TASK_INDEX_ASSERT_FAILED\")\n        }\n\n        if (this.isFinished) {\n          this.onPartEnd()\n          this.finishHandler()\n          return\n        }\n\n        start = this.searchHeaderListEnd(chunk, start)\n\n        if (start === -1) {\n          this.readState = ReadState.HEADER\n          return\n        }\n      }\n\n      const partLength = this.partIndexToLength[this.partIndex]\n      const end = start + partLength\n      const effectiveEnd = Math.min(end, chunk.length)\n      await this.processPartStarted(chunk, start, effectiveEnd)\n      this.remainingPartDataCount = partLength - (effectiveEnd - start)\n      if (this.remainingPartDataCount > 0) {\n        return\n      }\n\n      start = end + this.boundaryLength\n      if (start >= chunk.length) {\n        this.ignoreByteCount = this.boundaryLength - (chunk.length - end)\n        return\n      }\n    }\n  }\n\n  private copyExistingData(index: number, end: number): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const w = (): void => {\n        if (index === end) {\n          resolve()\n          return\n        }\n\n        const task = this.options.tasks[index]\n        if (task.kind !== OperationKind.COPY) {\n          reject(new Error(\"Task kind must be COPY\"))\n          return\n        }\n\n        copyData(task, this.out, this.options.oldFileFd, reject, () => {\n          index++\n          w()\n        })\n      }\n      w()\n    })\n  }\n\n  private searchHeaderListEnd(chunk: Buffer, readOffset: number): number {\n    const headerListEnd = chunk.indexOf(DOUBLE_CRLF, readOffset)\n    if (headerListEnd !== -1) {\n      return headerListEnd + DOUBLE_CRLF.length\n    }\n\n    // not all headers data were received, save to buffer\n    const partialChunk = readOffset === 0 ? chunk : chunk.slice(readOffset)\n    if (this.headerListBuffer == null) {\n      this.headerListBuffer = partialChunk\n    } else {\n      this.headerListBuffer = Buffer.concat([this.headerListBuffer, partialChunk])\n    }\n    return -1\n  }\n\n  private actualPartLength = 0\n\n  private onPartEnd(): void {\n    const expectedLength = this.partIndexToLength[this.partIndex - 1]\n    if (this.actualPartLength !== expectedLength) {\n      throw newError(`Expected length: ${expectedLength} differs from actual: ${this.actualPartLength}`, \"ERR_DATA_SPLITTER_LENGTH_MISMATCH\")\n    }\n    this.actualPartLength = 0\n  }\n\n  private processPartStarted(data: Buffer, start: number, end: number): Promise<void> {\n    if (this.partIndex !== 0) {\n      this.onPartEnd()\n    }\n    return this.processPartData(data, start, end)\n  }\n\n  private processPartData(data: Buffer, start: number, end: number): Promise<void> {\n    this.actualPartLength += end - start\n    this.transferred += end - start\n    this.delta += end - start\n    const out = this.out\n    if (out.write(start === 0 && data.length === end ? data : data.slice(start, end))) {\n      return Promise.resolve()\n    } else {\n      return new Promise((resolve, reject) => {\n        out.on(\"error\", reject)\n        out.once(\"drain\", () => {\n          out.removeListener(\"error\", reject)\n          resolve()\n        })\n      })\n    }\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DifferentialDownloader = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const fs_extra_1 = require("fs-extra");
const fs_1 = require("fs");
const DataSplitter_1 = require("./DataSplitter");
const url_1 = require("url");
const downloadPlanBuilder_1 = require("./downloadPlanBuilder");
const multipleRangeDownloader_1 = require("./multipleRangeDownloader");
const ProgressDifferentialDownloadCallbackTransform_1 = require("./ProgressDifferentialDownloadCallbackTransform");
class DifferentialDownloader {
    // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected
    constructor(blockAwareFileInfo, httpExecutor, options) {
        this.blockAwareFileInfo = blockAwareFileInfo;
        this.httpExecutor = httpExecutor;
        this.options = options;
        this.fileMetadataBuffer = null;
        this.logger = options.logger;
    }
    createRequestOptions() {
        const result = {
            headers: {
                ...this.options.requestHeaders,
                accept: "*/*",
            },
        };
        (0, builder_util_runtime_1.configureRequestUrl)(this.options.newUrl, result);
        // user-agent, cache-control and other common options
        (0, builder_util_runtime_1.configureRequestOptions)(result);
        return result;
    }
    doDownload(oldBlockMap, newBlockMap) {
        // we don't check other metadata like compressionMethod - generic check that it is make sense to differentially update is suitable for it
        if (oldBlockMap.version !== newBlockMap.version) {
            throw new Error(`version is different (${oldBlockMap.version} - ${newBlockMap.version}), full download is required`);
        }
        const logger = this.logger;
        const operations = (0, downloadPlanBuilder_1.computeOperations)(oldBlockMap, newBlockMap, logger);
        if (logger.debug != null) {
            logger.debug(JSON.stringify(operations, null, 2));
        }
        let downloadSize = 0;
        let copySize = 0;
        for (const operation of operations) {
            const length = operation.end - operation.start;
            if (operation.kind === downloadPlanBuilder_1.OperationKind.DOWNLOAD) {
                downloadSize += length;
            }
            else {
                copySize += length;
            }
        }
        const newSize = this.blockAwareFileInfo.size;
        if (downloadSize + copySize + (this.fileMetadataBuffer == null ? 0 : this.fileMetadataBuffer.length) !== newSize) {
            throw new Error(`Internal error, size mismatch: downloadSize: ${downloadSize}, copySize: ${copySize}, newSize: ${newSize}`);
        }
        logger.info(`Full: ${formatBytes(newSize)}, To download: ${formatBytes(downloadSize)} (${Math.round(downloadSize / (newSize / 100))}%)`);
        return this.downloadFile(operations);
    }
    downloadFile(tasks) {
        const fdList = [];
        const closeFiles = () => {
            return Promise.all(fdList.map(openedFile => {
                return (0, fs_extra_1.close)(openedFile.descriptor).catch((e) => {
                    this.logger.error(`cannot close file "${openedFile.path}": ${e}`);
                });
            }));
        };
        return this.doDownloadFile(tasks, fdList)
            .then(closeFiles)
            .catch((e) => {
            // then must be after catch here (since then always throws error)
            return closeFiles()
                .catch(closeFilesError => {
                // closeFiles never throw error, but just to be sure
                try {
                    this.logger.error(`cannot close files: ${closeFilesError}`);
                }
                catch (errorOnLog) {
                    try {
                        console.error(errorOnLog);
                    }
                    catch (_ignored) {
                        // ok, give up and ignore error
                    }
                }
                throw e;
            })
                .then(() => {
                throw e;
            });
        });
    }
    async doDownloadFile(tasks, fdList) {
        const oldFileFd = await (0, fs_extra_1.open)(this.options.oldFile, "r");
        fdList.push({ descriptor: oldFileFd, path: this.options.oldFile });
        const newFileFd = await (0, fs_extra_1.open)(this.options.newFile, "w");
        fdList.push({ descriptor: newFileFd, path: this.options.newFile });
        const fileOut = (0, fs_1.createWriteStream)(this.options.newFile, { fd: newFileFd });
        await new Promise((resolve, reject) => {
            const streams = [];
            // Create our download info transformer if we have one
            let downloadInfoTransform = undefined;
            if (!this.options.isUseMultipleRangeRequest && this.options.onProgress) {
                const expectedByteCounts = [];
                let grandTotalBytes = 0;
                for (const task of tasks) {
                    if (task.kind === downloadPlanBuilder_1.OperationKind.DOWNLOAD) {
                        expectedByteCounts.push(task.end - task.start);
                        grandTotalBytes += task.end - task.start;
                    }
                }
                const progressDifferentialDownloadInfo = {
                    expectedByteCounts: expectedByteCounts,
                    grandTotal: grandTotalBytes,
                };
                downloadInfoTransform = new ProgressDifferentialDownloadCallbackTransform_1.ProgressDifferentialDownloadCallbackTransform(progressDifferentialDownloadInfo, this.options.cancellationToken, this.options.onProgress);
                streams.push(downloadInfoTransform);
            }
            const digestTransform = new builder_util_runtime_1.DigestTransform(this.blockAwareFileInfo.sha512);
            // to simply debug, do manual validation to allow file to be fully written
            digestTransform.isValidateOnEnd = false;
            streams.push(digestTransform);
            // noinspection JSArrowFunctionCanBeReplacedWithShorthand
            fileOut.on("finish", () => {
                ;
                fileOut.close(() => {
                    // remove from fd list because closed successfully
                    fdList.splice(1, 1);
                    try {
                        digestTransform.validate();
                    }
                    catch (e) {
                        reject(e);
                        return;
                    }
                    resolve(undefined);
                });
            });
            streams.push(fileOut);
            let lastStream = null;
            for (const stream of streams) {
                stream.on("error", reject);
                if (lastStream == null) {
                    lastStream = stream;
                }
                else {
                    lastStream = lastStream.pipe(stream);
                }
            }
            const firstStream = streams[0];
            let w;
            if (this.options.isUseMultipleRangeRequest) {
                w = (0, multipleRangeDownloader_1.executeTasksUsingMultipleRangeRequests)(this, tasks, firstStream, oldFileFd, reject);
                w(0);
                return;
            }
            let downloadOperationCount = 0;
            let actualUrl = null;
            this.logger.info(`Differential download: ${this.options.newUrl}`);
            const requestOptions = this.createRequestOptions();
            requestOptions.redirect = "manual";
            w = (index) => {
                var _a, _b;
                if (index >= tasks.length) {
                    if (this.fileMetadataBuffer != null) {
                        firstStream.write(this.fileMetadataBuffer);
                    }
                    firstStream.end();
                    return;
                }
                const operation = tasks[index++];
                if (operation.kind === downloadPlanBuilder_1.OperationKind.COPY) {
                    // We are copying, let's not send status updates to the UI
                    if (downloadInfoTransform) {
                        downloadInfoTransform.beginFileCopy();
                    }
                    (0, DataSplitter_1.copyData)(operation, firstStream, oldFileFd, reject, () => w(index));
                    return;
                }
                const range = `bytes=${operation.start}-${operation.end - 1}`;
                requestOptions.headers.range = range;
                (_b = (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug) === null || _b === void 0 ? void 0 : _b.call(_a, `download range: ${range}`);
                // We are starting to download
                if (downloadInfoTransform) {
                    downloadInfoTransform.beginRangeDownload();
                }
                const request = this.httpExecutor.createRequest(requestOptions, response => {
                    response.on("error", reject);
                    response.on("aborted", () => {
                        reject(new Error("response has been aborted by the server"));
                    });
                    // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.
                    if (response.statusCode >= 400) {
                        reject((0, builder_util_runtime_1.createHttpError)(response));
                    }
                    response.pipe(firstStream, {
                        end: false,
                    });
                    response.once("end", () => {
                        // Pass on that we are downloading a segment
                        if (downloadInfoTransform) {
                            downloadInfoTransform.endRangeDownload();
                        }
                        if (++downloadOperationCount === 100) {
                            downloadOperationCount = 0;
                            setTimeout(() => w(index), 1000);
                        }
                        else {
                            w(index);
                        }
                    });
                });
                request.on("redirect", (statusCode, method, redirectUrl) => {
                    this.logger.info(`Redirect to ${removeQuery(redirectUrl)}`);
                    actualUrl = redirectUrl;
                    (0, builder_util_runtime_1.configureRequestUrl)(new url_1.URL(actualUrl), requestOptions);
                    request.followRedirect();
                });
                this.httpExecutor.addErrorAndTimeoutHandlers(request, reject);
                request.end();
            };
            w(0);
        });
    }
    async readRemoteBytes(start, endInclusive) {
        const buffer = Buffer.allocUnsafe(endInclusive + 1 - start);
        const requestOptions = this.createRequestOptions();
        requestOptions.headers.range = `bytes=${start}-${endInclusive}`;
        let position = 0;
        await this.request(requestOptions, chunk => {
            chunk.copy(buffer, position);
            position += chunk.length;
        });
        if (position !== buffer.length) {
            throw new Error(`Received data length ${position} is not equal to expected ${buffer.length}`);
        }
        return buffer;
    }
    request(requestOptions, dataHandler) {
        return new Promise((resolve, reject) => {
            const request = this.httpExecutor.createRequest(requestOptions, response => {
                if (!(0, multipleRangeDownloader_1.checkIsRangesSupported)(response, reject)) {
                    return;
                }
                response.on("error", reject);
                response.on("aborted", () => {
                    reject(new Error("response has been aborted by the server"));
                });
                response.on("data", dataHandler);
                response.on("end", () => resolve());
            });
            this.httpExecutor.addErrorAndTimeoutHandlers(request, reject);
            request.end();
        });
    }
}
exports.DifferentialDownloader = DifferentialDownloader;
function formatBytes(value, symbol = " KB") {
    return new Intl.NumberFormat("en").format((value / 1024).toFixed(2)) + symbol;
}
// safety
function removeQuery(url) {
    const index = url.indexOf("?");
    return index < 0 ? url : url.substring(0, index);
}
//# sourceMappingURL=DifferentialDownloader.js.map{"version":3,"file":"DifferentialDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/DifferentialDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockMapDataHolder, createHttpError, DigestTransform, HttpExecutor, configureRequestUrl, configureRequestOptions } from \"builder-util-runtime\"\nimport { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { close, open } from \"fs-extra\"\nimport { createWriteStream } from \"fs\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { ProgressInfo, CancellationToken } from \"builder-util-runtime\"\nimport { Logger } from \"../types\"\nimport { copyData } from \"./DataSplitter\"\nimport { URL } from \"url\"\nimport { computeOperations, Operation, OperationKind } from \"./downloadPlanBuilder\"\nimport { checkIsRangesSupported, executeTasksUsingMultipleRangeRequests } from \"./multipleRangeDownloader\"\nimport { ProgressDifferentialDownloadCallbackTransform, ProgressDifferentialDownloadInfo } from \"./ProgressDifferentialDownloadCallbackTransform\"\n\nexport interface DifferentialDownloaderOptions {\n  readonly oldFile: string\n  readonly newUrl: URL\n  readonly logger: Logger\n  readonly newFile: string\n\n  readonly requestHeaders: OutgoingHttpHeaders | null\n\n  readonly isUseMultipleRangeRequest?: boolean\n\n  readonly cancellationToken: CancellationToken\n  onProgress?: (progress: ProgressInfo) => void\n}\n\nexport abstract class DifferentialDownloader {\n  fileMetadataBuffer: Buffer | null = null\n\n  private readonly logger: Logger\n\n  // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected\n  constructor(\n    protected readonly blockAwareFileInfo: BlockMapDataHolder,\n    readonly httpExecutor: HttpExecutor<any>,\n    readonly options: DifferentialDownloaderOptions\n  ) {\n    this.logger = options.logger\n  }\n\n  createRequestOptions(): RequestOptions {\n    const result = {\n      headers: {\n        ...this.options.requestHeaders,\n        accept: \"*/*\",\n      },\n    }\n    configureRequestUrl(this.options.newUrl, result)\n    // user-agent, cache-control and other common options\n    configureRequestOptions(result)\n    return result\n  }\n\n  protected doDownload(oldBlockMap: BlockMap, newBlockMap: BlockMap): Promise<any> {\n    // we don't check other metadata like compressionMethod - generic check that it is make sense to differentially update is suitable for it\n    if (oldBlockMap.version !== newBlockMap.version) {\n      throw new Error(`version is different (${oldBlockMap.version} - ${newBlockMap.version}), full download is required`)\n    }\n\n    const logger = this.logger\n    const operations = computeOperations(oldBlockMap, newBlockMap, logger)\n    if (logger.debug != null) {\n      logger.debug(JSON.stringify(operations, null, 2))\n    }\n\n    let downloadSize = 0\n    let copySize = 0\n    for (const operation of operations) {\n      const length = operation.end - operation.start\n      if (operation.kind === OperationKind.DOWNLOAD) {\n        downloadSize += length\n      } else {\n        copySize += length\n      }\n    }\n\n    const newSize = this.blockAwareFileInfo.size\n    if (downloadSize + copySize + (this.fileMetadataBuffer == null ? 0 : this.fileMetadataBuffer.length) !== newSize) {\n      throw new Error(`Internal error, size mismatch: downloadSize: ${downloadSize}, copySize: ${copySize}, newSize: ${newSize}`)\n    }\n\n    logger.info(`Full: ${formatBytes(newSize)}, To download: ${formatBytes(downloadSize)} (${Math.round(downloadSize / (newSize / 100))}%)`)\n\n    return this.downloadFile(operations)\n  }\n\n  private downloadFile(tasks: Array<Operation>): Promise<any> {\n    const fdList: Array<OpenedFile> = []\n    const closeFiles = (): Promise<Array<void>> => {\n      return Promise.all(\n        fdList.map(openedFile => {\n          return close(openedFile.descriptor).catch((e: any) => {\n            this.logger.error(`cannot close file \"${openedFile.path}\": ${e}`)\n          })\n        })\n      )\n    }\n    return this.doDownloadFile(tasks, fdList)\n      .then(closeFiles)\n      .catch((e: any) => {\n        // then must be after catch here (since then always throws error)\n        return closeFiles()\n          .catch(closeFilesError => {\n            // closeFiles never throw error, but just to be sure\n            try {\n              this.logger.error(`cannot close files: ${closeFilesError}`)\n            } catch (errorOnLog) {\n              try {\n                console.error(errorOnLog)\n              } catch (_ignored) {\n                // ok, give up and ignore error\n              }\n            }\n            throw e\n          })\n          .then(() => {\n            throw e\n          })\n      })\n  }\n\n  private async doDownloadFile(tasks: Array<Operation>, fdList: Array<OpenedFile>): Promise<any> {\n    const oldFileFd = await open(this.options.oldFile, \"r\")\n    fdList.push({ descriptor: oldFileFd, path: this.options.oldFile })\n    const newFileFd = await open(this.options.newFile, \"w\")\n    fdList.push({ descriptor: newFileFd, path: this.options.newFile })\n    const fileOut = createWriteStream(this.options.newFile, { fd: newFileFd })\n    await new Promise((resolve, reject) => {\n      const streams: Array<any> = []\n\n      // Create our download info transformer if we have one\n      let downloadInfoTransform: ProgressDifferentialDownloadCallbackTransform | undefined = undefined\n      if (!this.options.isUseMultipleRangeRequest && this.options.onProgress) {\n        const expectedByteCounts: Array<number> = []\n        let grandTotalBytes = 0\n\n        for (const task of tasks) {\n          if (task.kind === OperationKind.DOWNLOAD) {\n            expectedByteCounts.push(task.end - task.start)\n            grandTotalBytes += task.end - task.start\n          }\n        }\n\n        const progressDifferentialDownloadInfo: ProgressDifferentialDownloadInfo = {\n          expectedByteCounts: expectedByteCounts,\n          grandTotal: grandTotalBytes,\n        }\n\n        downloadInfoTransform = new ProgressDifferentialDownloadCallbackTransform(progressDifferentialDownloadInfo, this.options.cancellationToken, this.options.onProgress)\n        streams.push(downloadInfoTransform)\n      }\n\n      const digestTransform = new DigestTransform(this.blockAwareFileInfo.sha512)\n      // to simply debug, do manual validation to allow file to be fully written\n      digestTransform.isValidateOnEnd = false\n      streams.push(digestTransform)\n\n      // noinspection JSArrowFunctionCanBeReplacedWithShorthand\n      fileOut.on(\"finish\", () => {\n        ;(fileOut.close as any)(() => {\n          // remove from fd list because closed successfully\n          fdList.splice(1, 1)\n          try {\n            digestTransform.validate()\n          } catch (e: any) {\n            reject(e)\n            return\n          }\n\n          resolve(undefined)\n        })\n      })\n\n      streams.push(fileOut)\n\n      let lastStream = null\n      for (const stream of streams) {\n        stream.on(\"error\", reject)\n        if (lastStream == null) {\n          lastStream = stream\n        } else {\n          lastStream = lastStream.pipe(stream)\n        }\n      }\n\n      const firstStream = streams[0]\n\n      let w: any\n      if (this.options.isUseMultipleRangeRequest) {\n        w = executeTasksUsingMultipleRangeRequests(this, tasks, firstStream, oldFileFd, reject)\n        w(0)\n        return\n      }\n\n      let downloadOperationCount = 0\n      let actualUrl: string | null = null\n      this.logger.info(`Differential download: ${this.options.newUrl}`)\n\n      const requestOptions = this.createRequestOptions()\n      ;(requestOptions as any).redirect = \"manual\"\n\n      w = (index: number): void => {\n        if (index >= tasks.length) {\n          if (this.fileMetadataBuffer != null) {\n            firstStream.write(this.fileMetadataBuffer)\n          }\n          firstStream.end()\n          return\n        }\n\n        const operation = tasks[index++]\n        if (operation.kind === OperationKind.COPY) {\n          // We are copying, let's not send status updates to the UI\n          if (downloadInfoTransform) {\n            downloadInfoTransform.beginFileCopy()\n          }\n\n          copyData(operation, firstStream, oldFileFd, reject, () => w(index))\n          return\n        }\n\n        const range = `bytes=${operation.start}-${operation.end - 1}`\n        requestOptions.headers!.range = range\n\n        this.logger?.debug?.(`download range: ${range}`)\n\n        // We are starting to download\n        if (downloadInfoTransform) {\n          downloadInfoTransform.beginRangeDownload()\n        }\n\n        const request = this.httpExecutor.createRequest(requestOptions, response => {\n          response.on(\"error\", reject)\n          response.on(\"aborted\", () => {\n            reject(new Error(\"response has been aborted by the server\"))\n          })\n          // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n          if (response.statusCode >= 400) {\n            reject(createHttpError(response))\n          }\n\n          response.pipe(firstStream, {\n            end: false,\n          })\n          response.once(\"end\", () => {\n            // Pass on that we are downloading a segment\n            if (downloadInfoTransform) {\n              downloadInfoTransform.endRangeDownload()\n            }\n\n            if (++downloadOperationCount === 100) {\n              downloadOperationCount = 0\n              setTimeout(() => w(index), 1000)\n            } else {\n              w(index)\n            }\n          })\n        })\n        request.on(\"redirect\", (statusCode: number, method: string, redirectUrl: string) => {\n          this.logger.info(`Redirect to ${removeQuery(redirectUrl)}`)\n          actualUrl = redirectUrl\n          configureRequestUrl(new URL(actualUrl), requestOptions)\n          request.followRedirect()\n        })\n        this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n        request.end()\n      }\n\n      w(0)\n    })\n  }\n\n  protected async readRemoteBytes(start: number, endInclusive: number): Promise<Buffer> {\n    const buffer = Buffer.allocUnsafe(endInclusive + 1 - start)\n    const requestOptions = this.createRequestOptions()\n    requestOptions.headers!.range = `bytes=${start}-${endInclusive}`\n    let position = 0\n    await this.request(requestOptions, chunk => {\n      chunk.copy(buffer, position)\n      position += chunk.length\n    })\n\n    if (position !== buffer.length) {\n      throw new Error(`Received data length ${position} is not equal to expected ${buffer.length}`)\n    }\n    return buffer\n  }\n\n  private request(requestOptions: RequestOptions, dataHandler: (chunk: Buffer) => void): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const request = this.httpExecutor.createRequest(requestOptions, response => {\n        if (!checkIsRangesSupported(response, reject)) {\n          return\n        }\n\n        response.on(\"error\", reject)\n        response.on(\"aborted\", () => {\n          reject(new Error(\"response has been aborted by the server\"))\n        })\n\n        response.on(\"data\", dataHandler)\n        response.on(\"end\", () => resolve())\n      })\n      this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n      request.end()\n    })\n  }\n}\n\nfunction formatBytes(value: number, symbol = \" KB\"): string {\n  return new Intl.NumberFormat(\"en\").format((value / 1024).toFixed(2) as any) + symbol\n}\n\n// safety\nfunction removeQuery(url: string): string {\n  const index = url.indexOf(\"?\")\n  return index < 0 ? url : url.substring(0, index)\n}\n\ninterface OpenedFile {\n  readonly descriptor: number\n  readonly path: string\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileWithEmbeddedBlockMapDifferentialDownloader = void 0;
const fs_extra_1 = require("fs-extra");
const DifferentialDownloader_1 = require("./DifferentialDownloader");
const zlib_1 = require("zlib");
class FileWithEmbeddedBlockMapDifferentialDownloader extends DifferentialDownloader_1.DifferentialDownloader {
    async download() {
        const packageInfo = this.blockAwareFileInfo;
        const fileSize = packageInfo.size;
        const offset = fileSize - (packageInfo.blockMapSize + 4);
        this.fileMetadataBuffer = await this.readRemoteBytes(offset, fileSize - 1);
        const newBlockMap = readBlockMap(this.fileMetadataBuffer.slice(0, this.fileMetadataBuffer.length - 4));
        await this.doDownload(await readEmbeddedBlockMapData(this.options.oldFile), newBlockMap);
    }
}
exports.FileWithEmbeddedBlockMapDifferentialDownloader = FileWithEmbeddedBlockMapDifferentialDownloader;
function readBlockMap(data) {
    return JSON.parse((0, zlib_1.inflateRawSync)(data).toString());
}
async function readEmbeddedBlockMapData(file) {
    const fd = await (0, fs_extra_1.open)(file, "r");
    try {
        const fileSize = (await (0, fs_extra_1.fstat)(fd)).size;
        const sizeBuffer = Buffer.allocUnsafe(4);
        await (0, fs_extra_1.read)(fd, sizeBuffer, 0, sizeBuffer.length, fileSize - sizeBuffer.length);
        const dataBuffer = Buffer.allocUnsafe(sizeBuffer.readUInt32BE(0));
        await (0, fs_extra_1.read)(fd, dataBuffer, 0, dataBuffer.length, fileSize - sizeBuffer.length - dataBuffer.length);
        await (0, fs_extra_1.close)(fd);
        return readBlockMap(dataBuffer);
    }
    catch (e) {
        await (0, fs_extra_1.close)(fd);
        throw e;
    }
}
//# sourceMappingURL=FileWithEmbeddedBlockMapDifferentialDownloader.js.map{"version":3,"file":"FileWithEmbeddedBlockMapDifferentialDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.ts"],"names":[],"mappings":";;;AACA,uCAAmD;AACnD,qEAAiE;AACjE,+BAAqC;AAErC,MAAa,8CAA+C,SAAQ,+CAAsB;IACxF,KAAK,CAAC,QAAQ;QACZ,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAA;QAC3C,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAK,CAAA;QAClC,MAAM,MAAM,GAAG,QAAQ,GAAG,CAAC,WAAW,CAAC,YAAa,GAAG,CAAC,CAAC,CAAA;QACzD,IAAI,CAAC,kBAAkB,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAA;QAC1E,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;QACtG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAA;IAC1F,CAAC;CACF;AATD,wGASC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,qBAAc,EAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;AACpD,CAAC;AAED,KAAK,UAAU,wBAAwB,CAAC,IAAY;IAClD,MAAM,EAAE,GAAG,MAAM,IAAA,eAAI,EAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAChC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAA,gBAAK,EAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QACvC,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;QACxC,MAAM,IAAA,eAAI,EAAC,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;QAE9E,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;QACjE,MAAM,IAAA,eAAI,EAAC,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;QAClG,MAAM,IAAA,gBAAK,EAAC,EAAE,CAAC,CAAA;QAEf,OAAO,YAAY,CAAC,UAAU,CAAC,CAAA;IACjC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,IAAA,gBAAK,EAAC,EAAE,CAAC,CAAA;QACf,MAAM,CAAC,CAAA;IACT,CAAC;AACH,CAAC","sourcesContent":["import { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { close, fstat, open, read } from \"fs-extra\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\nimport { inflateRawSync } from \"zlib\"\n\nexport class FileWithEmbeddedBlockMapDifferentialDownloader extends DifferentialDownloader {\n  async download(): Promise<void> {\n    const packageInfo = this.blockAwareFileInfo\n    const fileSize = packageInfo.size!\n    const offset = fileSize - (packageInfo.blockMapSize! + 4)\n    this.fileMetadataBuffer = await this.readRemoteBytes(offset, fileSize - 1)\n    const newBlockMap = readBlockMap(this.fileMetadataBuffer.slice(0, this.fileMetadataBuffer.length - 4))\n    await this.doDownload(await readEmbeddedBlockMapData(this.options.oldFile), newBlockMap)\n  }\n}\n\nfunction readBlockMap(data: Buffer): BlockMap {\n  return JSON.parse(inflateRawSync(data).toString())\n}\n\nasync function readEmbeddedBlockMapData(file: string): Promise<BlockMap> {\n  const fd = await open(file, \"r\")\n  try {\n    const fileSize = (await fstat(fd)).size\n    const sizeBuffer = Buffer.allocUnsafe(4)\n    await read(fd, sizeBuffer, 0, sizeBuffer.length, fileSize - sizeBuffer.length)\n\n    const dataBuffer = Buffer.allocUnsafe(sizeBuffer.readUInt32BE(0))\n    await read(fd, dataBuffer, 0, dataBuffer.length, fileSize - sizeBuffer.length - dataBuffer.length)\n    await close(fd)\n\n    return readBlockMap(dataBuffer)\n  } catch (e: any) {\n    await close(fd)\n    throw e\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenericDifferentialDownloader = void 0;
const DifferentialDownloader_1 = require("./DifferentialDownloader");
class GenericDifferentialDownloader extends DifferentialDownloader_1.DifferentialDownloader {
    download(oldBlockMap, newBlockMap) {
        return this.doDownload(oldBlockMap, newBlockMap);
    }
}
exports.GenericDifferentialDownloader = GenericDifferentialDownloader;
//# sourceMappingURL=GenericDifferentialDownloader.js.map{"version":3,"file":"GenericDifferentialDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/GenericDifferentialDownloader.ts"],"names":[],"mappings":";;;AACA,qEAAiE;AAEjE,MAAa,6BAA8B,SAAQ,+CAAsB;IACvE,QAAQ,CAAC,WAAqB,EAAE,WAAqB;QACnD,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;IAClD,CAAC;CACF;AAJD,sEAIC","sourcesContent":["import { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\n\nexport class GenericDifferentialDownloader extends DifferentialDownloader {\n  download(oldBlockMap: BlockMap, newBlockMap: BlockMap): Promise<any> {\n    return this.doDownload(oldBlockMap, newBlockMap)\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProgressDifferentialDownloadCallbackTransform = void 0;
const stream_1 = require("stream");
var OperationKind;
(function (OperationKind) {
    OperationKind[OperationKind["COPY"] = 0] = "COPY";
    OperationKind[OperationKind["DOWNLOAD"] = 1] = "DOWNLOAD";
})(OperationKind || (OperationKind = {}));
class ProgressDifferentialDownloadCallbackTransform extends stream_1.Transform {
    constructor(progressDifferentialDownloadInfo, cancellationToken, onProgress) {
        super();
        this.progressDifferentialDownloadInfo = progressDifferentialDownloadInfo;
        this.cancellationToken = cancellationToken;
        this.onProgress = onProgress;
        this.start = Date.now();
        this.transferred = 0;
        this.delta = 0;
        this.expectedBytes = 0;
        this.index = 0;
        this.operationType = OperationKind.COPY;
        this.nextUpdate = this.start + 1000;
    }
    _transform(chunk, encoding, callback) {
        if (this.cancellationToken.cancelled) {
            callback(new Error("cancelled"), null);
            return;
        }
        // Don't send progress update when copying from disk
        if (this.operationType == OperationKind.COPY) {
            callback(null, chunk);
            return;
        }
        this.transferred += chunk.length;
        this.delta += chunk.length;
        const now = Date.now();
        if (now >= this.nextUpdate &&
            this.transferred !== this.expectedBytes /* will be emitted by endRangeDownload() */ &&
            this.transferred !== this.progressDifferentialDownloadInfo.grandTotal /* will be emitted on _flush */) {
            this.nextUpdate = now + 1000;
            this.onProgress({
                total: this.progressDifferentialDownloadInfo.grandTotal,
                delta: this.delta,
                transferred: this.transferred,
                percent: (this.transferred / this.progressDifferentialDownloadInfo.grandTotal) * 100,
                bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),
            });
            this.delta = 0;
        }
        callback(null, chunk);
    }
    beginFileCopy() {
        this.operationType = OperationKind.COPY;
    }
    beginRangeDownload() {
        this.operationType = OperationKind.DOWNLOAD;
        this.expectedBytes += this.progressDifferentialDownloadInfo.expectedByteCounts[this.index++];
    }
    endRangeDownload() {
        // _flush() will doour final 100%
        if (this.transferred !== this.progressDifferentialDownloadInfo.grandTotal) {
            this.onProgress({
                total: this.progressDifferentialDownloadInfo.grandTotal,
                delta: this.delta,
                transferred: this.transferred,
                percent: (this.transferred / this.progressDifferentialDownloadInfo.grandTotal) * 100,
                bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),
            });
        }
    }
    // Called when we are 100% done with the connection/download
    _flush(callback) {
        if (this.cancellationToken.cancelled) {
            callback(new Error("cancelled"));
            return;
        }
        this.onProgress({
            total: this.progressDifferentialDownloadInfo.grandTotal,
            delta: this.delta,
            transferred: this.transferred,
            percent: 100,
            bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),
        });
        this.delta = 0;
        this.transferred = 0;
        callback(null);
    }
}
exports.ProgressDifferentialDownloadCallbackTransform = ProgressDifferentialDownloadCallbackTransform;
//# sourceMappingURL=ProgressDifferentialDownloadCallbackTransform.js.map{"version":3,"file":"ProgressDifferentialDownloadCallbackTransform.js","sourceRoot":"","sources":["../../src/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.ts"],"names":[],"mappings":"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","sourcesContent":["import { Transform } from \"stream\"\nimport { CancellationToken } from \"builder-util-runtime\"\n\nenum OperationKind {\n  COPY,\n  DOWNLOAD,\n}\n\nexport interface ProgressInfo {\n  total: number\n  delta: number\n  transferred: number\n  percent: number\n  bytesPerSecond: number\n}\n\nexport interface ProgressDifferentialDownloadInfo {\n  expectedByteCounts: Array<number>\n  grandTotal: number\n}\n\nexport class ProgressDifferentialDownloadCallbackTransform extends Transform {\n  private start = Date.now()\n  private transferred = 0\n  private delta = 0\n  private expectedBytes = 0\n  private index = 0\n  private operationType = OperationKind.COPY\n\n  private nextUpdate = this.start + 1000\n\n  constructor(\n    private readonly progressDifferentialDownloadInfo: ProgressDifferentialDownloadInfo,\n    private readonly cancellationToken: CancellationToken,\n    private readonly onProgress: (info: ProgressInfo) => any\n  ) {\n    super()\n  }\n\n  _transform(chunk: any, encoding: string, callback: any) {\n    if (this.cancellationToken.cancelled) {\n      callback(new Error(\"cancelled\"), null)\n      return\n    }\n\n    // Don't send progress update when copying from disk\n    if (this.operationType == OperationKind.COPY) {\n      callback(null, chunk)\n      return\n    }\n\n    this.transferred += chunk.length\n    this.delta += chunk.length\n\n    const now = Date.now()\n    if (\n      now >= this.nextUpdate &&\n      this.transferred !== this.expectedBytes /* will be emitted by endRangeDownload() */ &&\n      this.transferred !== this.progressDifferentialDownloadInfo.grandTotal /* will be emitted on _flush */\n    ) {\n      this.nextUpdate = now + 1000\n\n      this.onProgress({\n        total: this.progressDifferentialDownloadInfo.grandTotal,\n        delta: this.delta,\n        transferred: this.transferred,\n        percent: (this.transferred / this.progressDifferentialDownloadInfo.grandTotal) * 100,\n        bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),\n      })\n      this.delta = 0\n    }\n\n    callback(null, chunk)\n  }\n\n  beginFileCopy(): void {\n    this.operationType = OperationKind.COPY\n  }\n\n  beginRangeDownload(): void {\n    this.operationType = OperationKind.DOWNLOAD\n\n    this.expectedBytes += this.progressDifferentialDownloadInfo.expectedByteCounts[this.index++]\n  }\n\n  endRangeDownload(): void {\n    // _flush() will doour final 100%\n    if (this.transferred !== this.progressDifferentialDownloadInfo.grandTotal) {\n      this.onProgress({\n        total: this.progressDifferentialDownloadInfo.grandTotal,\n        delta: this.delta,\n        transferred: this.transferred,\n        percent: (this.transferred / this.progressDifferentialDownloadInfo.grandTotal) * 100,\n        bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),\n      })\n    }\n  }\n\n  // Called when we are 100% done with the connection/download\n  _flush(callback: any): void {\n    if (this.cancellationToken.cancelled) {\n      callback(new Error(\"cancelled\"))\n      return\n    }\n\n    this.onProgress({\n      total: this.progressDifferentialDownloadInfo.grandTotal,\n      delta: this.delta,\n      transferred: this.transferred,\n      percent: 100,\n      bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),\n    })\n    this.delta = 0\n    this.transferred = 0\n\n    callback(null)\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OperationKind = void 0;
exports.computeOperations = computeOperations;
var OperationKind;
(function (OperationKind) {
    OperationKind[OperationKind["COPY"] = 0] = "COPY";
    OperationKind[OperationKind["DOWNLOAD"] = 1] = "DOWNLOAD";
})(OperationKind || (exports.OperationKind = OperationKind = {}));
function computeOperations(oldBlockMap, newBlockMap, logger) {
    const nameToOldBlocks = buildBlockFileMap(oldBlockMap.files);
    const nameToNewBlocks = buildBlockFileMap(newBlockMap.files);
    let lastOperation = null;
    // for now only one file is supported in block map
    const blockMapFile = newBlockMap.files[0];
    const operations = [];
    const name = blockMapFile.name;
    const oldEntry = nameToOldBlocks.get(name);
    if (oldEntry == null) {
        // new file (unrealistic case for now, because in any case both blockmap contain the only file named as "file")
        throw new Error(`no file ${name} in old blockmap`);
    }
    const newFile = nameToNewBlocks.get(name);
    let changedBlockCount = 0;
    const { checksumToOffset: checksumToOldOffset, checksumToOldSize } = buildChecksumMap(nameToOldBlocks.get(name), oldEntry.offset, logger);
    let newOffset = blockMapFile.offset;
    for (let i = 0; i < newFile.checksums.length; newOffset += newFile.sizes[i], i++) {
        const blockSize = newFile.sizes[i];
        const checksum = newFile.checksums[i];
        let oldOffset = checksumToOldOffset.get(checksum);
        if (oldOffset != null && checksumToOldSize.get(checksum) !== blockSize) {
            logger.warn(`Checksum ("${checksum}") matches, but size differs (old: ${checksumToOldSize.get(checksum)}, new: ${blockSize})`);
            oldOffset = undefined;
        }
        if (oldOffset === undefined) {
            // download data from new file
            changedBlockCount++;
            if (lastOperation != null && lastOperation.kind === OperationKind.DOWNLOAD && lastOperation.end === newOffset) {
                lastOperation.end += blockSize;
            }
            else {
                lastOperation = {
                    kind: OperationKind.DOWNLOAD,
                    start: newOffset,
                    end: newOffset + blockSize,
                    // oldBlocks: null,
                };
                validateAndAdd(lastOperation, operations, checksum, i);
            }
        }
        else {
            // reuse data from old file
            if (lastOperation != null && lastOperation.kind === OperationKind.COPY && lastOperation.end === oldOffset) {
                lastOperation.end += blockSize;
                // lastOperation.oldBlocks!!.push(checksum)
            }
            else {
                lastOperation = {
                    kind: OperationKind.COPY,
                    start: oldOffset,
                    end: oldOffset + blockSize,
                    // oldBlocks: [checksum]
                };
                validateAndAdd(lastOperation, operations, checksum, i);
            }
        }
    }
    if (changedBlockCount > 0) {
        logger.info(`File${blockMapFile.name === "file" ? "" : " " + blockMapFile.name} has ${changedBlockCount} changed blocks`);
    }
    return operations;
}
const isValidateOperationRange = process.env["DIFFERENTIAL_DOWNLOAD_PLAN_BUILDER_VALIDATE_RANGES"] === "true";
function validateAndAdd(operation, operations, checksum, index) {
    if (isValidateOperationRange && operations.length !== 0) {
        const lastOperation = operations[operations.length - 1];
        if (lastOperation.kind === operation.kind && operation.start < lastOperation.end && operation.start > lastOperation.start) {
            const min = [lastOperation.start, lastOperation.end, operation.start, operation.end].reduce((p, v) => (p < v ? p : v));
            throw new Error(`operation (block index: ${index}, checksum: ${checksum}, kind: ${OperationKind[operation.kind]}) overlaps previous operation (checksum: ${checksum}):\n` +
                `abs: ${lastOperation.start} until ${lastOperation.end} and ${operation.start} until ${operation.end}\n` +
                `rel: ${lastOperation.start - min} until ${lastOperation.end - min} and ${operation.start - min} until ${operation.end - min}`);
        }
    }
    operations.push(operation);
}
function buildChecksumMap(file, fileOffset, logger) {
    const checksumToOffset = new Map();
    const checksumToSize = new Map();
    let offset = fileOffset;
    for (let i = 0; i < file.checksums.length; i++) {
        const checksum = file.checksums[i];
        const size = file.sizes[i];
        const existing = checksumToSize.get(checksum);
        if (existing === undefined) {
            checksumToOffset.set(checksum, offset);
            checksumToSize.set(checksum, size);
        }
        else if (logger.debug != null) {
            const sizeExplanation = existing === size ? "(same size)" : `(size: ${existing}, this size: ${size})`;
            logger.debug(`${checksum} duplicated in blockmap ${sizeExplanation}, it doesn't lead to broken differential downloader, just corresponding block will be skipped)`);
        }
        offset += size;
    }
    return { checksumToOffset, checksumToOldSize: checksumToSize };
}
function buildBlockFileMap(list) {
    const result = new Map();
    for (const item of list) {
        result.set(item.name, item);
    }
    return result;
}
//# sourceMappingURL=downloadPlanBuilder.js.map{"version":3,"file":"downloadPlanBuilder.js","sourceRoot":"","sources":["../../src/differentialDownloader/downloadPlanBuilder.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockMap, BlockMapFile } from \"builder-util-runtime/out/blockMapApi\"\nimport { Logger } from \"../types\"\n\nexport enum OperationKind {\n  COPY,\n  DOWNLOAD,\n}\n\nexport interface Operation {\n  kind: OperationKind\n\n  // inclusive\n  start: number\n  // exclusive\n  end: number\n\n  // debug only\n  // oldBlocks: Array<string> | null\n}\n\nexport function computeOperations(oldBlockMap: BlockMap, newBlockMap: BlockMap, logger: Logger): Array<Operation> {\n  const nameToOldBlocks = buildBlockFileMap(oldBlockMap.files)\n  const nameToNewBlocks = buildBlockFileMap(newBlockMap.files)\n\n  let lastOperation: Operation | null = null\n\n  // for now only one file is supported in block map\n  const blockMapFile: { name: string; offset: number } = newBlockMap.files[0]\n  const operations: Array<Operation> = []\n  const name = blockMapFile.name\n  const oldEntry = nameToOldBlocks.get(name)\n  if (oldEntry == null) {\n    // new file (unrealistic case for now, because in any case both blockmap contain the only file named as \"file\")\n    throw new Error(`no file ${name} in old blockmap`)\n  }\n\n  const newFile = nameToNewBlocks.get(name)!\n  let changedBlockCount = 0\n\n  const { checksumToOffset: checksumToOldOffset, checksumToOldSize } = buildChecksumMap(nameToOldBlocks.get(name)!, oldEntry.offset, logger)\n\n  let newOffset = blockMapFile.offset\n  for (let i = 0; i < newFile.checksums.length; newOffset += newFile.sizes[i], i++) {\n    const blockSize: number = newFile.sizes[i]\n    const checksum = newFile.checksums[i]\n    let oldOffset = checksumToOldOffset.get(checksum)\n    if (oldOffset != null && checksumToOldSize.get(checksum) !== blockSize) {\n      logger.warn(`Checksum (\"${checksum}\") matches, but size differs (old: ${checksumToOldSize.get(checksum)}, new: ${blockSize})`)\n      oldOffset = undefined\n    }\n\n    if (oldOffset === undefined) {\n      // download data from new file\n      changedBlockCount++\n\n      if (lastOperation != null && lastOperation.kind === OperationKind.DOWNLOAD && lastOperation.end === newOffset) {\n        lastOperation.end += blockSize\n      } else {\n        lastOperation = {\n          kind: OperationKind.DOWNLOAD,\n          start: newOffset,\n          end: newOffset + blockSize,\n          // oldBlocks: null,\n        }\n        validateAndAdd(lastOperation, operations, checksum, i)\n      }\n    } else {\n      // reuse data from old file\n      if (lastOperation != null && lastOperation.kind === OperationKind.COPY && lastOperation.end === oldOffset) {\n        lastOperation.end += blockSize\n        // lastOperation.oldBlocks!!.push(checksum)\n      } else {\n        lastOperation = {\n          kind: OperationKind.COPY,\n          start: oldOffset,\n          end: oldOffset + blockSize,\n          // oldBlocks: [checksum]\n        }\n        validateAndAdd(lastOperation, operations, checksum, i)\n      }\n    }\n  }\n\n  if (changedBlockCount > 0) {\n    logger.info(`File${blockMapFile.name === \"file\" ? \"\" : \" \" + blockMapFile.name} has ${changedBlockCount} changed blocks`)\n  }\n  return operations\n}\n\nconst isValidateOperationRange = process.env[\"DIFFERENTIAL_DOWNLOAD_PLAN_BUILDER_VALIDATE_RANGES\"] === \"true\"\n\nfunction validateAndAdd(operation: Operation, operations: Array<Operation>, checksum: string, index: number): void {\n  if (isValidateOperationRange && operations.length !== 0) {\n    const lastOperation = operations[operations.length - 1]\n    if (lastOperation.kind === operation.kind && operation.start < lastOperation.end && operation.start > lastOperation.start) {\n      const min = [lastOperation.start, lastOperation.end, operation.start, operation.end].reduce((p, v) => (p < v ? p : v))\n      throw new Error(\n        `operation (block index: ${index}, checksum: ${checksum}, kind: ${OperationKind[operation.kind]}) overlaps previous operation (checksum: ${checksum}):\\n` +\n          `abs: ${lastOperation.start} until ${lastOperation.end} and ${operation.start} until ${operation.end}\\n` +\n          `rel: ${lastOperation.start - min} until ${lastOperation.end - min} and ${operation.start - min} until ${operation.end - min}`\n      )\n    }\n  }\n  operations.push(operation)\n}\n\nfunction buildChecksumMap(file: BlockMapFile, fileOffset: number, logger: Logger) {\n  const checksumToOffset = new Map<string, number>()\n  const checksumToSize = new Map<string, number>()\n  let offset = fileOffset\n  for (let i = 0; i < file.checksums.length; i++) {\n    const checksum = file.checksums[i]\n    const size = file.sizes[i]\n\n    const existing = checksumToSize.get(checksum)\n    if (existing === undefined) {\n      checksumToOffset.set(checksum, offset)\n      checksumToSize.set(checksum, size)\n    } else if (logger.debug != null) {\n      const sizeExplanation = existing === size ? \"(same size)\" : `(size: ${existing}, this size: ${size})`\n      logger.debug(`${checksum} duplicated in blockmap ${sizeExplanation}, it doesn't lead to broken differential downloader, just corresponding block will be skipped)`)\n    }\n    offset += size\n  }\n  return { checksumToOffset, checksumToOldSize: checksumToSize }\n}\n\nfunction buildBlockFileMap(list: Array<BlockMapFile>): Map<string, BlockMapFile> {\n  const result = new Map<string, BlockMapFile>()\n  for (const item of list) {\n    result.set(item.name, item)\n  }\n  return result\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeTasksUsingMultipleRangeRequests = executeTasksUsingMultipleRangeRequests;
exports.checkIsRangesSupported = checkIsRangesSupported;
const builder_util_runtime_1 = require("builder-util-runtime");
const DataSplitter_1 = require("./DataSplitter");
const downloadPlanBuilder_1 = require("./downloadPlanBuilder");
function executeTasksUsingMultipleRangeRequests(differentialDownloader, tasks, out, oldFileFd, reject) {
    const w = (taskOffset) => {
        if (taskOffset >= tasks.length) {
            if (differentialDownloader.fileMetadataBuffer != null) {
                out.write(differentialDownloader.fileMetadataBuffer);
            }
            out.end();
            return;
        }
        const nextOffset = taskOffset + 1000;
        doExecuteTasks(differentialDownloader, {
            tasks,
            start: taskOffset,
            end: Math.min(tasks.length, nextOffset),
            oldFileFd,
        }, out, () => w(nextOffset), reject);
    };
    return w;
}
function doExecuteTasks(differentialDownloader, options, out, resolve, reject) {
    let ranges = "bytes=";
    let partCount = 0;
    let grandTotalBytes = 0;
    const partIndexToTaskIndex = new Map();
    const partIndexToLength = [];
    for (let i = options.start; i < options.end; i++) {
        const task = options.tasks[i];
        if (task.kind === downloadPlanBuilder_1.OperationKind.DOWNLOAD) {
            ranges += `${task.start}-${task.end - 1}, `;
            partIndexToTaskIndex.set(partCount, i);
            partCount++;
            partIndexToLength.push(task.end - task.start);
            grandTotalBytes += task.end - task.start;
        }
    }
    if (partCount <= 1) {
        // the only remote range - copy
        const w = (index) => {
            if (index >= options.end) {
                resolve();
                return;
            }
            const task = options.tasks[index++];
            if (task.kind === downloadPlanBuilder_1.OperationKind.COPY) {
                (0, DataSplitter_1.copyData)(task, out, options.oldFileFd, reject, () => w(index));
            }
            else {
                const requestOptions = differentialDownloader.createRequestOptions();
                requestOptions.headers.Range = `bytes=${task.start}-${task.end - 1}`;
                const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {
                    response.on("error", reject);
                    if (!checkIsRangesSupported(response, reject)) {
                        return;
                    }
                    response.pipe(out, {
                        end: false,
                    });
                    response.once("end", () => w(index));
                });
                differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject);
                request.end();
            }
        };
        w(options.start);
        return;
    }
    const requestOptions = differentialDownloader.createRequestOptions();
    requestOptions.headers.Range = ranges.substring(0, ranges.length - 2);
    const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {
        if (!checkIsRangesSupported(response, reject)) {
            return;
        }
        const contentType = (0, builder_util_runtime_1.safeGetHeader)(response, "content-type");
        const m = /^multipart\/.+?\s*;\s*boundary=(?:"([^"]+)"|([^\s";]+))\s*$/i.exec(contentType);
        if (m == null) {
            reject(new Error(`Content-Type "multipart/byteranges" is expected, but got "${contentType}"`));
            return;
        }
        const dicer = new DataSplitter_1.DataSplitter(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve, grandTotalBytes, differentialDownloader.options.onProgress);
        dicer.on("error", reject);
        response.pipe(dicer);
        response.on("end", () => {
            setTimeout(() => {
                request.abort();
                reject(new Error("Response ends without calling any handlers"));
            }, 10000);
        });
    });
    differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject);
    request.end();
}
function checkIsRangesSupported(response, reject) {
    // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.
    if (response.statusCode >= 400) {
        reject((0, builder_util_runtime_1.createHttpError)(response));
        return false;
    }
    if (response.statusCode !== 206) {
        const acceptRanges = (0, builder_util_runtime_1.safeGetHeader)(response, "accept-ranges");
        if (acceptRanges == null || acceptRanges === "none") {
            reject(new Error(`Server doesn't support Accept-Ranges (response code ${response.statusCode})`));
            return false;
        }
    }
    return true;
}
//# sourceMappingURL=multipleRangeDownloader.js.map{"version":3,"file":"multipleRangeDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/multipleRangeDownloader.ts"],"names":[],"mappings":";;AAOA,wFA+BC;AAoFD,wDAeC;AAzID,+DAAqE;AAGrE,iDAAyE;AAEzE,+DAAgE;AAEhE,SAAgB,sCAAsC,CACpD,sBAA8C,EAC9C,KAAuB,EACvB,GAAa,EACb,SAAiB,EACjB,MAA8B;IAE9B,MAAM,CAAC,GAAG,CAAC,UAAkB,EAAQ,EAAE;QACrC,IAAI,UAAU,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC/B,IAAI,sBAAsB,CAAC,kBAAkB,IAAI,IAAI,EAAE,CAAC;gBACtD,GAAG,CAAC,KAAK,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,CAAA;YACtD,CAAC;YACD,GAAG,CAAC,GAAG,EAAE,CAAA;YACT,OAAM;QACR,CAAC;QAED,MAAM,UAAU,GAAG,UAAU,GAAG,IAAI,CAAA;QACpC,cAAc,CACZ,sBAAsB,EACtB;YACE,KAAK;YACL,KAAK,EAAE,UAAU;YACjB,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC;YACvC,SAAS;SACV,EACD,GAAG,EACH,GAAG,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,EACnB,MAAM,CACP,CAAA;IACH,CAAC,CAAA;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED,SAAS,cAAc,CAAC,sBAA8C,EAAE,OAAyB,EAAE,GAAa,EAAE,OAAmB,EAAE,MAA8B;IACnK,IAAI,MAAM,GAAG,QAAQ,CAAA;IACrB,IAAI,SAAS,GAAG,CAAC,CAAA;IACjB,IAAI,eAAe,GAAG,CAAC,CAAA;IACvB,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAkB,CAAA;IACtD,MAAM,iBAAiB,GAAkB,EAAE,CAAA;IAC3C,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,mCAAa,CAAC,QAAQ,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAA;YAC3C,oBAAoB,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;YACtC,SAAS,EAAE,CAAA;YACX,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;YAC7C,eAAe,IAAI,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAA;QAC1C,CAAC;IACH,CAAC;IAED,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACnB,+BAA+B;QAC/B,MAAM,CAAC,GAAG,CAAC,KAAa,EAAQ,EAAE;YAChC,IAAI,KAAK,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;gBACzB,OAAO,EAAE,CAAA;gBACT,OAAM;YACR,CAAC;YAED,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;YAEnC,IAAI,IAAI,CAAC,IAAI,KAAK,mCAAa,CAAC,IAAI,EAAE,CAAC;gBACrC,IAAA,uBAAQ,EAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;YAChE,CAAC;iBAAM,CAAC;gBACN,MAAM,cAAc,GAAG,sBAAsB,CAAC,oBAAoB,EAAE,CAAA;gBACpE,cAAc,CAAC,OAAQ,CAAC,KAAK,GAAG,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,CAAA;gBACrE,MAAM,OAAO,GAAG,sBAAsB,CAAC,YAAY,CAAC,aAAa,CAAC,cAAc,EAAE,QAAQ,CAAC,EAAE;oBAC3F,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;oBAE5B,IAAI,CAAC,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;wBAC9C,OAAM;oBACR,CAAC;oBAED,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE;wBACjB,GAAG,EAAE,KAAK;qBACX,CAAC,CAAA;oBACF,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;gBACtC,CAAC,CAAC,CAAA;gBACF,sBAAsB,CAAC,YAAY,CAAC,0BAA0B,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;gBAC/E,OAAO,CAAC,GAAG,EAAE,CAAA;YACf,CAAC;QACH,CAAC,CAAA;QAED,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAChB,OAAM;IACR,CAAC;IAED,MAAM,cAAc,GAAG,sBAAsB,CAAC,oBAAoB,EAAE,CAAA;IACpE,cAAc,CAAC,OAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACtE,MAAM,OAAO,GAAG,sBAAsB,CAAC,YAAY,CAAC,aAAa,CAAC,cAAc,EAAE,QAAQ,CAAC,EAAE;QAC3F,IAAI,CAAC,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;YAC9C,OAAM;QACR,CAAC;QAED,MAAM,WAAW,GAAG,IAAA,oCAAa,EAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;QAC3D,MAAM,CAAC,GAAG,8DAA8D,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAC1F,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,KAAK,CAAC,6DAA6D,WAAW,GAAG,CAAC,CAAC,CAAA;YAC9F,OAAM;QACR,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,2BAAY,CAAC,GAAG,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,EAAE,eAAe,EAAE,sBAAsB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QACxK,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACzB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAEpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACtB,UAAU,CAAC,GAAG,EAAE;gBACd,OAAO,CAAC,KAAK,EAAE,CAAA;gBACf,MAAM,CAAC,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC,CAAA;YACjE,CAAC,EAAE,KAAK,CAAC,CAAA;QACX,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IACF,sBAAsB,CAAC,YAAY,CAAC,0BAA0B,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC/E,OAAO,CAAC,GAAG,EAAE,CAAA;AACf,CAAC;AAED,SAAgB,sBAAsB,CAAC,QAAyB,EAAE,MAA8B;IAC9F,6HAA6H;IAC7H,IAAI,QAAQ,CAAC,UAAW,IAAI,GAAG,EAAE,CAAC;QAChC,MAAM,CAAC,IAAA,sCAAe,EAAC,QAAQ,CAAC,CAAC,CAAA;QACjC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,IAAA,oCAAa,EAAC,QAAQ,EAAE,eAAe,CAAC,CAAA;QAC7D,IAAI,YAAY,IAAI,IAAI,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YACpD,MAAM,CAAC,IAAI,KAAK,CAAC,uDAAuD,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;YAChG,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import { createHttpError, safeGetHeader } from \"builder-util-runtime\"\nimport { IncomingMessage } from \"http\"\nimport { Writable } from \"stream\"\nimport { copyData, DataSplitter, PartListDataTask } from \"./DataSplitter\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\nimport { Operation, OperationKind } from \"./downloadPlanBuilder\"\n\nexport function executeTasksUsingMultipleRangeRequests(\n  differentialDownloader: DifferentialDownloader,\n  tasks: Array<Operation>,\n  out: Writable,\n  oldFileFd: number,\n  reject: (error: Error) => void\n): (taskOffset: number) => void {\n  const w = (taskOffset: number): void => {\n    if (taskOffset >= tasks.length) {\n      if (differentialDownloader.fileMetadataBuffer != null) {\n        out.write(differentialDownloader.fileMetadataBuffer)\n      }\n      out.end()\n      return\n    }\n\n    const nextOffset = taskOffset + 1000\n    doExecuteTasks(\n      differentialDownloader,\n      {\n        tasks,\n        start: taskOffset,\n        end: Math.min(tasks.length, nextOffset),\n        oldFileFd,\n      },\n      out,\n      () => w(nextOffset),\n      reject\n    )\n  }\n  return w\n}\n\nfunction doExecuteTasks(differentialDownloader: DifferentialDownloader, options: PartListDataTask, out: Writable, resolve: () => void, reject: (error: Error) => void): void {\n  let ranges = \"bytes=\"\n  let partCount = 0\n  let grandTotalBytes = 0\n  const partIndexToTaskIndex = new Map<number, number>()\n  const partIndexToLength: Array<number> = []\n  for (let i = options.start; i < options.end; i++) {\n    const task = options.tasks[i]\n    if (task.kind === OperationKind.DOWNLOAD) {\n      ranges += `${task.start}-${task.end - 1}, `\n      partIndexToTaskIndex.set(partCount, i)\n      partCount++\n      partIndexToLength.push(task.end - task.start)\n      grandTotalBytes += task.end - task.start\n    }\n  }\n\n  if (partCount <= 1) {\n    // the only remote range - copy\n    const w = (index: number): void => {\n      if (index >= options.end) {\n        resolve()\n        return\n      }\n\n      const task = options.tasks[index++]\n\n      if (task.kind === OperationKind.COPY) {\n        copyData(task, out, options.oldFileFd, reject, () => w(index))\n      } else {\n        const requestOptions = differentialDownloader.createRequestOptions()\n        requestOptions.headers!.Range = `bytes=${task.start}-${task.end - 1}`\n        const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {\n          response.on(\"error\", reject)\n\n          if (!checkIsRangesSupported(response, reject)) {\n            return\n          }\n\n          response.pipe(out, {\n            end: false,\n          })\n          response.once(\"end\", () => w(index))\n        })\n        differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n        request.end()\n      }\n    }\n\n    w(options.start)\n    return\n  }\n\n  const requestOptions = differentialDownloader.createRequestOptions()\n  requestOptions.headers!.Range = ranges.substring(0, ranges.length - 2)\n  const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {\n    if (!checkIsRangesSupported(response, reject)) {\n      return\n    }\n\n    const contentType = safeGetHeader(response, \"content-type\")\n    const m = /^multipart\\/.+?\\s*;\\s*boundary=(?:\"([^\"]+)\"|([^\\s\";]+))\\s*$/i.exec(contentType)\n    if (m == null) {\n      reject(new Error(`Content-Type \"multipart/byteranges\" is expected, but got \"${contentType}\"`))\n      return\n    }\n\n    const dicer = new DataSplitter(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve, grandTotalBytes, differentialDownloader.options.onProgress)\n    dicer.on(\"error\", reject)\n    response.pipe(dicer)\n\n    response.on(\"end\", () => {\n      setTimeout(() => {\n        request.abort()\n        reject(new Error(\"Response ends without calling any handlers\"))\n      }, 10000)\n    })\n  })\n  differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n  request.end()\n}\n\nexport function checkIsRangesSupported(response: IncomingMessage, reject: (error: Error) => void): boolean {\n  // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n  if (response.statusCode! >= 400) {\n    reject(createHttpError(response))\n    return false\n  }\n\n  if (response.statusCode !== 206) {\n    const acceptRanges = safeGetHeader(response, \"accept-ranges\")\n    if (acceptRanges == null || acceptRanges === \"none\") {\n      reject(new Error(`Server doesn't support Accept-Ranges (response code ${response.statusCode})`))\n      return false\n    }\n  }\n  return true\n}\n"]}The ISC License

Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
'use strict'

module.exports = clone

var getPrototypeOf = Object.getPrototypeOf || function (obj) {
  return obj.__proto__
}

function clone (obj) {
  if (obj === null || typeof obj !== 'object')
    return obj

  if (obj instanceof Object)
    var copy = { __proto__: getPrototypeOf(obj) }
  else
    var copy = Object.create(null)

  Object.getOwnPropertyNames(obj).forEach(function (key) {
    Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key))
  })

  return copy
}
var fs = require('fs')
var polyfills = require('./polyfills.js')
var legacy = require('./legacy-streams.js')
var clone = require('./clone.js')

var util = require('util')

/* istanbul ignore next - node 0.x polyfill */
var gracefulQueue
var previousSymbol

/* istanbul ignore else - node 0.x polyfill */
if (typeof Symbol === 'function' && typeof Symbol.for === 'function') {
  gracefulQueue = Symbol.for('graceful-fs.queue')
  // This is used in testing by future versions
  previousSymbol = Symbol.for('graceful-fs.previous')
} else {
  gracefulQueue = '___graceful-fs.queue'
  previousSymbol = '___graceful-fs.previous'
}

function noop () {}

function publishQueue(context, queue) {
  Object.defineProperty(context, gracefulQueue, {
    get: function() {
      return queue
    }
  })
}

var debug = noop
if (util.debuglog)
  debug = util.debuglog('gfs4')
else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ''))
  debug = function() {
    var m = util.format.apply(util, arguments)
    m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ')
    console.error(m)
  }

// Once time initialization
if (!fs[gracefulQueue]) {
  // This queue can be shared by multiple loaded instances
  var queue = global[gracefulQueue] || []
  publishQueue(fs, queue)

  // Patch fs.close/closeSync to shared queue version, because we need
  // to retry() whenever a close happens *anywhere* in the program.
  // This is essential when multiple graceful-fs instances are
  // in play at the same time.
  fs.close = (function (fs$close) {
    function close (fd, cb) {
      return fs$close.call(fs, fd, function (err) {
        // This function uses the graceful-fs shared queue
        if (!err) {
          resetQueue()
        }

        if (typeof cb === 'function')
          cb.apply(this, arguments)
      })
    }

    Object.defineProperty(close, previousSymbol, {
      value: fs$close
    })
    return close
  })(fs.close)

  fs.closeSync = (function (fs$closeSync) {
    function closeSync (fd) {
      // This function uses the graceful-fs shared queue
      fs$closeSync.apply(fs, arguments)
      resetQueue()
    }

    Object.defineProperty(closeSync, previousSymbol, {
      value: fs$closeSync
    })
    return closeSync
  })(fs.closeSync)

  if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
    process.on('exit', function() {
      debug(fs[gracefulQueue])
      require('assert').equal(fs[gracefulQueue].length, 0)
    })
  }
}

if (!global[gracefulQueue]) {
  publishQueue(global, fs[gracefulQueue]);
}

module.exports = patch(clone(fs))
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) {
    module.exports = patch(fs)
    fs.__patched = true;
}

function patch (fs) {
  // Everything that references the open() function needs to be in here
  polyfills(fs)
  fs.gracefulify = patch

  fs.createReadStream = createReadStream
  fs.createWriteStream = createWriteStream
  var fs$readFile = fs.readFile
  fs.readFile = readFile
  function readFile (path, options, cb) {
    if (typeof options === 'function')
      cb = options, options = null

    return go$readFile(path, options, cb)

    function go$readFile (path, options, cb, startTime) {
      return fs$readFile(path, options, function (err) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([go$readFile, [path, options, cb], err, startTime || Date.now(), Date.now()])
        else {
          if (typeof cb === 'function')
            cb.apply(this, arguments)
        }
      })
    }
  }

  var fs$writeFile = fs.writeFile
  fs.writeFile = writeFile
  function writeFile (path, data, options, cb) {
    if (typeof options === 'function')
      cb = options, options = null

    return go$writeFile(path, data, options, cb)

    function go$writeFile (path, data, options, cb, startTime) {
      return fs$writeFile(path, data, options, function (err) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([go$writeFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()])
        else {
          if (typeof cb === 'function')
            cb.apply(this, arguments)
        }
      })
    }
  }

  var fs$appendFile = fs.appendFile
  if (fs$appendFile)
    fs.appendFile = appendFile
  function appendFile (path, data, options, cb) {
    if (typeof options === 'function')
      cb = options, options = null

    return go$appendFile(path, data, options, cb)

    function go$appendFile (path, data, options, cb, startTime) {
      return fs$appendFile(path, data, options, function (err) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([go$appendFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()])
        else {
          if (typeof cb === 'function')
            cb.apply(this, arguments)
        }
      })
    }
  }

  var fs$copyFile = fs.copyFile
  if (fs$copyFile)
    fs.copyFile = copyFile
  function copyFile (src, dest, flags, cb) {
    if (typeof flags === 'function') {
      cb = flags
      flags = 0
    }
    return go$copyFile(src, dest, flags, cb)

    function go$copyFile (src, dest, flags, cb, startTime) {
      return fs$copyFile(src, dest, flags, function (err) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([go$copyFile, [src, dest, flags, cb], err, startTime || Date.now(), Date.now()])
        else {
          if (typeof cb === 'function')
            cb.apply(this, arguments)
        }
      })
    }
  }

  var fs$readdir = fs.readdir
  fs.readdir = readdir
  var noReaddirOptionVersions = /^v[0-5]\./
  function readdir (path, options, cb) {
    if (typeof options === 'function')
      cb = options, options = null

    var go$readdir = noReaddirOptionVersions.test(process.version)
      ? function go$readdir (path, options, cb, startTime) {
        return fs$readdir(path, fs$readdirCallback(
          path, options, cb, startTime
        ))
      }
      : function go$readdir (path, options, cb, startTime) {
        return fs$readdir(path, options, fs$readdirCallback(
          path, options, cb, startTime
        ))
      }

    return go$readdir(path, options, cb)

    function fs$readdirCallback (path, options, cb, startTime) {
      return function (err, files) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([
            go$readdir,
            [path, options, cb],
            err,
            startTime || Date.now(),
            Date.now()
          ])
        else {
          if (files && files.sort)
            files.sort()

          if (typeof cb === 'function')
            cb.call(this, err, files)
        }
      }
    }
  }

  if (process.version.substr(0, 4) === 'v0.8') {
    var legStreams = legacy(fs)
    ReadStream = legStreams.ReadStream
    WriteStream = legStreams.WriteStream
  }

  var fs$ReadStream = fs.ReadStream
  if (fs$ReadStream) {
    ReadStream.prototype = Object.create(fs$ReadStream.prototype)
    ReadStream.prototype.open = ReadStream$open
  }

  var fs$WriteStream = fs.WriteStream
  if (fs$WriteStream) {
    WriteStream.prototype = Object.create(fs$WriteStream.prototype)
    WriteStream.prototype.open = WriteStream$open
  }

  Object.defineProperty(fs, 'ReadStream', {
    get: function () {
      return ReadStream
    },
    set: function (val) {
      ReadStream = val
    },
    enumerable: true,
    configurable: true
  })
  Object.defineProperty(fs, 'WriteStream', {
    get: function () {
      return WriteStream
    },
    set: function (val) {
      WriteStream = val
    },
    enumerable: true,
    configurable: true
  })

  // legacy names
  var FileReadStream = ReadStream
  Object.defineProperty(fs, 'FileReadStream', {
    get: function () {
      return FileReadStream
    },
    set: function (val) {
      FileReadStream = val
    },
    enumerable: true,
    configurable: true
  })
  var FileWriteStream = WriteStream
  Object.defineProperty(fs, 'FileWriteStream', {
    get: function () {
      return FileWriteStream
    },
    set: function (val) {
      FileWriteStream = val
    },
    enumerable: true,
    configurable: true
  })

  function ReadStream (path, options) {
    if (this instanceof ReadStream)
      return fs$ReadStream.apply(this, arguments), this
    else
      return ReadStream.apply(Object.create(ReadStream.prototype), arguments)
  }

  function ReadStream$open () {
    var that = this
    open(that.path, that.flags, that.mode, function (err, fd) {
      if (err) {
        if (that.autoClose)
          that.destroy()

        that.emit('error', err)
      } else {
        that.fd = fd
        that.emit('open', fd)
        that.read()
      }
    })
  }

  function WriteStream (path, options) {
    if (this instanceof WriteStream)
      return fs$WriteStream.apply(this, arguments), this
    else
      return WriteStream.apply(Object.create(WriteStream.prototype), arguments)
  }

  function WriteStream$open () {
    var that = this
    open(that.path, that.flags, that.mode, function (err, fd) {
      if (err) {
        that.destroy()
        that.emit('error', err)
      } else {
        that.fd = fd
        that.emit('open', fd)
      }
    })
  }

  function createReadStream (path, options) {
    return new fs.ReadStream(path, options)
  }

  function createWriteStream (path, options) {
    return new fs.WriteStream(path, options)
  }

  var fs$open = fs.open
  fs.open = open
  function open (path, flags, mode, cb) {
    if (typeof mode === 'function')
      cb = mode, mode = null

    return go$open(path, flags, mode, cb)

    function go$open (path, flags, mode, cb, startTime) {
      return fs$open(path, flags, mode, function (err, fd) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([go$open, [path, flags, mode, cb], err, startTime || Date.now(), Date.now()])
        else {
          if (typeof cb === 'function')
            cb.apply(this, arguments)
        }
      })
    }
  }

  return fs
}

function enqueue (elem) {
  debug('ENQUEUE', elem[0].name, elem[1])
  fs[gracefulQueue].push(elem)
  retry()
}

// keep track of the timeout between retry() calls
var retryTimer

// reset the startTime and lastTime to now
// this resets the start of the 60 second overall timeout as well as the
// delay between attempts so that we'll retry these jobs sooner
function resetQueue () {
  var now = Date.now()
  for (var i = 0; i < fs[gracefulQueue].length; ++i) {
    // entries that are only a length of 2 are from an older version, don't
    // bother modifying those since they'll be retried anyway.
    if (fs[gracefulQueue][i].length > 2) {
      fs[gracefulQueue][i][3] = now // startTime
      fs[gracefulQueue][i][4] = now // lastTime
    }
  }
  // call retry to make sure we're actively processing the queue
  retry()
}

function retry () {
  // clear the timer and remove it to help prevent unintended concurrency
  clearTimeout(retryTimer)
  retryTimer = undefined

  if (fs[gracefulQueue].length === 0)
    return

  var elem = fs[gracefulQueue].shift()
  var fn = elem[0]
  var args = elem[1]
  // these items may be unset if they were added by an older graceful-fs
  var err = elem[2]
  var startTime = elem[3]
  var lastTime = elem[4]

  // if we don't have a startTime we have no way of knowing if we've waited
  // long enough, so go ahead and retry this item now
  if (startTime === undefined) {
    debug('RETRY', fn.name, args)
    fn.apply(null, args)
  } else if (Date.now() - startTime >= 60000) {
    // it's been more than 60 seconds total, bail now
    debug('TIMEOUT', fn.name, args)
    var cb = args.pop()
    if (typeof cb === 'function')
      cb.call(null, err)
  } else {
    // the amount of time between the last attempt and right now
    var sinceAttempt = Date.now() - lastTime
    // the amount of time between when we first tried, and when we last tried
    // rounded up to at least 1
    var sinceStart = Math.max(lastTime - startTime, 1)
    // backoff. wait longer than the total time we've been retrying, but only
    // up to a maximum of 100ms
    var desiredDelay = Math.min(sinceStart * 1.2, 100)
    // it's been long enough since the last retry, do it again
    if (sinceAttempt >= desiredDelay) {
      debug('RETRY', fn.name, args)
      fn.apply(null, args.concat([startTime]))
    } else {
      // if we can't do this job yet, push it to the end of the queue
      // and let the next iteration check again
      fs[gracefulQueue].push(elem)
    }
  }

  // schedule our next run if one isn't already scheduled
  if (retryTimer === undefined) {
    retryTimer = setTimeout(retry, 0)
  }
}
var Stream = require('stream').Stream

module.exports = legacy

function legacy (fs) {
  return {
    ReadStream: ReadStream,
    WriteStream: WriteStream
  }

  function ReadStream (path, options) {
    if (!(this instanceof ReadStream)) return new ReadStream(path, options);

    Stream.call(this);

    var self = this;

    this.path = path;
    this.fd = null;
    this.readable = true;
    this.paused = false;

    this.flags = 'r';
    this.mode = 438; /*=0666*/
    this.bufferSize = 64 * 1024;

    options = options || {};

    // Mixin options into this
    var keys = Object.keys(options);
    for (var index = 0, length = keys.length; index < length; index++) {
      var key = keys[index];
      this[key] = options[key];
    }

    if (this.encoding) this.setEncoding(this.encoding);

    if (this.start !== undefined) {
      if ('number' !== typeof this.start) {
        throw TypeError('start must be a Number');
      }
      if (this.end === undefined) {
        this.end = Infinity;
      } else if ('number' !== typeof this.end) {
        throw TypeError('end must be a Number');
      }

      if (this.start > this.end) {
        throw new Error('start must be <= end');
      }

      this.pos = this.start;
    }

    if (this.fd !== null) {
      process.nextTick(function() {
        self._read();
      });
      return;
    }

    fs.open(this.path, this.flags, this.mode, function (err, fd) {
      if (err) {
        self.emit('error', err);
        self.readable = false;
        return;
      }

      self.fd = fd;
      self.emit('open', fd);
      self._read();
    })
  }

  function WriteStream (path, options) {
    if (!(this instanceof WriteStream)) return new WriteStream(path, options);

    Stream.call(this);

    this.path = path;
    this.fd = null;
    this.writable = true;

    this.flags = 'w';
    this.encoding = 'binary';
    this.mode = 438; /*=0666*/
    this.bytesWritten = 0;

    options = options || {};

    // Mixin options into this
    var keys = Object.keys(options);
    for (var index = 0, length = keys.length; index < length; index++) {
      var key = keys[index];
      this[key] = options[key];
    }

    if (this.start !== undefined) {
      if ('number' !== typeof this.start) {
        throw TypeError('start must be a Number');
      }
      if (this.start < 0) {
        throw new Error('start must be >= zero');
      }

      this.pos = this.start;
    }

    this.busy = false;
    this._queue = [];

    if (this.fd === null) {
      this._open = fs.open;
      this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
      this.flush();
    }
  }
}
{
  "name": "graceful-fs",
  "description": "A drop-in replacement for fs, making various improvements.",
  "version": "4.2.11",
  "repository": {
    "type": "git",
    "url": "https://github.com/isaacs/node-graceful-fs"
  },
  "main": "graceful-fs.js",
  "directories": {
    "test": "test"
  },
  "license": "ISC",
  "devDependencies": {
    "import-fresh": "^2.0.0",
    "mkdirp": "^0.5.0",
    "rimraf": "^2.2.8",
    "tap": "^16.3.4"
  },
  "files": [
    "fs.js",
    "graceful-fs.js",
    "legacy-streams.js",
    "polyfills.js",
    "clone.js"
  ],
  "tap": {
    "reporter": "classic"
  }
}var constants = require('constants')

var origCwd = process.cwd
var cwd = null

var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform

process.cwd = function() {
  if (!cwd)
    cwd = origCwd.call(process)
  return cwd
}
try {
  process.cwd()
} catch (er) {}

// This check is needed until node.js 12 is required
if (typeof process.chdir === 'function') {
  var chdir = process.chdir
  process.chdir = function (d) {
    cwd = null
    chdir.call(process, d)
  }
  if (Object.setPrototypeOf) Object.setPrototypeOf(process.chdir, chdir)
}

module.exports = patch

function patch (fs) {
  // (re-)implement some things that are known busted or missing.

  // lchmod, broken prior to 0.6.2
  // back-port the fix here.
  if (constants.hasOwnProperty('O_SYMLINK') &&
      process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
    patchLchmod(fs)
  }

  // lutimes implementation, or no-op
  if (!fs.lutimes) {
    patchLutimes(fs)
  }

  // https://github.com/isaacs/node-graceful-fs/issues/4
  // Chown should not fail on einval or eperm if non-root.
  // It should not fail on enosys ever, as this just indicates
  // that a fs doesn't support the intended operation.

  fs.chown = chownFix(fs.chown)
  fs.fchown = chownFix(fs.fchown)
  fs.lchown = chownFix(fs.lchown)

  fs.chmod = chmodFix(fs.chmod)
  fs.fchmod = chmodFix(fs.fchmod)
  fs.lchmod = chmodFix(fs.lchmod)

  fs.chownSync = chownFixSync(fs.chownSync)
  fs.fchownSync = chownFixSync(fs.fchownSync)
  fs.lchownSync = chownFixSync(fs.lchownSync)

  fs.chmodSync = chmodFixSync(fs.chmodSync)
  fs.fchmodSync = chmodFixSync(fs.fchmodSync)
  fs.lchmodSync = chmodFixSync(fs.lchmodSync)

  fs.stat = statFix(fs.stat)
  fs.fstat = statFix(fs.fstat)
  fs.lstat = statFix(fs.lstat)

  fs.statSync = statFixSync(fs.statSync)
  fs.fstatSync = statFixSync(fs.fstatSync)
  fs.lstatSync = statFixSync(fs.lstatSync)

  // if lchmod/lchown do not exist, then make them no-ops
  if (fs.chmod && !fs.lchmod) {
    fs.lchmod = function (path, mode, cb) {
      if (cb) process.nextTick(cb)
    }
    fs.lchmodSync = function () {}
  }
  if (fs.chown && !fs.lchown) {
    fs.lchown = function (path, uid, gid, cb) {
      if (cb) process.nextTick(cb)
    }
    fs.lchownSync = function () {}
  }

  // on Windows, A/V software can lock the directory, causing this
  // to fail with an EACCES or EPERM if the directory contains newly
  // created files.  Try again on failure, for up to 60 seconds.

  // Set the timeout this long because some Windows Anti-Virus, such as Parity
  // bit9, may lock files for up to a minute, causing npm package install
  // failures. Also, take care to yield the scheduler. Windows scheduling gives
  // CPU to a busy looping process, which can cause the program causing the lock
  // contention to be starved of CPU by node, so the contention doesn't resolve.
  if (platform === "win32") {
    fs.rename = typeof fs.rename !== 'function' ? fs.rename
    : (function (fs$rename) {
      function rename (from, to, cb) {
        var start = Date.now()
        var backoff = 0;
        fs$rename(from, to, function CB (er) {
          if (er
              && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY")
              && Date.now() - start < 60000) {
            setTimeout(function() {
              fs.stat(to, function (stater, st) {
                if (stater && stater.code === "ENOENT")
                  fs$rename(from, to, CB);
                else
                  cb(er)
              })
            }, backoff)
            if (backoff < 100)
              backoff += 10;
            return;
          }
          if (cb) cb(er)
        })
      }
      if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename)
      return rename
    })(fs.rename)
  }

  // if read() returns EAGAIN, then just try it again.
  fs.read = typeof fs.read !== 'function' ? fs.read
  : (function (fs$read) {
    function read (fd, buffer, offset, length, position, callback_) {
      var callback
      if (callback_ && typeof callback_ === 'function') {
        var eagCounter = 0
        callback = function (er, _, __) {
          if (er && er.code === 'EAGAIN' && eagCounter < 10) {
            eagCounter ++
            return fs$read.call(fs, fd, buffer, offset, length, position, callback)
          }
          callback_.apply(this, arguments)
        }
      }
      return fs$read.call(fs, fd, buffer, offset, length, position, callback)
    }

    // This ensures `util.promisify` works as it does for native `fs.read`.
    if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read)
    return read
  })(fs.read)

  fs.readSync = typeof fs.readSync !== 'function' ? fs.readSync
  : (function (fs$readSync) { return function (fd, buffer, offset, length, position) {
    var eagCounter = 0
    while (true) {
      try {
        return fs$readSync.call(fs, fd, buffer, offset, length, position)
      } catch (er) {
        if (er.code === 'EAGAIN' && eagCounter < 10) {
          eagCounter ++
          continue
        }
        throw er
      }
    }
  }})(fs.readSync)

  function patchLchmod (fs) {
    fs.lchmod = function (path, mode, callback) {
      fs.open( path
             , constants.O_WRONLY | constants.O_SYMLINK
             , mode
             , function (err, fd) {
        if (err) {
          if (callback) callback(err)
          return
        }
        // prefer to return the chmod error, if one occurs,
        // but still try to close, and report closing errors if they occur.
        fs.fchmod(fd, mode, function (err) {
          fs.close(fd, function(err2) {
            if (callback) callback(err || err2)
          })
        })
      })
    }

    fs.lchmodSync = function (path, mode) {
      var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)

      // prefer to return the chmod error, if one occurs,
      // but still try to close, and report closing errors if they occur.
      var threw = true
      var ret
      try {
        ret = fs.fchmodSync(fd, mode)
        threw = false
      } finally {
        if (threw) {
          try {
            fs.closeSync(fd)
          } catch (er) {}
        } else {
          fs.closeSync(fd)
        }
      }
      return ret
    }
  }

  function patchLutimes (fs) {
    if (constants.hasOwnProperty("O_SYMLINK") && fs.futimes) {
      fs.lutimes = function (path, at, mt, cb) {
        fs.open(path, constants.O_SYMLINK, function (er, fd) {
          if (er) {
            if (cb) cb(er)
            return
          }
          fs.futimes(fd, at, mt, function (er) {
            fs.close(fd, function (er2) {
              if (cb) cb(er || er2)
            })
          })
        })
      }

      fs.lutimesSync = function (path, at, mt) {
        var fd = fs.openSync(path, constants.O_SYMLINK)
        var ret
        var threw = true
        try {
          ret = fs.futimesSync(fd, at, mt)
          threw = false
        } finally {
          if (threw) {
            try {
              fs.closeSync(fd)
            } catch (er) {}
          } else {
            fs.closeSync(fd)
          }
        }
        return ret
      }

    } else if (fs.futimes) {
      fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) }
      fs.lutimesSync = function () {}
    }
  }

  function chmodFix (orig) {
    if (!orig) return orig
    return function (target, mode, cb) {
      return orig.call(fs, target, mode, function (er) {
        if (chownErOk(er)) er = null
        if (cb) cb.apply(this, arguments)
      })
    }
  }

  function chmodFixSync (orig) {
    if (!orig) return orig
    return function (target, mode) {
      try {
        return orig.call(fs, target, mode)
      } catch (er) {
        if (!chownErOk(er)) throw er
      }
    }
  }


  function chownFix (orig) {
    if (!orig) return orig
    return function (target, uid, gid, cb) {
      return orig.call(fs, target, uid, gid, function (er) {
        if (chownErOk(er)) er = null
        if (cb) cb.apply(this, arguments)
      })
    }
  }

  function chownFixSync (orig) {
    if (!orig) return orig
    return function (target, uid, gid) {
      try {
        return orig.call(fs, target, uid, gid)
      } catch (er) {
        if (!chownErOk(er)) throw er
      }
    }
  }

  function statFix (orig) {
    if (!orig) return orig
    // Older versions of Node erroneously returned signed integers for
    // uid + gid.
    return function (target, options, cb) {
      if (typeof options === 'function') {
        cb = options
        options = null
      }
      function callback (er, stats) {
        if (stats) {
          if (stats.uid < 0) stats.uid += 0x100000000
          if (stats.gid < 0) stats.gid += 0x100000000
        }
        if (cb) cb.apply(this, arguments)
      }
      return options ? orig.call(fs, target, options, callback)
        : orig.call(fs, target, callback)
    }
  }

  function statFixSync (orig) {
    if (!orig) return orig
    // Older versions of Node erroneously returned signed integers for
    // uid + gid.
    return function (target, options) {
      var stats = options ? orig.call(fs, target, options)
        : orig.call(fs, target)
      if (stats) {
        if (stats.uid < 0) stats.uid += 0x100000000
        if (stats.gid < 0) stats.gid += 0x100000000
      }
      return stats;
    }
  }

  // ENOSYS means that the fs doesn't support the op. Just ignore
  // that, because it doesn't matter.
  //
  // if there's no getuid, or if getuid() is something other
  // than 0, and the error is EINVAL or EPERM, then just ignore
  // it.
  //
  // This specific case is a silent failure in cp, install, tar,
  // and most other unix tools that manage permissions.
  //
  // When running as root, or if other types of errors are
  // encountered, then it's strict.
  function chownErOk (er) {
    if (!er)
      return true

    if (er.code === "ENOSYS")
      return true

    var nonroot = !process.getuid || process.getuid() !== 0
    if (nonroot) {
      if (er.code === "EINVAL" || er.code === "EPERM")
        return true
    }

    return false
  }
}
(The MIT License)

Copyright (C) 2011-2015 by Vitaly Puzrin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
'use strict'

const loader = require('./lib/loader')
const dumper = require('./lib/dumper')

function renamed (from, to) {
  return function () {
    throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' +
      'Use yaml.' + to + ' instead, which is now safe by default.')
  }
}

module.exports.Type = require('./lib/type')
module.exports.Schema = require('./lib/schema')
module.exports.FAILSAFE_SCHEMA = require('./lib/schema/failsafe')
module.exports.JSON_SCHEMA = require('./lib/schema/json')
module.exports.CORE_SCHEMA = require('./lib/schema/core')
module.exports.DEFAULT_SCHEMA = require('./lib/schema/default')
module.exports.load = loader.load
module.exports.loadAll = loader.loadAll
module.exports.dump = dumper.dump
module.exports.YAMLException = require('./lib/exception')

// Re-export all types in case user wants to create custom schema
module.exports.types = {
  binary: require('./lib/type/binary'),
  float: require('./lib/type/float'),
  map: require('./lib/type/map'),
  null: require('./lib/type/null'),
  pairs: require('./lib/type/pairs'),
  set: require('./lib/type/set'),
  timestamp: require('./lib/type/timestamp'),
  bool: require('./lib/type/bool'),
  int: require('./lib/type/int'),
  merge: require('./lib/type/merge'),
  omap: require('./lib/type/omap'),
  seq: require('./lib/type/seq'),
  str: require('./lib/type/str')
}

// Removed functions from JS-YAML 3.0.x
module.exports.safeLoad = renamed('safeLoad', 'load')
module.exports.safeLoadAll = renamed('safeLoadAll', 'loadAll')
module.exports.safeDump = renamed('safeDump', 'dump')
{
  "name": "js-yaml",
  "version": "4.3.1",
  "description": "YAML 1.2 parser and serializer",
  "author": "Vladimir Zapparov <dervus.grim@gmail.com>",
  "license": "MIT",
  "repository": "nodeca/js-yaml",
  "funding": [
    {
      "type": "github",
      "url": "https://github.com/sponsors/puzrin"
    },
    {
      "type": "github",
      "url": "https://github.com/sponsors/nodeca"
    }
  ],
  "files": [
    "index.js",
    "lib/",
    "bin/",
    "dist/"
  ],
  "publishConfig": {
    "tag": "v4-legacy"
  },
  "bin": {
    "js-yaml": "bin/js-yaml.js"
  },
  "module": "./dist/js-yaml.mjs",
  "exports": {
    ".": {
      "import": "./dist/js-yaml.mjs",
      "require": "./index.js"
    },
    "./package.json": "./package.json"
  },
  "unpkg": "dist/js-yaml.min.js",
  "jsdelivr": "dist/js-yaml.min.js",
  "dependencies": {
    "argparse": "^2.0.1"
  },
  "devDependencies": {
    "@babel/core": "8.0.1",
    "@babel/preset-env": "8.0.1",
    "@rollup/plugin-commonjs": "29.0.3",
    "@rollup/plugin-terser": "0.4.4",
    "c8": "^11.0.0",
    "codemirror": "^5.65.21",
    "eslint": "^9.39.4",
    "fast-check": "^4.8.0",
    "gh-pages": "^6.3.0",
    "neostandard": "^0.13.0",
    "tinybench": "^6.0.2",
    "vite": "7.3.6",
    "vite-plugin-node-polyfills": "^0.28.0",
    "vite-plugin-singlefile": "^2.3.3",
    "workerpool": "^10.0.2"
  }
}'use strict'

function isNothing (subject) {
  return (typeof subject === 'undefined') || (subject === null)
}

function isObject (subject) {
  return (typeof subject === 'object') && (subject !== null)
}

function toArray (sequence) {
  if (Array.isArray(sequence)) return sequence
  else if (isNothing(sequence)) return []

  return [sequence]
}

function extend (target, source) {
  if (source) {
    const sourceKeys = Object.keys(source)

    for (let index = 0, length = sourceKeys.length; index < length; index += 1) {
      const key = sourceKeys[index]
      target[key] = source[key]
    }
  }

  return target
}

function repeat (string, count) {
  let result = ''

  for (let cycle = 0; cycle < count; cycle += 1) {
    result += string
  }

  return result
}

function isNegativeZero (number) {
  return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number)
}

module.exports.isNothing = isNothing
module.exports.isObject = isObject
module.exports.toArray = toArray
module.exports.repeat = repeat
module.exports.isNegativeZero = isNegativeZero
module.exports.extend = extend
'use strict'

const common = require('./common')
const YAMLException = require('./exception')
const DEFAULT_SCHEMA = require('./schema/default')

const _toString = Object.prototype.toString
const _hasOwnProperty = Object.prototype.hasOwnProperty

const CHAR_BOM = 0xFEFF
const CHAR_TAB = 0x09 /* Tab */
const CHAR_LINE_FEED = 0x0A /* LF */
const CHAR_CARRIAGE_RETURN = 0x0D /* CR */
const CHAR_SPACE = 0x20 /* Space */
const CHAR_EXCLAMATION = 0x21 /* ! */
const CHAR_DOUBLE_QUOTE = 0x22 /* " */
const CHAR_SHARP = 0x23 /* # */
const CHAR_PERCENT = 0x25 /* % */
const CHAR_AMPERSAND = 0x26 /* & */
const CHAR_SINGLE_QUOTE = 0x27 /* ' */
const CHAR_ASTERISK = 0x2A /* * */
const CHAR_COMMA = 0x2C /* , */
const CHAR_MINUS = 0x2D /* - */
const CHAR_COLON = 0x3A /* : */
const CHAR_EQUALS = 0x3D /* = */
const CHAR_GREATER_THAN = 0x3E /* > */
const CHAR_QUESTION = 0x3F /* ? */
const CHAR_COMMERCIAL_AT = 0x40 /* @ */
const CHAR_LEFT_SQUARE_BRACKET = 0x5B /* [ */
const CHAR_RIGHT_SQUARE_BRACKET = 0x5D /* ] */
const CHAR_GRAVE_ACCENT = 0x60 /* ` */
const CHAR_LEFT_CURLY_BRACKET = 0x7B /* { */
const CHAR_VERTICAL_LINE = 0x7C /* | */
const CHAR_RIGHT_CURLY_BRACKET = 0x7D /* } */

const ESCAPE_SEQUENCES = {}

ESCAPE_SEQUENCES[0x00] = '\\0'
ESCAPE_SEQUENCES[0x07] = '\\a'
ESCAPE_SEQUENCES[0x08] = '\\b'
ESCAPE_SEQUENCES[0x09] = '\\t'
ESCAPE_SEQUENCES[0x0A] = '\\n'
ESCAPE_SEQUENCES[0x0B] = '\\v'
ESCAPE_SEQUENCES[0x0C] = '\\f'
ESCAPE_SEQUENCES[0x0D] = '\\r'
ESCAPE_SEQUENCES[0x1B] = '\\e'
ESCAPE_SEQUENCES[0x22] = '\\"'
ESCAPE_SEQUENCES[0x5C] = '\\\\'
ESCAPE_SEQUENCES[0x85] = '\\N'
ESCAPE_SEQUENCES[0xA0] = '\\_'
ESCAPE_SEQUENCES[0x2028] = '\\L'
ESCAPE_SEQUENCES[0x2029] = '\\P'

const DEPRECATED_BOOLEANS_SYNTAX = [
  'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',
  'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'
]

const DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/

function compileStyleMap (schema, map) {
  if (map === null) return {}

  const result = {}
  const keys = Object.keys(map)

  for (let index = 0, length = keys.length; index < length; index += 1) {
    let tag = keys[index]
    let style = String(map[tag])

    if (tag.slice(0, 2) === '!!') {
      tag = 'tag:yaml.org,2002:' + tag.slice(2)
    }
    const type = schema.compiledTypeMap['fallback'][tag]

    if (type && _hasOwnProperty.call(type.styleAliases, style)) {
      style = type.styleAliases[style]
    }

    result[tag] = style
  }

  return result
}

function encodeHex (character) {
  let handle
  let length

  const string = character.toString(16).toUpperCase()

  if (character <= 0xFF) {
    handle = 'x'
    length = 2
  } else if (character <= 0xFFFF) {
    handle = 'u'
    length = 4
  } else if (character <= 0xFFFFFFFF) {
    handle = 'U'
    length = 8
  } else {
    throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF')
  }

  return '\\' + handle + common.repeat('0', length - string.length) + string
}

const QUOTING_TYPE_SINGLE = 1
const QUOTING_TYPE_DOUBLE = 2

function State (options) {
  this.schema = options['schema'] || DEFAULT_SCHEMA
  this.indent = Math.max(1, (options['indent'] || 2))
  this.noArrayIndent = options['noArrayIndent'] || false
  this.skipInvalid = options['skipInvalid'] || false
  this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel'])
  this.styleMap = compileStyleMap(this.schema, options['styles'] || null)
  this.sortKeys = options['sortKeys'] || false
  this.lineWidth = options['lineWidth'] || 80
  this.noRefs = options['noRefs'] || false
  this.noCompatMode = options['noCompatMode'] || false
  this.condenseFlow = options['condenseFlow'] || false
  this.quotingType = options['quotingType'] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE
  this.forceQuotes = options['forceQuotes'] || false
  this.replacer = typeof options['replacer'] === 'function' ? options['replacer'] : null

  this.implicitTypes = this.schema.compiledImplicit
  this.explicitTypes = this.schema.compiledExplicit

  this.tag = null
  this.result = ''

  this.duplicates = []
  this.usedDuplicates = null
}

// Indents every line in a string. Empty lines (\n only) are not indented.
function indentString (string, spaces) {
  const ind = common.repeat(' ', spaces)
  let position = 0
  let result = ''
  const length = string.length

  while (position < length) {
    let line
    const next = string.indexOf('\n', position)
    if (next === -1) {
      line = string.slice(position)
      position = length
    } else {
      line = string.slice(position, next + 1)
      position = next + 1
    }

    if (line.length && line !== '\n') result += ind

    result += line
  }

  return result
}

function generateNextLine (state, level) {
  return '\n' + common.repeat(' ', state.indent * level)
}

function testImplicitResolving (state, str) {
  for (let index = 0, length = state.implicitTypes.length; index < length; index += 1) {
    const type = state.implicitTypes[index]

    if (type.resolve(str)) {
      return true
    }
  }

  return false
}

// [33] s-white ::= s-space | s-tab
function isWhitespace (c) {
  return c === CHAR_SPACE || c === CHAR_TAB
}

// Returns true if the character can be printed without escaping.
// From YAML 1.2: "any allowed characters known to be non-printable
// should also be escaped. [However,] This isn’t mandatory"
// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029.
function isPrintable (c) {
  return (c >= 0x00020 && c <= 0x00007E) ||
    ((c >= 0x000A1 && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029) ||
    ((c >= 0x0E000 && c <= 0x00FFFD) && c !== CHAR_BOM) ||
    (c >= 0x10000 && c <= 0x10FFFF)
}

// [34] ns-char ::= nb-char - s-white
// [27] nb-char ::= c-printable - b-char - c-byte-order-mark
// [26] b-char  ::= b-line-feed | b-carriage-return
// Including s-white (for some reason, examples doesn't match specs in this aspect)
// ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark
function isNsCharOrWhitespace (c) {
  return isPrintable(c) &&
    c !== CHAR_BOM &&
    // - b-char
    c !== CHAR_CARRIAGE_RETURN &&
    c !== CHAR_LINE_FEED
}

// [127]  ns-plain-safe(c) ::= c = flow-out  ⇒ ns-plain-safe-out
//                             c = flow-in   ⇒ ns-plain-safe-in
//                             c = block-key ⇒ ns-plain-safe-out
//                             c = flow-key  ⇒ ns-plain-safe-in
// [128] ns-plain-safe-out ::= ns-char
// [129]  ns-plain-safe-in ::= ns-char - c-flow-indicator
// [130]  ns-plain-char(c) ::=  ( ns-plain-safe(c) - “:” - “#” )
//                            | ( /* An ns-char preceding */ “#” )
//                            | ( “:” /* Followed by an ns-plain-safe(c) */ )
function isPlainSafe (c, prev, inblock) {
  const cIsNsCharOrWhitespace = isNsCharOrWhitespace(c)
  const cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c)
  return (
    (
      // ns-plain-safe
      inblock // c = flow-in
        ? cIsNsCharOrWhitespace
        : cIsNsCharOrWhitespace &&
          // - c-flow-indicator
          c !== CHAR_COMMA &&
          c !== CHAR_LEFT_SQUARE_BRACKET &&
          c !== CHAR_RIGHT_SQUARE_BRACKET &&
          c !== CHAR_LEFT_CURLY_BRACKET &&
          c !== CHAR_RIGHT_CURLY_BRACKET
    ) &&
    // ns-plain-char
    c !== CHAR_SHARP && // false on '#'
    !(prev === CHAR_COLON && !cIsNsChar)
  ) || // false on ': '
  (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP) || // change to true on '[^ ]#'
  (prev === CHAR_COLON && cIsNsChar) // change to true on ':[^ ]'
}

// Simplified test for values allowed as the first character in plain style.
function isPlainSafeFirst (c) {
  // Uses a subset of ns-char - c-indicator
  // where ns-char = nb-char - s-white.
  // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part
  return isPrintable(c) &&
    c !== CHAR_BOM &&
    !isWhitespace(c) && // - s-white
    // - (c-indicator ::=
    // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
    c !== CHAR_MINUS &&
    c !== CHAR_QUESTION &&
    c !== CHAR_COLON &&
    c !== CHAR_COMMA &&
    c !== CHAR_LEFT_SQUARE_BRACKET &&
    c !== CHAR_RIGHT_SQUARE_BRACKET &&
    c !== CHAR_LEFT_CURLY_BRACKET &&
    c !== CHAR_RIGHT_CURLY_BRACKET &&
    // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"”
    c !== CHAR_SHARP &&
    c !== CHAR_AMPERSAND &&
    c !== CHAR_ASTERISK &&
    c !== CHAR_EXCLAMATION &&
    c !== CHAR_VERTICAL_LINE &&
    c !== CHAR_EQUALS &&
    c !== CHAR_GREATER_THAN &&
    c !== CHAR_SINGLE_QUOTE &&
    c !== CHAR_DOUBLE_QUOTE &&
    // | “%” | “@” | “`”)
    c !== CHAR_PERCENT &&
    c !== CHAR_COMMERCIAL_AT &&
    c !== CHAR_GRAVE_ACCENT
}

// Simplified test for values allowed as the last character in plain style.
function isPlainSafeLast (c) {
  // just not whitespace or colon, it will be checked to be plain character later
  return !isWhitespace(c) && c !== CHAR_COLON
}

// Same as 'string'.codePointAt(pos), but works in older browsers.
function codePointAt (string, pos) {
  const first = string.charCodeAt(pos)
  let second

  if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) {
    second = string.charCodeAt(pos + 1)
    if (second >= 0xDC00 && second <= 0xDFFF) {
      // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
      return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000
    }
  }
  return first
}

// Determines whether block indentation indicator is required.
function needIndentIndicator (string) {
  const leadingSpaceRe = /^\n* /
  return leadingSpaceRe.test(string)
}

const STYLE_PLAIN = 1
const STYLE_SINGLE = 2
const STYLE_LITERAL = 3
const STYLE_FOLDED = 4
const STYLE_DOUBLE = 5

// Determines which scalar styles are possible and returns the preferred style.
// lineWidth = -1 => no limit.
// Pre-conditions: str.length > 0.
// Post-conditions:
//    STYLE_PLAIN or STYLE_SINGLE => no \n are in the string.
//    STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).
//    STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).
function chooseScalarStyle (string, singleLineOnly, indentPerLevel, lineWidth,
  testAmbiguousType, quotingType, forceQuotes, inblock) {
  let i
  let char = 0
  let prevChar = null
  let hasLineBreak = false
  let hasFoldableLine = false // only checked if shouldTrackWidth
  const shouldTrackWidth = lineWidth !== -1
  let previousLineBreak = -1 // count the first line correctly
  let plain = isPlainSafeFirst(codePointAt(string, 0)) &&
    isPlainSafeLast(codePointAt(string, string.length - 1))

  if (singleLineOnly || forceQuotes) {
    // Case: no block styles.
    // Check for disallowed characters to rule out plain and single.
    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
      char = codePointAt(string, i)
      if (!isPrintable(char)) {
        return STYLE_DOUBLE
      }
      plain = plain && isPlainSafe(char, prevChar, inblock)
      prevChar = char
    }
  } else {
    // Case: block styles permitted.
    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
      char = codePointAt(string, i)
      if (char === CHAR_LINE_FEED) {
        hasLineBreak = true
        // Check if any line can be folded.
        if (shouldTrackWidth) {
          hasFoldableLine = hasFoldableLine ||
            // Foldable line = too long, and not more-indented.
            (i - previousLineBreak - 1 > lineWidth &&
             string[previousLineBreak + 1] !== ' ')
          previousLineBreak = i
        }
      } else if (!isPrintable(char)) {
        return STYLE_DOUBLE
      }
      plain = plain && isPlainSafe(char, prevChar, inblock)
      prevChar = char
    }
    // in case the end is missing a \n
    hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&
      (i - previousLineBreak - 1 > lineWidth &&
       string[previousLineBreak + 1] !== ' '))
  }
  // Although every style can represent \n without escaping, prefer block styles
  // for multiline, since they're more readable and they don't add empty lines.
  // Also prefer folding a super-long line.
  if (!hasLineBreak && !hasFoldableLine) {
    // Strings interpretable as another type have to be quoted;
    // e.g. the string 'true' vs. the boolean true.
    if (plain && !forceQuotes && !testAmbiguousType(string)) {
      return STYLE_PLAIN
    }
    return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE
  }
  // Edge case: block indentation indicator can only have one digit.
  if (indentPerLevel > 9 && needIndentIndicator(string)) {
    return STYLE_DOUBLE
  }
  // At this point we know block styles are valid.
  // Prefer literal style unless we want to fold.
  if (!forceQuotes) {
    return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL
  }
  return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE
}

// Note: line breaking/folding is implemented for only the folded style.
// NB. We drop the last trailing newline (if any) of a returned block scalar
//  since the dumper adds its own newline. This always works:
//    • No ending newline => unaffected; already using strip "-" chomping.
//    • Ending newline    => removed then restored.
//  Importantly, this keeps the "+" chomp indicator from gaining an extra line.
function writeScalar (state, string, level, iskey, inblock) {
  state.dump = (function () {
    if (string.length === 0) {
      return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''"
    }
    if (!state.noCompatMode) {
      if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {
        return state.quotingType === QUOTING_TYPE_DOUBLE ? ('"' + string + '"') : ("'" + string + "'")
      }
    }

    const indent = state.indent * Math.max(1, level) // no 0-indent scalars
    // As indentation gets deeper, let the width decrease monotonically
    // to the lower bound min(state.lineWidth, 40).
    // Note that this implies
    //  state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.
    //  state.lineWidth > 40 + state.indent: width decreases until the lower bound.
    // This behaves better than a constant minimum width which disallows narrower options,
    // or an indent threshold which causes the width to suddenly increase.
    const lineWidth = (state.lineWidth === -1)
      ? -1
      : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent)

    // Without knowing if keys are implicit/explicit, assume implicit for safety.
    const singleLineOnly = iskey ||
      // No block styles in flow mode.
      (state.flowLevel > -1 && level >= state.flowLevel)
    function testAmbiguity (string) {
      return testImplicitResolving(state, string)
    }

    switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth,
      testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {
      case STYLE_PLAIN:
        return string
      case STYLE_SINGLE:
        return "'" + string.replace(/'/g, "''") + "'"
      case STYLE_LITERAL:
        return '|' + blockHeader(string, state.indent) +
          dropEndingNewline(indentString(string, indent))
      case STYLE_FOLDED:
        return '>' + blockHeader(string, state.indent) +
          dropEndingNewline(indentString(foldString(string, lineWidth), indent))
      case STYLE_DOUBLE:
        return '"' + escapeString(string, lineWidth) + '"'
      default:
        throw new YAMLException('impossible error: invalid scalar style')
    }
  }())
}

// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.
function blockHeader (string, indentPerLevel) {
  const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : ''

  // note the special case: the string '\n' counts as a "trailing" empty line.
  const clip = string[string.length - 1] === '\n'
  const keep = clip && (string[string.length - 2] === '\n' || string === '\n')
  const chomp = keep ? '+' : (clip ? '' : '-')

  return indentIndicator + chomp + '\n'
}

// (See the note for writeScalar.)
function dropEndingNewline (string) {
  return string[string.length - 1] === '\n' ? string.slice(0, -1) : string
}

// Note: a long line without a suitable break point will exceed the width limit.
// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.
function foldString (string, width) {
  // In folded style, $k$ consecutive newlines output as $k+1$ newlines—
  // unless they're before or after a more-indented line, or at the very
  // beginning or end, in which case $k$ maps to $k$.
  // Therefore, parse each chunk as newline(s) followed by a content line.
  const lineRe = /(\n+)([^\n]*)/g

  // first line (possibly an empty line)
  let result = (function () {
    let nextLF = string.indexOf('\n')
    nextLF = nextLF !== -1 ? nextLF : string.length
    lineRe.lastIndex = nextLF
    return foldLine(string.slice(0, nextLF), width)
  }())
  // If we haven't reached the first content line yet, don't add an extra \n.
  let prevMoreIndented = string[0] === '\n' || string[0] === ' '
  let moreIndented

  // rest of the lines
  let match
  while ((match = lineRe.exec(string))) {
    const prefix = match[1]
    const line = match[2]

    moreIndented = (line[0] === ' ')
    result += prefix +
      ((!prevMoreIndented && !moreIndented && line !== '') ? '\n' : '') +
      foldLine(line, width)
    prevMoreIndented = moreIndented
  }

  return result
}

// Greedy line breaking.
// Picks the longest line under the limit each time,
// otherwise settles for the shortest line over the limit.
// NB. More-indented lines *cannot* be folded, as that would add an extra \n.
function foldLine (line, width) {
  if (line === '' || line[0] === ' ') return line

  // Since a more-indented line adds a \n, breaks can't be followed by a space.
  const breakRe = / [^ ]/g // note: the match index will always be <= length-2.
  let match
  // start is an inclusive index. end, curr, and next are exclusive.
  let start = 0
  let end
  let curr = 0
  let next = 0
  let result = ''

  // Invariants: 0 <= start <= length-1.
  //   0 <= curr <= next <= max(0, length-2). curr - start <= width.
  // Inside the loop:
  //   A match implies length >= 2, so curr and next are <= length-2.
  while ((match = breakRe.exec(line))) {
    next = match.index
    // maintain invariant: curr - start <= width
    if (next - start > width) {
      end = (curr > start) ? curr : next // derive end <= length-2
      result += '\n' + line.slice(start, end)
      // skip the space that was output as \n
      start = end + 1                    // derive start <= length-1
    }
    curr = next
  }

  // By the invariants, start <= length-1, so there is something left over.
  // It is either the whole string or a part starting from non-whitespace.
  result += '\n'
  // Insert a break if the remainder is too long and there is a break available.
  if (line.length - start > width && curr > start) {
    result += line.slice(start, curr) + '\n' + line.slice(curr + 1)
  } else {
    result += line.slice(start)
  }

  return result.slice(1) // drop extra \n joiner
}

// Escapes a double-quoted string.
function escapeString (string) {
  let result = ''
  let char = 0

  for (let i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
    char = codePointAt(string, i)
    const escapeSeq = ESCAPE_SEQUENCES[char]

    if (!escapeSeq && isPrintable(char)) {
      result += string[i]
      if (char >= 0x10000) result += string[i + 1]
    } else {
      result += escapeSeq || encodeHex(char)
    }
  }

  return result
}

function writeFlowSequence (state, level, object) {
  let _result = ''
  const _tag = state.tag

  for (let index = 0, length = object.length; index < length; index += 1) {
    let value = object[index]

    if (state.replacer) {
      value = state.replacer.call(object, String(index), value)
    }

    // Write only valid elements, put null instead of invalid elements.
    if (writeNode(state, level, value, false, false) ||
        (typeof value === 'undefined' &&
         writeNode(state, level, null, false, false))) {
      if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : '')
      _result += state.dump
    }
  }

  state.tag = _tag
  state.dump = '[' + _result + ']'
}

function writeBlockSequence (state, level, object, compact) {
  let _result = ''
  const _tag = state.tag

  for (let index = 0, length = object.length; index < length; index += 1) {
    let value = object[index]

    if (state.replacer) {
      value = state.replacer.call(object, String(index), value)
    }

    // Write only valid elements, put null instead of invalid elements.
    if (writeNode(state, level + 1, value, true, true, false, true) ||
        (typeof value === 'undefined' &&
         writeNode(state, level + 1, null, true, true, false, true))) {
      if (!compact || _result !== '') {
        _result += generateNextLine(state, level)
      }

      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
        _result += '-'
      } else {
        _result += '- '
      }

      _result += state.dump
    }
  }

  state.tag = _tag
  state.dump = _result || '[]' // Empty sequence if no valid values.
}

function writeFlowMapping (state, level, object) {
  let _result = ''
  const _tag = state.tag
  const objectKeyList = Object.keys(object)

  for (let index = 0, length = objectKeyList.length; index < length; index += 1) {
    let pairBuffer = ''
    if (_result !== '') pairBuffer += ', '

    if (state.condenseFlow) pairBuffer += '"'

    const objectKey = objectKeyList[index]
    let objectValue = object[objectKey]

    if (state.replacer) {
      objectValue = state.replacer.call(object, objectKey, objectValue)
    }

    if (!writeNode(state, level, objectKey, false, false)) {
      continue // Skip this pair because of invalid key;
    }

    if (state.dump.length > 1024) pairBuffer += '? '

    pairBuffer += state.dump + (state.condenseFlow ? '"' : '') + ':' + (state.condenseFlow ? '' : ' ')

    if (!writeNode(state, level, objectValue, false, false)) {
      continue // Skip this pair because of invalid value.
    }

    pairBuffer += state.dump

    // Both key and value are valid.
    _result += pairBuffer
  }

  state.tag = _tag
  state.dump = '{' + _result + '}'
}

function writeBlockMapping (state, level, object, compact) {
  let _result = ''
  const _tag = state.tag
  const objectKeyList = Object.keys(object)

  // Allow sorting keys so that the output file is deterministic
  if (state.sortKeys === true) {
    // Default sorting
    objectKeyList.sort()
  } else if (typeof state.sortKeys === 'function') {
    // Custom sort function
    objectKeyList.sort(state.sortKeys)
  } else if (state.sortKeys) {
    // Something is wrong
    throw new YAMLException('sortKeys must be a boolean or a function')
  }

  for (let index = 0, length = objectKeyList.length; index < length; index += 1) {
    let pairBuffer = ''

    if (!compact || _result !== '') {
      pairBuffer += generateNextLine(state, level)
    }

    const objectKey = objectKeyList[index]
    let objectValue = object[objectKey]

    if (state.replacer) {
      objectValue = state.replacer.call(object, objectKey, objectValue)
    }

    if (!writeNode(state, level + 1, objectKey, true, true, true)) {
      continue // Skip this pair because of invalid key.
    }

    const explicitPair = (state.tag !== null && state.tag !== '?') ||
                   (state.dump && state.dump.length > 1024)

    if (explicitPair) {
      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
        pairBuffer += '?'
      } else {
        pairBuffer += '? '
      }
    }

    pairBuffer += state.dump

    if (explicitPair) {
      pairBuffer += generateNextLine(state, level)
    }

    if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
      continue // Skip this pair because of invalid value.
    }

    if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
      pairBuffer += ':'
    } else {
      pairBuffer += ': '
    }

    pairBuffer += state.dump

    // Both key and value are valid.
    _result += pairBuffer
  }

  state.tag = _tag
  state.dump = _result || '{}' // Empty mapping if no valid pairs.
}

function detectType (state, object, explicit) {
  const typeList = explicit ? state.explicitTypes : state.implicitTypes

  for (let index = 0, length = typeList.length; index < length; index += 1) {
    const type = typeList[index]

    if ((type.instanceOf || type.predicate) &&
        (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&
        (!type.predicate || type.predicate(object))) {
      if (explicit) {
        if (type.multi && type.representName) {
          state.tag = type.representName(object)
        } else {
          state.tag = type.tag
        }
      } else {
        state.tag = '?'
      }

      if (type.represent) {
        const style = state.styleMap[type.tag] || type.defaultStyle

        let _result
        if (_toString.call(type.represent) === '[object Function]') {
          _result = type.represent(object, style)
        } else if (_hasOwnProperty.call(type.represent, style)) {
          _result = type.represent[style](object, style)
        } else {
          throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style')
        }

        state.dump = _result
      }

      return true
    }
  }

  return false
}

// Serializes `object` and writes it to global `result`.
// Returns true on success, or false on invalid object.
//
function writeNode (state, level, object, block, compact, iskey, isblockseq) {
  state.tag = null
  state.dump = object

  if (!detectType(state, object, false)) {
    detectType(state, object, true)
  }

  const type = _toString.call(state.dump)
  const inblock = block

  if (block) {
    block = (state.flowLevel < 0 || state.flowLevel > level)
  }

  const objectOrArray = type === '[object Object]' || type === '[object Array]'
  let duplicateIndex
  let duplicate

  if (objectOrArray) {
    duplicateIndex = state.duplicates.indexOf(object)
    duplicate = duplicateIndex !== -1
  }

  if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {
    compact = false
  }

  if (duplicate && state.usedDuplicates[duplicateIndex]) {
    state.dump = '*ref_' + duplicateIndex
  } else {
    if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
      state.usedDuplicates[duplicateIndex] = true
    }
    if (type === '[object Object]') {
      if (block && (Object.keys(state.dump).length !== 0)) {
        writeBlockMapping(state, level, state.dump, compact)
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + state.dump
        }
      } else {
        writeFlowMapping(state, level, state.dump)
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump
        }
      }
    } else if (type === '[object Array]') {
      if (block && (state.dump.length !== 0)) {
        if (state.noArrayIndent && !isblockseq && level > 0) {
          writeBlockSequence(state, level - 1, state.dump, compact)
        } else {
          writeBlockSequence(state, level, state.dump, compact)
        }
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + state.dump
        }
      } else {
        writeFlowSequence(state, level, state.dump)
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump
        }
      }
    } else if (type === '[object String]') {
      if (state.tag !== '?') {
        writeScalar(state, state.dump, level, iskey, inblock)
      }
    } else if (type === '[object Undefined]') {
      return false
    } else {
      if (state.skipInvalid) return false
      throw new YAMLException('unacceptable kind of an object to dump ' + type)
    }

    if (state.tag !== null && state.tag !== '?') {
      // Need to encode all characters except those allowed by the spec:
      //
      // [35] ns-dec-digit    ::=  [#x30-#x39] /* 0-9 */
      // [36] ns-hex-digit    ::=  ns-dec-digit
      //                         | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */
      // [37] ns-ascii-letter ::=  [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */
      // [38] ns-word-char    ::=  ns-dec-digit | ns-ascii-letter | “-”
      // [39] ns-uri-char     ::=  “%” ns-hex-digit ns-hex-digit | ns-word-char | “#”
      //                         | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,”
      //                         | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]”
      //
      // Also need to encode '!' because it has special meaning (end of tag prefix).
      //
      let tagStr = encodeURI(
        state.tag[0] === '!' ? state.tag.slice(1) : state.tag
      ).replace(/!/g, '%21')

      if (state.tag[0] === '!') {
        tagStr = '!' + tagStr
      } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') {
        tagStr = '!!' + tagStr.slice(18)
      } else {
        tagStr = '!<' + tagStr + '>'
      }

      state.dump = tagStr + ' ' + state.dump
    }
  }

  return true
}

function getDuplicateReferences (object, state) {
  const objects = []
  const duplicatesIndexes = []

  inspectNode(object, objects, duplicatesIndexes)

  const length = duplicatesIndexes.length
  for (let index = 0; index < length; index += 1) {
    state.duplicates.push(objects[duplicatesIndexes[index]])
  }
  state.usedDuplicates = new Array(length)
}

function inspectNode (object, objects, duplicatesIndexes) {
  if (object !== null && typeof object === 'object') {
    const index = objects.indexOf(object)
    if (index !== -1) {
      if (duplicatesIndexes.indexOf(index) === -1) {
        duplicatesIndexes.push(index)
      }
    } else {
      objects.push(object)

      if (Array.isArray(object)) {
        for (let i = 0, length = object.length; i < length; i += 1) {
          inspectNode(object[i], objects, duplicatesIndexes)
        }
      } else {
        const objectKeyList = Object.keys(object)

        for (let i = 0, length = objectKeyList.length; i < length; i += 1) {
          inspectNode(object[objectKeyList[i]], objects, duplicatesIndexes)
        }
      }
    }
  }
}

function dump (input, options) {
  options = options || {}

  const state = new State(options)

  if (!state.noRefs) getDuplicateReferences(input, state)

  let value = input

  if (state.replacer) {
    value = state.replacer.call({ '': value }, '', value)
  }

  if (writeNode(state, 0, value, true, true)) return state.dump + '\n'

  return ''
}

module.exports.dump = dump
// YAML error class. http://stackoverflow.com/questions/8458984
//
'use strict'

function formatError (exception, compact) {
  let where = ''
  const message = exception.reason || '(unknown reason)'

  if (!exception.mark) return message

  if (exception.mark.name) {
    where += 'in "' + exception.mark.name + '" '
  }

  where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')'

  if (!compact && exception.mark.snippet) {
    where += '\n\n' + exception.mark.snippet
  }

  return message + ' ' + where
}

function YAMLException (reason, mark) {
  // Super constructor
  Error.call(this)

  this.name = 'YAMLException'
  this.reason = reason
  this.mark = mark
  this.message = formatError(this, false)

  // Include stack trace in error object
  if (Error.captureStackTrace) {
    // Chrome and NodeJS
    Error.captureStackTrace(this, this.constructor)
  } else {
    // FF, IE 10+ and Safari 6+. Fallback for others
    this.stack = (new Error()).stack || ''
  }
}

// Inherit from Error
YAMLException.prototype = Object.create(Error.prototype)
YAMLException.prototype.constructor = YAMLException

YAMLException.prototype.toString = function toString (compact) {
  return this.name + ': ' + formatError(this, compact)
}

module.exports = YAMLException
import yaml from '../index.js'

const {
  Type,
  Schema,
  FAILSAFE_SCHEMA,
  JSON_SCHEMA,
  CORE_SCHEMA,
  DEFAULT_SCHEMA,
  load,
  loadAll,
  dump,
  YAMLException,
  types,
  safeLoad,
  safeLoadAll,
  safeDump
} = yaml

export {
  Type,
  Schema,
  FAILSAFE_SCHEMA,
  JSON_SCHEMA,
  CORE_SCHEMA,
  DEFAULT_SCHEMA,
  load,
  loadAll,
  dump,
  YAMLException,
  types,
  safeLoad,
  safeLoadAll,
  safeDump
}

export default yaml
'use strict'

const common = require('./common')
const YAMLException = require('./exception')
const makeSnippet = require('./snippet')
const DEFAULT_SCHEMA = require('./schema/default')

const _hasOwnProperty = Object.prototype.hasOwnProperty

const CONTEXT_FLOW_IN = 1
const CONTEXT_FLOW_OUT = 2
const CONTEXT_BLOCK_IN = 3
const CONTEXT_BLOCK_OUT = 4

const CHOMPING_CLIP = 1
const CHOMPING_STRIP = 2
const CHOMPING_KEEP = 3

// eslint-disable-next-line no-control-regex
const PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/
const PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/
// eslint-disable-next-line no-useless-escape
const PATTERN_FLOW_INDICATORS = /[,\[\]{}]/
// eslint-disable-next-line no-useless-escape
const PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/
// eslint-disable-next-line no-useless-escape
const PATTERN_TAG_URI = /^(?:!|[^,\[\]{}])(?:%[0-9a-f]{2}|[0-9a-z\-#;/?:@&=+$,_.!~*'()\[\]])*$/i

function _class (obj) { return Object.prototype.toString.call(obj) }

function isEol (c) {
  return (c === 0x0A/* LF */) || (c === 0x0D/* CR */)
}

function isWhiteSpace (c) {
  return (c === 0x09/* Tab */) || (c === 0x20/* Space */)
}

function isWsOrEol (c) {
  return (c === 0x09/* Tab */) ||
         (c === 0x20/* Space */) ||
         (c === 0x0A/* LF */) ||
         (c === 0x0D/* CR */)
}

function isFlowIndicator (c) {
  return c === 0x2C/* , */ ||
         c === 0x5B/* [ */ ||
         c === 0x5D/* ] */ ||
         c === 0x7B/* { */ ||
         c === 0x7D/* } */
}

function fromHexCode (c) {
  if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {
    return c - 0x30
  }

  const lc = c | 0x20

  if ((lc >= 0x61/* a */) && (lc <= 0x66/* f */)) {
    return lc - 0x61 + 10
  }

  return -1
}

function escapedHexLen (c) {
  if (c === 0x78/* x */) { return 2 }
  if (c === 0x75/* u */) { return 4 }
  if (c === 0x55/* U */) { return 8 }
  return 0
}

function fromDecimalCode (c) {
  if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {
    return c - 0x30
  }

  return -1
}

function simpleEscapeSequence (c) {
  switch (c) {
    case 0x30/* 0 */: return '\x00'
    case 0x61/* a */: return '\x07'
    case 0x62/* b */: return '\x08'
    case 0x74/* t */: return '\x09'
    case 0x09/* Tab */: return '\x09'
    case 0x6E/* n */: return '\x0A'
    case 0x76/* v */: return '\x0B'
    case 0x66/* f */: return '\x0C'
    case 0x72/* r */: return '\x0D'
    case 0x65/* e */: return '\x1B'
    case 0x20/* Space */: return ' '
    case 0x22/* " */: return '\x22'
    case 0x2F/* / */: return '/'
    case 0x5C/* \ */: return '\x5C'
    case 0x4E/* N */: return '\x85'
    case 0x5F/* _ */: return '\xA0'
    case 0x4C/* L */: return '\u2028'
    case 0x50/* P */: return '\u2029'
    default: return ''
  }
}

function charFromCodepoint (c) {
  if (c <= 0xFFFF) {
    return String.fromCharCode(c)
  }
  // Encode UTF-16 surrogate pair
  // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF
  return String.fromCharCode(
    ((c - 0x010000) >> 10) + 0xD800,
    ((c - 0x010000) & 0x03FF) + 0xDC00
  )
}

// set a property of a literal object, while protecting against prototype pollution,
// see https://github.com/nodeca/js-yaml/issues/164 for more details
function setProperty (object, key, value) {
  // used for this specific key only because Object.defineProperty is slow
  if (key === '__proto__') {
    Object.defineProperty(object, key, {
      configurable: true,
      enumerable: true,
      writable: true,
      value: value
    })
  } else {
    object[key] = value
  }
}

const simpleEscapeCheck = new Array(256) // integer, for fast access
const simpleEscapeMap = new Array(256)
for (let i = 0; i < 256; i++) {
  simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0
  simpleEscapeMap[i] = simpleEscapeSequence(i)
}

function State (input, options) {
  this.input = input

  this.filename = options['filename'] || null
  this.schema = options['schema'] || DEFAULT_SCHEMA
  this.onWarning = options['onWarning'] || null
  // (Hidden) Remove? makes the loader to expect YAML 1.1 documents
  // if such documents have no explicit %YAML directive
  this.legacy = options['legacy'] || false

  this.json = options['json'] || false
  this.listener = options['listener'] || null
  this.maxDepth = typeof options['maxDepth'] === 'number' ? options['maxDepth'] : 100
  this.maxTotalMergeKeys = typeof options['maxTotalMergeKeys'] === 'number' ? options['maxTotalMergeKeys'] : 10000

  this.implicitTypes = this.schema.compiledImplicit
  this.typeMap = this.schema.compiledTypeMap

  this.length = input.length
  this.position = 0
  this.line = 0
  this.lineStart = 0
  this.lineIndent = 0
  this.depth = 0
  this.totalMergeKeys = 0

  // position of first leading tab in the current line,
  // used to make sure there are no tabs in the indentation
  this.firstTabInLine = -1

  this.documents = []
  this.anchorMapTransactions = []

  /*
  this.version;
  this.checkLineBreaks;
  this.tagMap;
  this.anchorMap;
  this.tag;
  this.anchor;
  this.kind;
  this.result; */
}

function generateError (state, message) {
  const mark = {
    name: state.filename,
    buffer: state.input.slice(0, -1), // omit trailing \0
    position: state.position,
    line: state.line,
    column: state.position - state.lineStart
  }

  mark.snippet = makeSnippet(mark)

  return new YAMLException(message, mark)
}

function throwError (state, message) {
  throw generateError(state, message)
}

function throwWarning (state, message) {
  if (state.onWarning) {
    state.onWarning.call(null, generateError(state, message))
  }
}

function storeAnchor (state, name, value) {
  const transactions = state.anchorMapTransactions

  if (transactions.length !== 0) {
    const transaction = transactions[transactions.length - 1]

    if (!_hasOwnProperty.call(transaction, name)) {
      transaction[name] = {
        existed: _hasOwnProperty.call(state.anchorMap, name),
        value: state.anchorMap[name]
      }
    }
  }

  state.anchorMap[name] = value
}

function beginAnchorTransaction (state) {
  state.anchorMapTransactions.push(Object.create(null))
}

function commitAnchorTransaction (state) {
  const transaction = state.anchorMapTransactions.pop()
  const transactions = state.anchorMapTransactions

  if (transactions.length === 0) return

  const parent = transactions[transactions.length - 1]
  const names = Object.keys(transaction)

  for (let index = 0, length = names.length; index < length; index += 1) {
    const name = names[index]

    if (!_hasOwnProperty.call(parent, name)) {
      parent[name] = transaction[name]
    }
  }
}

function rollbackAnchorTransaction (state) {
  const transaction = state.anchorMapTransactions.pop()
  const names = Object.keys(transaction)

  for (let index = names.length - 1; index >= 0; index -= 1) {
    const entry = transaction[names[index]]

    if (entry.existed) {
      state.anchorMap[names[index]] = entry.value
    } else {
      delete state.anchorMap[names[index]]
    }
  }
}

function snapshotState (state) {
  return {
    position: state.position,
    line: state.line,
    lineStart: state.lineStart,
    lineIndent: state.lineIndent,
    firstTabInLine: state.firstTabInLine,
    tag: state.tag,
    anchor: state.anchor,
    kind: state.kind,
    result: state.result
  }
}

function restoreState (state, snapshot) {
  state.position = snapshot.position
  state.line = snapshot.line
  state.lineStart = snapshot.lineStart
  state.lineIndent = snapshot.lineIndent
  state.firstTabInLine = snapshot.firstTabInLine
  state.tag = snapshot.tag
  state.anchor = snapshot.anchor
  state.kind = snapshot.kind
  state.result = snapshot.result
}

const directiveHandlers = {

  YAML: function handleYamlDirective (state, name, args) {
    if (state.version !== null) {
      throwError(state, 'duplication of %YAML directive')
    }

    if (args.length !== 1) {
      throwError(state, 'YAML directive accepts exactly one argument')
    }

    const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0])

    if (match === null) {
      throwError(state, 'ill-formed argument of the YAML directive')
    }

    const major = parseInt(match[1], 10)
    const minor = parseInt(match[2], 10)

    if (major !== 1) {
      throwError(state, 'unacceptable YAML version of the document')
    }

    state.version = args[0]
    state.checkLineBreaks = (minor < 2)

    if (minor !== 1 && minor !== 2) {
      throwWarning(state, 'unsupported YAML version of the document')
    }
  },

  TAG: function handleTagDirective (state, name, args) {
    let prefix

    if (args.length !== 2) {
      throwError(state, 'TAG directive accepts exactly two arguments')
    }

    const handle = args[0]
    prefix = args[1]

    if (!PATTERN_TAG_HANDLE.test(handle)) {
      throwError(state, 'ill-formed tag handle (first argument) of the TAG directive')
    }

    if (_hasOwnProperty.call(state.tagMap, handle)) {
      throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle')
    }

    if (!PATTERN_TAG_URI.test(prefix)) {
      throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive')
    }

    try {
      prefix = decodeURIComponent(prefix)
    } catch (err) {
      throwError(state, 'tag prefix is malformed: ' + prefix)
    }

    state.tagMap[handle] = prefix
  }
}

function captureSegment (state, start, end, checkJson) {
  if (start < end) {
    const _result = state.input.slice(start, end)

    if (checkJson) {
      for (let _position = 0, _length = _result.length; _position < _length; _position += 1) {
        const _character = _result.charCodeAt(_position)
        if (!(_character === 0x09 ||
              (_character >= 0x20 && _character <= 0x10FFFF))) {
          throwError(state, 'expected valid JSON character')
        }
      }
    } else if (PATTERN_NON_PRINTABLE.test(_result)) {
      throwError(state, 'the stream contains non-printable characters')
    }

    state.result += _result
  }
}

function mergeMappings (state, destination, source, overridableKeys) {
  if (!common.isObject(source)) {
    throwError(state, 'cannot merge mappings; the provided source object is unacceptable')
  }

  const sourceKeys = Object.keys(source)

  for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
    const key = sourceKeys[index]

    if (state.maxTotalMergeKeys !== -1 && ++state.totalMergeKeys > state.maxTotalMergeKeys) {
      throwError(state, 'merge keys exceeded maxTotalMergeKeys (' + state.maxTotalMergeKeys + ')')
    }

    if (!_hasOwnProperty.call(destination, key)) {
      setProperty(destination, key, source[key])
      overridableKeys[key] = true
    }
  }
}

function storeMappingPair (state, _result, overridableKeys, keyTag, keyNode, valueNode,
  startLine, startLineStart, startPos) {
  // The output is a plain object here, so keys can only be strings.
  // We need to convert keyNode to a string, but doing so can hang the process
  // (deeply nested arrays that explode exponentially using aliases).
  if (Array.isArray(keyNode)) {
    keyNode = Array.prototype.slice.call(keyNode)

    for (let index = 0, quantity = keyNode.length; index < quantity; index += 1) {
      if (Array.isArray(keyNode[index])) {
        throwError(state, 'nested arrays are not supported inside keys')
      }

      if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {
        keyNode[index] = '[object Object]'
      }
    }
  }

  // Avoid code execution in load() via toString property
  // (still use its own toString for arrays, timestamps,
  // and whatever user schema extensions happen to have @@toStringTag)
  if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {
    keyNode = '[object Object]'
  }

  keyNode = String(keyNode)

  if (_result === null) {
    _result = {}
  }

  if (keyTag === 'tag:yaml.org,2002:merge') {
    if (Array.isArray(valueNode)) {
      for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {
        mergeMappings(state, _result, valueNode[index], overridableKeys)
      }
    } else {
      mergeMappings(state, _result, valueNode, overridableKeys)
    }
  } else {
    if (!state.json &&
        !_hasOwnProperty.call(overridableKeys, keyNode) &&
        _hasOwnProperty.call(_result, keyNode)) {
      state.line = startLine || state.line
      state.lineStart = startLineStart || state.lineStart
      state.position = startPos || state.position
      throwError(state, 'duplicated mapping key')
    }

    setProperty(_result, keyNode, valueNode)
    delete overridableKeys[keyNode]
  }

  return _result
}

function readLineBreak (state) {
  const ch = state.input.charCodeAt(state.position)

  if (ch === 0x0A/* LF */) {
    state.position++
  } else if (ch === 0x0D/* CR */) {
    state.position++
    if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {
      state.position++
    }
  } else {
    throwError(state, 'a line break is expected')
  }

  state.line += 1
  state.lineStart = state.position
  state.firstTabInLine = -1
}

function skipSeparationSpace (state, allowComments, checkIndent) {
  let lineBreaks = 0
  let ch = state.input.charCodeAt(state.position)

  while (ch !== 0) {
    while (isWhiteSpace(ch)) {
      if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) {
        state.firstTabInLine = state.position
      }
      ch = state.input.charCodeAt(++state.position)
    }

    if (allowComments && ch === 0x23/* # */) {
      do {
        ch = state.input.charCodeAt(++state.position)
      } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0)
    }

    if (isEol(ch)) {
      readLineBreak(state)

      ch = state.input.charCodeAt(state.position)
      lineBreaks++
      state.lineIndent = 0

      while (ch === 0x20/* Space */) {
        state.lineIndent++
        ch = state.input.charCodeAt(++state.position)
      }
    } else {
      break
    }
  }

  if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
    throwWarning(state, 'deficient indentation')
  }

  return lineBreaks
}

function testDocumentSeparator (state) {
  let _position = state.position
  let ch = state.input.charCodeAt(_position)

  // Condition state.position === state.lineStart is tested
  // in parent on each call, for efficiency. No needs to test here again.
  if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&
      ch === state.input.charCodeAt(_position + 1) &&
      ch === state.input.charCodeAt(_position + 2)) {
    _position += 3

    ch = state.input.charCodeAt(_position)

    if (ch === 0 || isWsOrEol(ch)) {
      return true
    }
  }

  return false
}

function writeFoldedLines (state, count) {
  if (count === 1) {
    state.result += ' '
  } else if (count > 1) {
    state.result += common.repeat('\n', count - 1)
  }
}

function readPlainScalar (state, nodeIndent, withinFlowCollection) {
  let captureStart
  let captureEnd
  let hasPendingContent
  let _line
  let _lineStart
  let _lineIndent
  const _kind = state.kind
  const _result = state.result

  let ch = state.input.charCodeAt(state.position)

  if (isWsOrEol(ch) ||
      isFlowIndicator(ch) ||
      ch === 0x23/* # */ ||
      ch === 0x26/* & */ ||
      ch === 0x2A/* * */ ||
      ch === 0x21/* ! */ ||
      ch === 0x7C/* | */ ||
      ch === 0x3E/* > */ ||
      ch === 0x27/* ' */ ||
      ch === 0x22/* " */ ||
      ch === 0x25/* % */ ||
      ch === 0x40/* @ */ ||
      ch === 0x60/* ` */) {
    return false
  }

  if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {
    const following = state.input.charCodeAt(state.position + 1)

    if (isWsOrEol(following) ||
        (withinFlowCollection && isFlowIndicator(following))) {
      return false
    }
  }

  state.kind = 'scalar'
  state.result = ''
  captureStart = captureEnd = state.position
  hasPendingContent = false

  while (ch !== 0) {
    if (ch === 0x3A/* : */) {
      const following = state.input.charCodeAt(state.position + 1)

      if (isWsOrEol(following) ||
          (withinFlowCollection && isFlowIndicator(following))) {
        break
      }
    } else if (ch === 0x23/* # */) {
      const preceding = state.input.charCodeAt(state.position - 1)

      if (isWsOrEol(preceding)) {
        break
      }
    } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||
               (withinFlowCollection && isFlowIndicator(ch))) {
      break
    } else if (isEol(ch)) {
      _line = state.line
      _lineStart = state.lineStart
      _lineIndent = state.lineIndent
      skipSeparationSpace(state, false, -1)

      if (state.lineIndent >= nodeIndent) {
        hasPendingContent = true
        ch = state.input.charCodeAt(state.position)
        continue
      } else {
        state.position = captureEnd
        state.line = _line
        state.lineStart = _lineStart
        state.lineIndent = _lineIndent
        break
      }
    }

    if (hasPendingContent) {
      captureSegment(state, captureStart, captureEnd, false)
      writeFoldedLines(state, state.line - _line)
      captureStart = captureEnd = state.position
      hasPendingContent = false
    }

    if (!isWhiteSpace(ch)) {
      captureEnd = state.position + 1
    }

    ch = state.input.charCodeAt(++state.position)
  }

  captureSegment(state, captureStart, captureEnd, false)

  if (state.result) {
    return true
  }

  state.kind = _kind
  state.result = _result
  return false
}

function readSingleQuotedScalar (state, nodeIndent) {
  let captureStart
  let captureEnd

  let ch = state.input.charCodeAt(state.position)

  if (ch !== 0x27/* ' */) {
    return false
  }

  state.kind = 'scalar'
  state.result = ''
  state.position++
  captureStart = captureEnd = state.position

  while ((ch = state.input.charCodeAt(state.position)) !== 0) {
    if (ch === 0x27/* ' */) {
      captureSegment(state, captureStart, state.position, true)
      ch = state.input.charCodeAt(++state.position)

      if (ch === 0x27/* ' */) {
        captureStart = state.position
        state.position++
        captureEnd = state.position
      } else {
        return true
      }
    } else if (isEol(ch)) {
      captureSegment(state, captureStart, captureEnd, true)
      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))
      captureStart = captureEnd = state.position
    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
      throwError(state, 'unexpected end of the document within a single quoted scalar')
    } else {
      state.position++
      if (!isWhiteSpace(ch)) {
        captureEnd = state.position
      }
    }
  }

  throwError(state, 'unexpected end of the stream within a single quoted scalar')
}

function readDoubleQuotedScalar (state, nodeIndent) {
  let captureStart
  let captureEnd
  let tmp

  let ch = state.input.charCodeAt(state.position)

  if (ch !== 0x22/* " */) {
    return false
  }

  state.kind = 'scalar'
  state.result = ''
  state.position++
  captureStart = captureEnd = state.position

  while ((ch = state.input.charCodeAt(state.position)) !== 0) {
    if (ch === 0x22/* " */) {
      captureSegment(state, captureStart, state.position, true)
      state.position++
      return true
    } else if (ch === 0x5C/* \ */) {
      captureSegment(state, captureStart, state.position, true)
      ch = state.input.charCodeAt(++state.position)

      if (isEol(ch)) {
        skipSeparationSpace(state, false, nodeIndent)

        // TODO: rework to inline fn with no type cast?
      } else if (ch < 256 && simpleEscapeCheck[ch]) {
        state.result += simpleEscapeMap[ch]
        state.position++
      } else if ((tmp = escapedHexLen(ch)) > 0) {
        let hexLength = tmp
        let hexResult = 0

        for (; hexLength > 0; hexLength--) {
          ch = state.input.charCodeAt(++state.position)

          if ((tmp = fromHexCode(ch)) >= 0) {
            hexResult = (hexResult << 4) + tmp
          } else {
            throwError(state, 'expected hexadecimal character')
          }
        }

        state.result += charFromCodepoint(hexResult)

        state.position++
      } else {
        throwError(state, 'unknown escape sequence')
      }

      captureStart = captureEnd = state.position
    } else if (isEol(ch)) {
      captureSegment(state, captureStart, captureEnd, true)
      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))
      captureStart = captureEnd = state.position
    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
      throwError(state, 'unexpected end of the document within a double quoted scalar')
    } else {
      state.position++
      if (!isWhiteSpace(ch)) {
        captureEnd = state.position
      }
    }
  }

  throwError(state, 'unexpected end of the stream within a double quoted scalar')
}

function readFlowCollection (state, nodeIndent) {
  let readNext = true
  let _line
  let _lineStart
  let _pos
  const _tag = state.tag
  let _result
  const _anchor = state.anchor
  let terminator
  let isPair
  let isExplicitPair
  let isMapping
  const overridableKeys = Object.create(null)
  let keyNode
  let keyTag
  let valueNode

  let ch = state.input.charCodeAt(state.position)

  if (ch === 0x5B/* [ */) {
    terminator = 0x5D/* ] */
    isMapping = false
    _result = []
  } else if (ch === 0x7B/* { */) {
    terminator = 0x7D/* } */
    isMapping = true
    _result = {}
  } else {
    return false
  }

  if (state.anchor !== null) {
    storeAnchor(state, state.anchor, _result)
  }

  ch = state.input.charCodeAt(++state.position)

  while (ch !== 0) {
    skipSeparationSpace(state, true, nodeIndent)

    ch = state.input.charCodeAt(state.position)

    if (ch === terminator) {
      state.position++
      state.tag = _tag
      state.anchor = _anchor
      state.kind = isMapping ? 'mapping' : 'sequence'
      state.result = _result
      return true
    } else if (!readNext) {
      throwError(state, 'missed comma between flow collection entries')
    } else if (ch === 0x2C/* , */) {
      // "flow collection entries can never be completely empty", as per YAML 1.2, section 7.4
      throwError(state, "expected the node content, but found ','")
    }

    keyTag = keyNode = valueNode = null
    isPair = isExplicitPair = false

    if (ch === 0x3F/* ? */) {
      const following = state.input.charCodeAt(state.position + 1)

      if (isWsOrEol(following)) {
        isPair = isExplicitPair = true
        state.position++
        skipSeparationSpace(state, true, nodeIndent)
      }
    }

    _line = state.line // Save the current line.
    _lineStart = state.lineStart
    _pos = state.position
    composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)
    keyTag = state.tag
    keyNode = state.result
    skipSeparationSpace(state, true, nodeIndent)

    ch = state.input.charCodeAt(state.position)

    if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {
      isPair = true
      ch = state.input.charCodeAt(++state.position)
      skipSeparationSpace(state, true, nodeIndent)
      composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)
      valueNode = state.result
    }

    if (isMapping) {
      storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)
    } else if (isPair) {
      _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos))
    } else {
      _result.push(keyNode)
    }

    skipSeparationSpace(state, true, nodeIndent)

    ch = state.input.charCodeAt(state.position)

    if (ch === 0x2C/* , */) {
      readNext = true
      ch = state.input.charCodeAt(++state.position)
    } else {
      readNext = false
    }
  }

  throwError(state, 'unexpected end of the stream within a flow collection')
}

function readBlockScalar (state, nodeIndent) {
  let folding
  let chomping = CHOMPING_CLIP
  let didReadContent = false
  let detectedIndent = false
  let textIndent = nodeIndent
  let emptyLines = 0
  let atMoreIndented = false
  let tmp

  let ch = state.input.charCodeAt(state.position)

  if (ch === 0x7C/* | */) {
    folding = false
  } else if (ch === 0x3E/* > */) {
    folding = true
  } else {
    return false
  }

  state.kind = 'scalar'
  state.result = ''

  while (ch !== 0) {
    ch = state.input.charCodeAt(++state.position)

    if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {
      if (CHOMPING_CLIP === chomping) {
        chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP
      } else {
        throwError(state, 'repeat of a chomping mode identifier')
      }
    } else if ((tmp = fromDecimalCode(ch)) >= 0) {
      if (tmp === 0) {
        throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one')
      } else if (!detectedIndent) {
        textIndent = nodeIndent + tmp - 1
        detectedIndent = true
      } else {
        throwError(state, 'repeat of an indentation width identifier')
      }
    } else {
      break
    }
  }

  if (isWhiteSpace(ch)) {
    do { ch = state.input.charCodeAt(++state.position) }
    while (isWhiteSpace(ch))

    if (ch === 0x23/* # */) {
      do { ch = state.input.charCodeAt(++state.position) }
      while (!isEol(ch) && (ch !== 0))
    }
  }

  while (ch !== 0) {
    readLineBreak(state)
    state.lineIndent = 0

    ch = state.input.charCodeAt(state.position)

    // eslint-disable-next-line no-unmodified-loop-condition
    while ((!detectedIndent || state.lineIndent < textIndent) &&
           (ch === 0x20/* Space */)) {
      state.lineIndent++
      ch = state.input.charCodeAt(++state.position)
    }

    if (!detectedIndent && state.lineIndent > textIndent) {
      textIndent = state.lineIndent
    }

    if (isEol(ch)) {
      emptyLines++
      continue
    }

    if (!detectedIndent && textIndent === 0) {
      throwError(state, 'missing indentation for block scalar')
    }

    // End of the scalar.
    if (state.lineIndent < textIndent) {
      // Perform the chomping.
      if (chomping === CHOMPING_KEEP) {
        state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines)
      } else if (chomping === CHOMPING_CLIP) {
        if (didReadContent) { // i.e. only if the scalar is not empty.
          state.result += '\n'
        }
      }

      // Break this `while` cycle and go to the funciton's epilogue.
      break
    }

    // Folded style: use fancy rules to handle line breaks.
    if (folding) {
      // Lines starting with white space characters (more-indented lines) are not folded.
      if (isWhiteSpace(ch)) {
        atMoreIndented = true
        // except for the first content line (cf. Example 8.1)
        state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines)

      // End of more-indented block.
      } else if (atMoreIndented) {
        atMoreIndented = false
        state.result += common.repeat('\n', emptyLines + 1)

      // Just one line break - perceive as the same line.
      } else if (emptyLines === 0) {
        if (didReadContent) { // i.e. only if we have already read some scalar content.
          state.result += ' '
        }

      // Several line breaks - perceive as different lines.
      } else {
        state.result += common.repeat('\n', emptyLines)
      }

    // Literal style: just add exact number of line breaks between content lines.
    } else {
      // Keep all line breaks except the header line break.
      state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines)
    }

    didReadContent = true
    detectedIndent = true
    emptyLines = 0
    const captureStart = state.position

    while (!isEol(ch) && (ch !== 0)) {
      ch = state.input.charCodeAt(++state.position)
    }

    captureSegment(state, captureStart, state.position, false)
  }

  return true
}

function readBlockSequence (state, nodeIndent) {
  const _tag = state.tag
  const _anchor = state.anchor
  const _result = []
  let detected = false

  // there is a leading tab before this token, so it can't be a block sequence/mapping;
  // it can still be flow sequence/mapping or a scalar
  if (state.firstTabInLine !== -1) return false

  if (state.anchor !== null) {
    storeAnchor(state, state.anchor, _result)
  }

  let ch = state.input.charCodeAt(state.position)

  while (ch !== 0) {
    if (state.firstTabInLine !== -1) {
      state.position = state.firstTabInLine
      throwError(state, 'tab characters must not be used in indentation')
    }

    if (ch !== 0x2D/* - */) {
      break
    }

    const following = state.input.charCodeAt(state.position + 1)

    if (!isWsOrEol(following)) {
      break
    }

    detected = true
    state.position++

    if (skipSeparationSpace(state, true, -1)) {
      if (state.lineIndent <= nodeIndent) {
        _result.push(null)
        ch = state.input.charCodeAt(state.position)
        continue
      }
    }

    const _line = state.line
    composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true)
    _result.push(state.result)
    skipSeparationSpace(state, true, -1)

    ch = state.input.charCodeAt(state.position)

    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
      throwError(state, 'bad indentation of a sequence entry')
    } else if (state.lineIndent < nodeIndent) {
      break
    }
  }

  if (detected) {
    state.tag = _tag
    state.anchor = _anchor
    state.kind = 'sequence'
    state.result = _result
    return true
  }
  return false
}

function readBlockMapping (state, nodeIndent, flowIndent) {
  let allowCompact
  let _keyLine
  let _keyLineStart
  let _keyPos
  const _tag = state.tag
  const _anchor = state.anchor
  const _result = {}
  const overridableKeys = Object.create(null)
  let keyTag = null
  let keyNode = null
  let valueNode = null
  let atExplicitKey = false
  let detected = false

  // there is a leading tab before this token, so it can't be a block sequence/mapping;
  // it can still be flow sequence/mapping or a scalar
  if (state.firstTabInLine !== -1) return false

  if (state.anchor !== null) {
    storeAnchor(state, state.anchor, _result)
  }

  let ch = state.input.charCodeAt(state.position)

  while (ch !== 0) {
    if (!atExplicitKey && state.firstTabInLine !== -1) {
      state.position = state.firstTabInLine
      throwError(state, 'tab characters must not be used in indentation')
    }

    const following = state.input.charCodeAt(state.position + 1)
    const _line = state.line // Save the current line.

    //
    // Explicit notation case. There are two separate blocks:
    // first for the key (denoted by "?") and second for the value (denoted by ":")
    //
    if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && isWsOrEol(following)) {
      if (ch === 0x3F/* ? */) {
        if (atExplicitKey) {
          storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)
          keyTag = keyNode = valueNode = null
        }

        detected = true
        atExplicitKey = true
        allowCompact = true
      } else if (atExplicitKey) {
        // i.e. 0x3A/* : */ === character after the explicit key.
        atExplicitKey = false
        allowCompact = true
      } else {
        throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line')
      }

      state.position += 1
      ch = following

    //
    // Implicit notation case. Flow-style node as the key first, then ":", and the value.
    //
    } else {
      _keyLine = state.line
      _keyLineStart = state.lineStart
      _keyPos = state.position

      if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
        // Neither implicit nor explicit notation.
        // Reading is done. Go to the epilogue.
        break
      }

      if (state.line === _line) {
        ch = state.input.charCodeAt(state.position)

        while (isWhiteSpace(ch)) {
          ch = state.input.charCodeAt(++state.position)
        }

        if (ch === 0x3A/* : */) {
          ch = state.input.charCodeAt(++state.position)

          if (!isWsOrEol(ch)) {
            throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping')
          }

          if (atExplicitKey) {
            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)
            keyTag = keyNode = valueNode = null
          }

          detected = true
          atExplicitKey = false
          allowCompact = false
          keyTag = state.tag
          keyNode = state.result
        } else if (detected) {
          throwError(state, 'can not read an implicit mapping pair; a colon is missed')
        } else {
          state.tag = _tag
          state.anchor = _anchor
          return true // Keep the result of `composeNode`.
        }
      } else if (detected) {
        throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key')
      } else {
        state.tag = _tag
        state.anchor = _anchor
        return true // Keep the result of `composeNode`.
      }
    }

    //
    // Common reading code for both explicit and implicit notations.
    //
    if (state.line === _line || state.lineIndent > nodeIndent) {
      if (atExplicitKey) {
        _keyLine = state.line
        _keyLineStart = state.lineStart
        _keyPos = state.position
      }

      if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
        if (atExplicitKey) {
          keyNode = state.result
        } else {
          valueNode = state.result
        }
      }

      if (!atExplicitKey) {
        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos)
        keyTag = keyNode = valueNode = null
      }

      skipSeparationSpace(state, true, -1)
      ch = state.input.charCodeAt(state.position)
    }

    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
      throwError(state, 'bad indentation of a mapping entry')
    } else if (state.lineIndent < nodeIndent) {
      break
    }
  }

  //
  // Epilogue.
  //

  // Special case: last mapping's node contains only the key in explicit notation.
  if (atExplicitKey) {
    storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)
  }

  // Expose the resulting mapping.
  if (detected) {
    state.tag = _tag
    state.anchor = _anchor
    state.kind = 'mapping'
    state.result = _result
  }

  return detected
}

function readTagProperty (state) {
  let isVerbatim = false
  let isNamed = false
  let tagHandle
  let tagName

  let ch = state.input.charCodeAt(state.position)

  if (ch !== 0x21/* ! */) return false

  if (state.tag !== null) {
    throwError(state, 'duplication of a tag property')
  }

  ch = state.input.charCodeAt(++state.position)

  if (ch === 0x3C/* < */) {
    isVerbatim = true
    ch = state.input.charCodeAt(++state.position)
  } else if (ch === 0x21/* ! */) {
    isNamed = true
    tagHandle = '!!'
    ch = state.input.charCodeAt(++state.position)
  } else {
    tagHandle = '!'
  }

  let _position = state.position

  if (isVerbatim) {
    do { ch = state.input.charCodeAt(++state.position) }
    while (ch !== 0 && ch !== 0x3E/* > */)

    if (state.position < state.length) {
      tagName = state.input.slice(_position, state.position)
      ch = state.input.charCodeAt(++state.position)
    } else {
      throwError(state, 'unexpected end of the stream within a verbatim tag')
    }
  } else {
    while (ch !== 0 && !isWsOrEol(ch)) {
      if (ch === 0x21/* ! */) {
        if (!isNamed) {
          tagHandle = state.input.slice(_position - 1, state.position + 1)

          if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
            throwError(state, 'named tag handle cannot contain such characters')
          }

          isNamed = true
          _position = state.position + 1
        } else {
          throwError(state, 'tag suffix cannot contain exclamation marks')
        }
      }

      ch = state.input.charCodeAt(++state.position)
    }

    tagName = state.input.slice(_position, state.position)

    if (PATTERN_FLOW_INDICATORS.test(tagName)) {
      throwError(state, 'tag suffix cannot contain flow indicator characters')
    }
  }

  if (tagName && !PATTERN_TAG_URI.test(tagName)) {
    throwError(state, 'tag name cannot contain such characters: ' + tagName)
  }

  try {
    tagName = decodeURIComponent(tagName)
  } catch (err) {
    throwError(state, 'tag name is malformed: ' + tagName)
  }

  if (isVerbatim) {
    state.tag = tagName
  } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {
    state.tag = state.tagMap[tagHandle] + tagName
  } else if (tagHandle === '!') {
    state.tag = '!' + tagName
  } else if (tagHandle === '!!') {
    state.tag = 'tag:yaml.org,2002:' + tagName
  } else {
    throwError(state, 'undeclared tag handle "' + tagHandle + '"')
  }

  return true
}

function readAnchorProperty (state) {
  let ch = state.input.charCodeAt(state.position)

  if (ch !== 0x26/* & */) return false

  if (state.anchor !== null) {
    throwError(state, 'duplication of an anchor property')
  }

  ch = state.input.charCodeAt(++state.position)
  const _position = state.position

  while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {
    ch = state.input.charCodeAt(++state.position)
  }

  if (state.position === _position) {
    throwError(state, 'name of an anchor node must contain at least one character')
  }

  state.anchor = state.input.slice(_position, state.position)
  return true
}

function readAlias (state) {
  let ch = state.input.charCodeAt(state.position)

  if (ch !== 0x2A/* * */) return false

  ch = state.input.charCodeAt(++state.position)
  const _position = state.position

  while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {
    ch = state.input.charCodeAt(++state.position)
  }

  if (state.position === _position) {
    throwError(state, 'name of an alias node must contain at least one character')
  }

  const alias = state.input.slice(_position, state.position)

  if (!_hasOwnProperty.call(state.anchorMap, alias)) {
    throwError(state, 'unidentified alias "' + alias + '"')
  }

  state.result = state.anchorMap[alias]
  skipSeparationSpace(state, true, -1)
  return true
}

function tryReadBlockMappingFromProperty (state, propertyStart, nodeIndent, flowIndent) {
  const fallbackState = snapshotState(state)

  beginAnchorTransaction(state)
  restoreState(state, propertyStart)

  // Re-read the leading properties as part of the first implicit key, not as
  // properties of the current node.
  state.tag = null
  state.anchor = null
  state.kind = null
  state.result = null

  if (readBlockMapping(state, nodeIndent, flowIndent) && state.kind === 'mapping') {
    commitAnchorTransaction(state)
    return true
  }

  rollbackAnchorTransaction(state)
  restoreState(state, fallbackState)
  return false
}

function composeNode (state, parentIndent, nodeContext, allowToSeek, allowCompact) {
  let allowBlockScalars
  let allowBlockCollections
  let indentStatus = 1 // 1: this>parent, 0: this=parent, -1: this<parent
  let atNewLine = false
  let hasContent = false
  let propertyStart = null
  let type
  let flowIndent
  let blockIndent

  if (state.depth >= state.maxDepth) {
    throwError(state, 'nesting exceeded maxDepth (' + state.maxDepth + ')')
  }

  state.depth += 1

  if (state.listener !== null) {
    state.listener('open', state)
  }

  state.tag = null
  state.anchor = null
  state.kind = null
  state.result = null

  const allowBlockStyles = allowBlockScalars = allowBlockCollections =
    CONTEXT_BLOCK_OUT === nodeContext ||
    CONTEXT_BLOCK_IN === nodeContext

  if (allowToSeek) {
    if (skipSeparationSpace(state, true, -1)) {
      atNewLine = true

      if (state.lineIndent > parentIndent) {
        indentStatus = 1
      } else if (state.lineIndent === parentIndent) {
        indentStatus = 0
      } else if (state.lineIndent < parentIndent) {
        indentStatus = -1
      }
    }
  }

  if (indentStatus === 1) {
    while (true) {
      const ch = state.input.charCodeAt(state.position)
      const propertyState = snapshotState(state)

      // A duplicate property token after a line break can be the first key of
      // a nested block mapping, e.g. `!!map\n  !!str key: value`.
      if (atNewLine &&
          ((ch === 0x21/* ! */ && state.tag !== null) ||
           (ch === 0x26/* & */ && state.anchor !== null))) {
        break
      }

      if (!readTagProperty(state) && !readAnchorProperty(state)) {
        break
      }

      if (propertyStart === null) {
        propertyStart = propertyState
      }

      if (skipSeparationSpace(state, true, -1)) {
        atNewLine = true
        allowBlockCollections = allowBlockStyles

        if (state.lineIndent > parentIndent) {
          indentStatus = 1
        } else if (state.lineIndent === parentIndent) {
          indentStatus = 0
        } else if (state.lineIndent < parentIndent) {
          indentStatus = -1
        }
      } else {
        allowBlockCollections = false
      }
    }
  }

  if (allowBlockCollections) {
    allowBlockCollections = atNewLine || allowCompact
  }

  if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
    if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
      flowIndent = parentIndent
    } else {
      flowIndent = parentIndent + 1
    }

    blockIndent = state.position - state.lineStart

    if (indentStatus === 1) {
      if ((allowBlockCollections &&
          (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent))) ||
          readFlowCollection(state, flowIndent)) {
        hasContent = true
      } else {
        const ch = state.input.charCodeAt(state.position)

        if (propertyStart !== null && allowBlockStyles && !allowBlockCollections &&
            ch !== 0x7C/* | */ && ch !== 0x3E/* > */ &&
            tryReadBlockMappingFromProperty(
              state,
              propertyStart,
              propertyStart.position - propertyStart.lineStart,
              flowIndent
            )) {
          hasContent = true
        } else if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||
            readSingleQuotedScalar(state, flowIndent) ||
            readDoubleQuotedScalar(state, flowIndent)) {
          hasContent = true
        } else if (readAlias(state)) {
          hasContent = true

          if (state.tag !== null || state.anchor !== null) {
            throwError(state, 'alias node should not have any properties')
          }
        } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
          hasContent = true

          if (state.tag === null) {
            state.tag = '?'
          }
        }

        if (state.anchor !== null) {
          storeAnchor(state, state.anchor, state.result)
        }
      }
    } else if (indentStatus === 0) {
      // Special case: block sequences are allowed to have same indentation level as the parent.
      // http://www.yaml.org/spec/1.2/spec.html#id2799784
      hasContent = allowBlockCollections && readBlockSequence(state, blockIndent)
    }
  }

  if (state.tag === null) {
    if (state.anchor !== null) {
      storeAnchor(state, state.anchor, state.result)
    }
  } else if (state.tag === '?') {
    // Implicit resolving is not allowed for non-scalar types, and '?'
    // non-specific tag is only automatically assigned to plain scalars.
    //
    // We only need to check kind conformity in case user explicitly assigns '?'
    // tag, for example like this: "!<?> [0]"
    //
    if (state.result !== null && state.kind !== 'scalar') {
      throwError(state, 'unacceptable node kind for !<?> tag; it should be "scalar", not "' + state.kind + '"')
    }

    for (let typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {
      type = state.implicitTypes[typeIndex]

      if (type.resolve(state.result)) { // `state.result` updated in resolver if matched
        state.result = type.construct(state.result)
        state.tag = type.tag
        if (state.anchor !== null) {
          storeAnchor(state, state.anchor, state.result)
        }
        break
      }
    }
  } else if (state.tag !== '!') {
    if (_hasOwnProperty.call(state.typeMap[state.kind || 'fallback'], state.tag)) {
      type = state.typeMap[state.kind || 'fallback'][state.tag]
    } else {
      // looking for multi type
      type = null
      const typeList = state.typeMap.multi[state.kind || 'fallback']

      for (let typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {
        if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {
          type = typeList[typeIndex]
          break
        }
      }
    }

    if (!type) {
      throwError(state, 'unknown tag !<' + state.tag + '>')
    }

    if (state.result !== null && type.kind !== state.kind) {
      throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"')
    }

    if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched
      throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag')
    } else {
      state.result = type.construct(state.result, state.tag)
      if (state.anchor !== null) {
        storeAnchor(state, state.anchor, state.result)
      }
    }
  }

  if (state.listener !== null) {
    state.listener('close', state)
  }

  state.depth -= 1
  return state.tag !== null || state.anchor !== null || hasContent
}

function readDocument (state) {
  const documentStart = state.position
  let hasDirectives = false
  let ch

  state.version = null
  state.checkLineBreaks = state.legacy
  state.tagMap = Object.create(null)
  state.anchorMap = Object.create(null)

  while ((ch = state.input.charCodeAt(state.position)) !== 0) {
    skipSeparationSpace(state, true, -1)

    ch = state.input.charCodeAt(state.position)

    if (state.lineIndent > 0 || ch !== 0x25/* % */) {
      break
    }

    hasDirectives = true
    ch = state.input.charCodeAt(++state.position)
    let _position = state.position

    while (ch !== 0 && !isWsOrEol(ch)) {
      ch = state.input.charCodeAt(++state.position)
    }

    const directiveName = state.input.slice(_position, state.position)
    const directiveArgs = []

    if (directiveName.length < 1) {
      throwError(state, 'directive name must not be less than one character in length')
    }

    while (ch !== 0) {
      while (isWhiteSpace(ch)) {
        ch = state.input.charCodeAt(++state.position)
      }

      if (ch === 0x23/* # */) {
        do { ch = state.input.charCodeAt(++state.position) }
        while (ch !== 0 && !isEol(ch))
        break
      }

      if (isEol(ch)) break

      _position = state.position

      while (ch !== 0 && !isWsOrEol(ch)) {
        ch = state.input.charCodeAt(++state.position)
      }

      directiveArgs.push(state.input.slice(_position, state.position))
    }

    if (ch !== 0) readLineBreak(state)

    if (_hasOwnProperty.call(directiveHandlers, directiveName)) {
      directiveHandlers[directiveName](state, directiveName, directiveArgs)
    } else {
      throwWarning(state, 'unknown document directive "' + directiveName + '"')
    }
  }

  skipSeparationSpace(state, true, -1)

  if (state.lineIndent === 0 &&
      state.input.charCodeAt(state.position) === 0x2D/* - */ &&
      state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&
      state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {
    state.position += 3
    skipSeparationSpace(state, true, -1)
  } else if (hasDirectives) {
    throwError(state, 'directives end mark is expected')
  }

  composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true)
  skipSeparationSpace(state, true, -1)

  if (state.checkLineBreaks &&
      PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
    throwWarning(state, 'non-ASCII line breaks are interpreted as content')
  }

  state.documents.push(state.result)

  if (state.position === state.lineStart && testDocumentSeparator(state)) {
    if (state.input.charCodeAt(state.position) === 0x2E/* . */) {
      state.position += 3
      skipSeparationSpace(state, true, -1)
    }
    return
  }

  if (state.position < (state.length - 1)) {
    throwError(state, 'end of the stream or a document separator is expected')
  }
}

function loadDocuments (input, options) {
  input = String(input)
  options = options || {}

  if (input.length !== 0) {
    // Add tailing `\n` if not exists
    if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&
        input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {
      input += '\n'
    }

    // Strip BOM
    if (input.charCodeAt(0) === 0xFEFF) {
      input = input.slice(1)
    }
  }

  const state = new State(input, options)

  const nullpos = input.indexOf('\0')

  if (nullpos !== -1) {
    state.position = nullpos
    throwError(state, 'null byte is not allowed in input')
  }

  // Use 0 as string terminator. That significantly simplifies bounds check.
  state.input += '\0'

  while (state.input.charCodeAt(state.position) === 0x20/* Space */) {
    state.lineIndent += 1
    state.position += 1
  }

  while (state.position < (state.length - 1)) {
    readDocument(state)
  }

  return state.documents
}

function loadAll (input, iterator, options) {
  if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {
    options = iterator
    iterator = null
  }

  const documents = loadDocuments(input, options)

  if (typeof iterator !== 'function') {
    return documents
  }

  for (let index = 0, length = documents.length; index < length; index += 1) {
    iterator(documents[index])
  }
}

function load (input, options) {
  const documents = loadDocuments(input, options)

  if (documents.length === 0) {
    return undefined
  } else if (documents.length === 1) {
    return documents[0]
  }
  throw new YAMLException('expected a single document in the stream, but found more')
}

module.exports.loadAll = loadAll
module.exports.load = load
'use strict'

const YAMLException = require('./exception')
const Type = require('./type')

function compileList (schema, name) {
  const result = []

  schema[name].forEach(function (currentType) {
    let newIndex = result.length

    result.forEach(function (previousType, previousIndex) {
      if (previousType.tag === currentType.tag &&
          previousType.kind === currentType.kind &&
          previousType.multi === currentType.multi) {
        newIndex = previousIndex
      }
    })

    result[newIndex] = currentType
  })

  return result
}

function compileMap (/* lists... */) {
  const result = {
    scalar: {},
    sequence: {},
    mapping: {},
    fallback: {},
    multi: {
      scalar: [],
      sequence: [],
      mapping: [],
      fallback: []
    }
  }
  function collectType (type) {
    if (type.multi) {
      result.multi[type.kind].push(type)
      result.multi['fallback'].push(type)
    } else {
      result[type.kind][type.tag] = result['fallback'][type.tag] = type
    }
  }

  for (let index = 0, length = arguments.length; index < length; index += 1) {
    arguments[index].forEach(collectType)
  }
  return result
}

function Schema (definition) {
  return this.extend(definition)
}

Schema.prototype.extend = function extend (definition) {
  let implicit = []
  let explicit = []

  if (definition instanceof Type) {
    // Schema.extend(type)
    explicit.push(definition)
  } else if (Array.isArray(definition)) {
    // Schema.extend([ type1, type2, ... ])
    explicit = explicit.concat(definition)
  } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {
    // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] })
    if (definition.implicit) implicit = implicit.concat(definition.implicit)
    if (definition.explicit) explicit = explicit.concat(definition.explicit)
  } else {
    throw new YAMLException('Schema.extend argument should be a Type, [ Type ], ' +
      'or a schema definition ({ implicit: [...], explicit: [...] })')
  }

  implicit.forEach(function (type) {
    if (!(type instanceof Type)) {
      throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')
    }

    if (type.loadKind && type.loadKind !== 'scalar') {
      throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.')
    }

    if (type.multi) {
      throw new YAMLException('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.')
    }
  })

  explicit.forEach(function (type) {
    if (!(type instanceof Type)) {
      throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')
    }
  })

  const result = Object.create(Schema.prototype)

  result.implicit = (this.implicit || []).concat(implicit)
  result.explicit = (this.explicit || []).concat(explicit)

  result.compiledImplicit = compileList(result, 'implicit')
  result.compiledExplicit = compileList(result, 'explicit')
  result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit)

  return result
}

module.exports = Schema
'use strict'

const common = require('./common')

// get snippet for a single line, respecting maxLength
function getLine (buffer, lineStart, lineEnd, position, maxLineLength) {
  let head = ''
  let tail = ''
  const maxHalfLength = Math.floor(maxLineLength / 2) - 1

  if (position - lineStart > maxHalfLength) {
    head = ' ... '
    lineStart = position - maxHalfLength + head.length
  }

  if (lineEnd - position > maxHalfLength) {
    tail = ' ...'
    lineEnd = position + maxHalfLength - tail.length
  }

  return {
    str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, '→') + tail,
    pos: position - lineStart + head.length // relative position
  }
}

function padStart (string, max) {
  return common.repeat(' ', max - string.length) + string
}

function makeSnippet (mark, options) {
  options = Object.create(options || null)

  if (!mark.buffer) return null

  if (!options.maxLength) options.maxLength = 79
  if (typeof options.indent !== 'number') options.indent = 1
  if (typeof options.linesBefore !== 'number') options.linesBefore = 3
  if (typeof options.linesAfter !== 'number') options.linesAfter = 2

  const re = /\r?\n|\r|\0/g
  const lineStarts = [0]
  const lineEnds = []
  let match
  let foundLineNo = -1

  while ((match = re.exec(mark.buffer))) {
    lineEnds.push(match.index)
    lineStarts.push(match.index + match[0].length)

    if (mark.position <= match.index && foundLineNo < 0) {
      foundLineNo = lineStarts.length - 2
    }
  }

  if (foundLineNo < 0) foundLineNo = lineStarts.length - 1

  let result = ''
  const lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length
  const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3)

  for (let i = 1; i <= options.linesBefore; i++) {
    if (foundLineNo - i < 0) break
    const line = getLine(
      mark.buffer,
      lineStarts[foundLineNo - i],
      lineEnds[foundLineNo - i],
      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
      maxLineLength
    )
    result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) +
      ' | ' + line.str + '\n' + result
  }

  const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength)
  result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) +
    ' | ' + line.str + '\n'
  result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\n'

  for (let i = 1; i <= options.linesAfter; i++) {
    if (foundLineNo + i >= lineEnds.length) break
    const line = getLine(
      mark.buffer,
      lineStarts[foundLineNo + i],
      lineEnds[foundLineNo + i],
      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
      maxLineLength
    )
    result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) +
      ' | ' + line.str + '\n'
  }

  return result.replace(/\n$/, '')
}

module.exports = makeSnippet
'use strict'

const YAMLException = require('./exception')

const TYPE_CONSTRUCTOR_OPTIONS = [
  'kind',
  'multi',
  'resolve',
  'construct',
  'instanceOf',
  'predicate',
  'represent',
  'representName',
  'defaultStyle',
  'styleAliases'
]

const YAML_NODE_KINDS = [
  'scalar',
  'sequence',
  'mapping'
]

function compileStyleAliases (map) {
  const result = {}

  if (map !== null) {
    Object.keys(map).forEach(function (style) {
      map[style].forEach(function (alias) {
        result[String(alias)] = style
      })
    })
  }

  return result
}

function Type (tag, options) {
  options = options || {}

  Object.keys(options).forEach(function (name) {
    if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
      throw new YAMLException('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.')
    }
  })

  // TODO: Add tag format check.
  this.options = options // keep original options in case user wants to extend this type later
  this.tag = tag
  this.kind = options['kind'] || null
  this.resolve = options['resolve'] || function () { return true }
  this.construct = options['construct'] || function (data) { return data }
  this.instanceOf = options['instanceOf'] || null
  this.predicate = options['predicate'] || null
  this.represent = options['represent'] || null
  this.representName = options['representName'] || null
  this.defaultStyle = options['defaultStyle'] || null
  this.multi = options['multi'] || false
  this.styleAliases = compileStyleAliases(options['styleAliases'] || null)

  if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
    throw new YAMLException('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.')
  }
}

module.exports = Type
'use strict'

const Type = require('../type')

// [ 64, 65, 66 ] -> [ padding, CR, LF ]
const BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r'

function resolveYamlBinary (data) {
  if (data === null) return false

  let bitlen = 0
  const max = data.length
  const map = BASE64_MAP

  // Convert one by one.
  for (let idx = 0; idx < max; idx++) {
    const code = map.indexOf(data.charAt(idx))

    // Skip CR/LF
    if (code > 64) continue

    // Fail on illegal characters
    if (code < 0) return false

    bitlen += 6
  }

  // If there are any bits left, source was corrupted
  return (bitlen % 8) === 0
}

function constructYamlBinary (data) {
  const input = data.replace(/[\r\n=]/g, '') // remove CR/LF & padding to simplify scan
  const max = input.length
  const map = BASE64_MAP
  let bits = 0
  const result = []

  // Collect by 6*4 bits (3 bytes)

  for (let idx = 0; idx < max; idx++) {
    if ((idx % 4 === 0) && idx) {
      result.push((bits >> 16) & 0xFF)
      result.push((bits >> 8) & 0xFF)
      result.push(bits & 0xFF)
    }

    bits = (bits << 6) | map.indexOf(input.charAt(idx))
  }

  // Dump tail

  const tailbits = (max % 4) * 6

  if (tailbits === 0) {
    result.push((bits >> 16) & 0xFF)
    result.push((bits >> 8) & 0xFF)
    result.push(bits & 0xFF)
  } else if (tailbits === 18) {
    result.push((bits >> 10) & 0xFF)
    result.push((bits >> 2) & 0xFF)
  } else if (tailbits === 12) {
    result.push((bits >> 4) & 0xFF)
  }

  return new Uint8Array(result)
}

function representYamlBinary (object /*, style */) {
  let result = ''
  let bits = 0
  const max = object.length
  const map = BASE64_MAP

  // Convert every three bytes to 4 ASCII characters.

  for (let idx = 0; idx < max; idx++) {
    if ((idx % 3 === 0) && idx) {
      result += map[(bits >> 18) & 0x3F]
      result += map[(bits >> 12) & 0x3F]
      result += map[(bits >> 6) & 0x3F]
      result += map[bits & 0x3F]
    }

    bits = (bits << 8) + object[idx]
  }

  // Dump tail

  const tail = max % 3

  if (tail === 0) {
    result += map[(bits >> 18) & 0x3F]
    result += map[(bits >> 12) & 0x3F]
    result += map[(bits >> 6) & 0x3F]
    result += map[bits & 0x3F]
  } else if (tail === 2) {
    result += map[(bits >> 10) & 0x3F]
    result += map[(bits >> 4) & 0x3F]
    result += map[(bits << 2) & 0x3F]
    result += map[64]
  } else if (tail === 1) {
    result += map[(bits >> 2) & 0x3F]
    result += map[(bits << 4) & 0x3F]
    result += map[64]
    result += map[64]
  }

  return result
}

function isBinary (obj) {
  return Object.prototype.toString.call(obj) === '[object Uint8Array]'
}

module.exports = new Type('tag:yaml.org,2002:binary', {
  kind: 'scalar',
  resolve: resolveYamlBinary,
  construct: constructYamlBinary,
  predicate: isBinary,
  represent: representYamlBinary
})
'use strict'

const Type = require('../type')

function resolveYamlBoolean (data) {
  if (data === null) return false

  const max = data.length

  return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||
         (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'))
}

function constructYamlBoolean (data) {
  return data === 'true' ||
         data === 'True' ||
         data === 'TRUE'
}

function isBoolean (object) {
  return Object.prototype.toString.call(object) === '[object Boolean]'
}

module.exports = new Type('tag:yaml.org,2002:bool', {
  kind: 'scalar',
  resolve: resolveYamlBoolean,
  construct: constructYamlBoolean,
  predicate: isBoolean,
  represent: {
    lowercase: function (object) { return object ? 'true' : 'false' },
    uppercase: function (object) { return object ? 'TRUE' : 'FALSE' },
    camelcase: function (object) { return object ? 'True' : 'False' }
  },
  defaultStyle: 'lowercase'
})
'use strict'

const common = require('../common')
const Type = require('../type')

const YAML_FLOAT_PATTERN = new RegExp(
  // 2.5e4, 2.5 and integers
  '^(?:[-+]?(?:[0-9]+)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?' +
  // .2e4, .2
  // special case, seems not from spec
  '|\\.[0-9]+(?:[eE][-+]?[0-9]+)?' +
  // .inf
  '|[-+]?\\.(?:inf|Inf|INF)' +
  // .nan
  '|\\.(?:nan|NaN|NAN))$')

const YAML_FLOAT_SPECIAL_PATTERN = new RegExp(
  '^(?:' +
  // .inf
  '[-+]?\\.(?:inf|Inf|INF)' +
  // .nan
  '|\\.(?:nan|NaN|NAN))$')

function resolveYamlFloat (data) {
  if (data === null) return false

  if (!YAML_FLOAT_PATTERN.test(data)) {
    return false
  }

  if (isFinite(parseFloat(data, 10))) {
    return true
  }

  return YAML_FLOAT_SPECIAL_PATTERN.test(data)
}

function constructYamlFloat (data) {
  let value = data.toLowerCase()
  const sign = value[0] === '-' ? -1 : 1

  if ('+-'.indexOf(value[0]) >= 0) {
    value = value.slice(1)
  }

  if (value === '.inf') {
    return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY
  } else if (value === '.nan') {
    return NaN
  }
  return sign * parseFloat(value, 10)
}

const SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/

function representYamlFloat (object, style) {
  if (isNaN(object)) {
    switch (style) {
      case 'lowercase': return '.nan'
      case 'uppercase': return '.NAN'
      case 'camelcase': return '.NaN'
    }
  } else if (Number.POSITIVE_INFINITY === object) {
    switch (style) {
      case 'lowercase': return '.inf'
      case 'uppercase': return '.INF'
      case 'camelcase': return '.Inf'
    }
  } else if (Number.NEGATIVE_INFINITY === object) {
    switch (style) {
      case 'lowercase': return '-.inf'
      case 'uppercase': return '-.INF'
      case 'camelcase': return '-.Inf'
    }
  } else if (common.isNegativeZero(object)) {
    return '-0.0'
  }

  const res = object.toString(10)

  // JS stringifier can build scientific format without dots: 5e-100,
  // while YAML requres dot: 5.e-100. Fix it with simple hack

  return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res
}

function isFloat (object) {
  return (Object.prototype.toString.call(object) === '[object Number]') &&
         (object % 1 !== 0 || common.isNegativeZero(object))
}

module.exports = new Type('tag:yaml.org,2002:float', {
  kind: 'scalar',
  resolve: resolveYamlFloat,
  construct: constructYamlFloat,
  predicate: isFloat,
  represent: representYamlFloat,
  defaultStyle: 'lowercase'
})
'use strict'

const common = require('../common')
const Type = require('../type')

function isHexCode (c) {
  return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) ||
         ((c >= 0x41/* A */) && (c <= 0x46/* F */)) ||
         ((c >= 0x61/* a */) && (c <= 0x66/* f */))
}

function isOctCode (c) {
  return ((c >= 0x30/* 0 */) && (c <= 0x37/* 7 */))
}

function isDecCode (c) {
  return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */))
}

function resolveYamlInteger (data) {
  if (data === null) return false

  const max = data.length
  let index = 0
  let hasDigits = false

  if (!max) return false

  let ch = data[index]

  // sign
  if (ch === '-' || ch === '+') {
    ch = data[++index]
  }

  if (ch === '0') {
    // 0
    if (index + 1 === max) return true
    ch = data[++index]

    // base 2, base 8, base 16

    if (ch === 'b') {
      // base 2
      index++

      for (; index < max; index++) {
        ch = data[index]
        if (ch !== '0' && ch !== '1') return false
        hasDigits = true
      }
      return hasDigits && isFinite(parseYamlInteger(data))
    }

    if (ch === 'x') {
      // base 16
      index++

      for (; index < max; index++) {
        if (!isHexCode(data.charCodeAt(index))) return false
        hasDigits = true
      }
      return hasDigits && isFinite(parseYamlInteger(data))
    }

    if (ch === 'o') {
      // base 8
      index++

      for (; index < max; index++) {
        if (!isOctCode(data.charCodeAt(index))) return false
        hasDigits = true
      }
      return hasDigits && isFinite(parseYamlInteger(data))
    }
  }

  // base 10 (except 0)

  for (; index < max; index++) {
    if (!isDecCode(data.charCodeAt(index))) {
      return false
    }
    hasDigits = true
  }

  if (!hasDigits) return false

  return isFinite(parseYamlInteger(data))
}

function parseYamlInteger (data) {
  let value = data
  let sign = 1

  let ch = value[0]

  if (ch === '-' || ch === '+') {
    if (ch === '-') sign = -1
    value = value.slice(1)
    ch = value[0]
  }

  if (value === '0') return 0

  if (ch === '0') {
    if (value[1] === 'b') return sign * parseInt(value.slice(2), 2)
    if (value[1] === 'x') return sign * parseInt(value.slice(2), 16)
    if (value[1] === 'o') return sign * parseInt(value.slice(2), 8)
  }

  return sign * parseInt(value, 10)
}

function constructYamlInteger (data) {
  return parseYamlInteger(data)
}

function isInteger (object) {
  return (Object.prototype.toString.call(object)) === '[object Number]' &&
         (object % 1 === 0 && !common.isNegativeZero(object))
}

module.exports = new Type('tag:yaml.org,2002:int', {
  kind: 'scalar',
  resolve: resolveYamlInteger,
  construct: constructYamlInteger,
  predicate: isInteger,
  represent: {
    binary: function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1) },
    octal: function (obj) { return obj >= 0 ? '0o' + obj.toString(8) : '-0o' + obj.toString(8).slice(1) },
    decimal: function (obj) { return obj.toString(10) },
    hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() : '-0x' + obj.toString(16).toUpperCase().slice(1) }
  },
  defaultStyle: 'decimal',
  styleAliases: {
    binary: [2, 'bin'],
    octal: [8, 'oct'],
    decimal: [10, 'dec'],
    hexadecimal: [16, 'hex']
  }
})
'use strict'

const Type = require('../type')

module.exports = new Type('tag:yaml.org,2002:map', {
  kind: 'mapping',
  construct: function (data) { return data !== null ? data : {} }
})
'use strict'

const Type = require('../type')

function resolveYamlMerge (data) {
  return data === '<<' || data === null
}

module.exports = new Type('tag:yaml.org,2002:merge', {
  kind: 'scalar',
  resolve: resolveYamlMerge
})
'use strict'

const Type = require('../type')

function resolveYamlNull (data) {
  if (data === null) return true

  const max = data.length

  return (max === 1 && data === '~') ||
         (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'))
}

function constructYamlNull () {
  return null
}

function isNull (object) {
  return object === null
}

module.exports = new Type('tag:yaml.org,2002:null', {
  kind: 'scalar',
  resolve: resolveYamlNull,
  construct: constructYamlNull,
  predicate: isNull,
  represent: {
    canonical: function () { return '~' },
    lowercase: function () { return 'null' },
    uppercase: function () { return 'NULL' },
    camelcase: function () { return 'Null' },
    empty: function () { return '' }
  },
  defaultStyle: 'lowercase'
})
'use strict'

const Type = require('../type')

const _hasOwnProperty = Object.prototype.hasOwnProperty
const _toString = Object.prototype.toString

function resolveYamlOmap (data) {
  if (data === null) return true

  const objectKeys = {}
  const object = data

  for (let index = 0, length = object.length; index < length; index += 1) {
    const pair = object[index]
    let pairHasKey = false

    if (_toString.call(pair) !== '[object Object]') return false

    let pairKey
    for (pairKey in pair) {
      if (_hasOwnProperty.call(pair, pairKey)) {
        if (!pairHasKey) pairHasKey = true
        else return false
      }
    }

    if (!pairHasKey) return false

    if (_hasOwnProperty.call(objectKeys, pairKey)) return false
    Object.defineProperty(objectKeys, pairKey, { value: true })
  }

  return true
}

function constructYamlOmap (data) {
  return data !== null ? data : []
}

module.exports = new Type('tag:yaml.org,2002:omap', {
  kind: 'sequence',
  resolve: resolveYamlOmap,
  construct: constructYamlOmap
})
'use strict'

const Type = require('../type')

const _toString = Object.prototype.toString

function resolveYamlPairs (data) {
  if (data === null) return true

  const object = data

  const result = new Array(object.length)

  for (let index = 0, length = object.length; index < length; index += 1) {
    const pair = object[index]

    if (_toString.call(pair) !== '[object Object]') return false

    const keys = Object.keys(pair)

    if (keys.length !== 1) return false

    result[index] = [keys[0], pair[keys[0]]]
  }

  return true
}

function constructYamlPairs (data) {
  if (data === null) return []

  const object = data
  const result = new Array(object.length)

  for (let index = 0, length = object.length; index < length; index += 1) {
    const pair = object[index]

    const keys = Object.keys(pair)

    result[index] = [keys[0], pair[keys[0]]]
  }

  return result
}

module.exports = new Type('tag:yaml.org,2002:pairs', {
  kind: 'sequence',
  resolve: resolveYamlPairs,
  construct: constructYamlPairs
})
'use strict'

const Type = require('../type')

module.exports = new Type('tag:yaml.org,2002:seq', {
  kind: 'sequence',
  construct: function (data) { return data !== null ? data : [] }
})
'use strict'

const Type = require('../type')

const _hasOwnProperty = Object.prototype.hasOwnProperty

function resolveYamlSet (data) {
  if (data === null) return true

  const object = data

  for (const key in object) {
    if (_hasOwnProperty.call(object, key)) {
      if (object[key] !== null) return false
    }
  }

  return true
}

function constructYamlSet (data) {
  return data !== null ? data : {}
}

module.exports = new Type('tag:yaml.org,2002:set', {
  kind: 'mapping',
  resolve: resolveYamlSet,
  construct: constructYamlSet
})
'use strict'

const Type = require('../type')

module.exports = new Type('tag:yaml.org,2002:str', {
  kind: 'scalar',
  construct: function (data) { return data !== null ? data : '' }
})
'use strict'

const Type = require('../type')

const YAML_DATE_REGEXP = new RegExp(
  '^([0-9][0-9][0-9][0-9])' + // [1] year
  '-([0-9][0-9])' + // [2] month
  '-([0-9][0-9])$')                   // [3] day

const YAML_TIMESTAMP_REGEXP = new RegExp(
  '^([0-9][0-9][0-9][0-9])' + // [1] year
  '-([0-9][0-9]?)' + // [2] month
  '-([0-9][0-9]?)' + // [3] day
  '(?:[Tt]|[ \\t]+)' + // ...
  '([0-9][0-9]?)' + // [4] hour
  ':([0-9][0-9])' + // [5] minute
  ':([0-9][0-9])' + // [6] second
  '(?:\\.([0-9]*))?' + // [7] fraction
  '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tzHour
  '(?::([0-9][0-9]))?))?$')           // [11] tzMinute

function resolveYamlTimestamp (data) {
  if (data === null) return false
  if (YAML_DATE_REGEXP.exec(data) !== null) return true
  if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true
  return false
}

function constructYamlTimestamp (data) {
  let fraction = 0
  let delta = null

  let match = YAML_DATE_REGEXP.exec(data)
  if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data)

  if (match === null) throw new Error('Date resolve error')

  // match: [1] year [2] month [3] day

  const year = +(match[1])
  const month = +(match[2]) - 1 // JS month starts with 0
  const day = +(match[3])

  if (!match[4]) { // no hour
    return new Date(Date.UTC(year, month, day))
  }

  // match: [4] hour [5] minute [6] second [7] fraction

  const hour = +(match[4])
  const minute = +(match[5])
  const second = +(match[6])

  if (match[7]) {
    fraction = match[7].slice(0, 3)
    while (fraction.length < 3) { // milli-seconds
      fraction += '0'
    }
    fraction = +fraction
  }

  // match: [8] tz [9] tz_sign [10] tzHour [11] tzMinute

  if (match[9]) {
    const tzHour = +(match[10])
    const tzMinute = +(match[11] || 0)
    delta = (tzHour * 60 + tzMinute) * 60000 // delta in mili-seconds
    if (match[9] === '-') delta = -delta
  }

  const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction))

  if (delta) date.setTime(date.getTime() - delta)

  return date
}

function representYamlTimestamp (object /*, style */) {
  return object.toISOString()
}

module.exports = new Type('tag:yaml.org,2002:timestamp', {
  kind: 'scalar',
  resolve: resolveYamlTimestamp,
  construct: constructYamlTimestamp,
  instanceOf: Date,
  represent: representYamlTimestamp
})
// Standard YAML's Core schema.
// http://www.yaml.org/spec/1.2/spec.html#id2804923
//
// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
// So, Core schema has no distinctions from JSON schema is JS-YAML.

'use strict'

module.exports = require('./json')
// JS-YAML's default schema for `safeLoad` function.
// It is not described in the YAML specification.
//
// This schema is based on standard YAML's Core schema and includes most of
// extra types described at YAML tag repository. (http://yaml.org/type/)

'use strict'

module.exports = require('./core').extend({
  implicit: [
    require('../type/timestamp'),
    require('../type/merge')
  ],
  explicit: [
    require('../type/binary'),
    require('../type/omap'),
    require('../type/pairs'),
    require('../type/set')
  ]
})
// Standard YAML's Failsafe schema.
// http://www.yaml.org/spec/1.2/spec.html#id2802346

'use strict'

const Schema = require('../schema')

module.exports = new Schema({
  explicit: [
    require('../type/str'),
    require('../type/seq'),
    require('../type/map')
  ]
})
// Standard YAML's JSON schema.
// http://www.yaml.org/spec/1.2/spec.html#id2803231
//
// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
// So, this schema is not such strict as defined in the YAML specification.
// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.

'use strict'

module.exports = require('./failsafe').extend({
  implicit: [
    require('../type/null'),
    require('../type/bool'),
    require('../type/int'),
    require('../type/float')
  ]
})
(function(global, factory) {
    typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, 
    factory(global.jsyaml = {}));
})(this, function(exports2) {
    "use strict";
    function getDefaultExportFromCjs(x) {
        return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
    }
    var jsYaml = {};
    var loader = {};
    var common = {};
    var hasRequiredCommon;
    function requireCommon() {
        if (hasRequiredCommon) return common;
        hasRequiredCommon = 1;
        function _typeof(o) {
            "@babel/helpers - typeof";
            return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
                return typeof o2;
            } : function(o2) {
                return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2;
            }, _typeof(o);
        }
        function isNothing(subject) {
            return typeof subject === "undefined" || subject === null;
        }
        function isObject(subject) {
            return _typeof(subject) === "object" && subject !== null;
        }
        function toArray(sequence) {
            if (Array.isArray(sequence)) return sequence; else if (isNothing(sequence)) return [];
            return [ sequence ];
        }
        function extend(target, source) {
            if (source) {
                var sourceKeys = Object.keys(source);
                for (var index = 0, length = sourceKeys.length; index < length; index += 1) {
                    var key = sourceKeys[index];
                    target[key] = source[key];
                }
            }
            return target;
        }
        function repeat(string, count) {
            var result = "";
            for (var cycle = 0; cycle < count; cycle += 1) {
                result += string;
            }
            return result;
        }
        function isNegativeZero(number) {
            return number === 0 && Number.NEGATIVE_INFINITY === 1 / number;
        }
        common.isNothing = isNothing;
        common.isObject = isObject;
        common.toArray = toArray;
        common.repeat = repeat;
        common.isNegativeZero = isNegativeZero;
        common.extend = extend;
        return common;
    }
    var exception;
    var hasRequiredException;
    function requireException() {
        if (hasRequiredException) return exception;
        hasRequiredException = 1;
        function formatError(exception2, compact) {
            var where = "";
            var message = exception2.reason || "(unknown reason)";
            if (!exception2.mark) return message;
            if (exception2.mark.name) {
                where += 'in "' + exception2.mark.name + '" ';
            }
            where += "(" + (exception2.mark.line + 1) + ":" + (exception2.mark.column + 1) + ")";
            if (!compact && exception2.mark.snippet) {
                where += "\n\n" + exception2.mark.snippet;
            }
            return message + " " + where;
        }
        function YAMLException2(reason, mark) {
            Error.call(this);
            this.name = "YAMLException";
            this.reason = reason;
            this.mark = mark;
            this.message = formatError(this, false);
            if (Error.captureStackTrace) {
                Error.captureStackTrace(this, this.constructor);
            } else {
                this.stack = (new Error).stack || "";
            }
        }
        YAMLException2.prototype = Object.create(Error.prototype);
        YAMLException2.prototype.constructor = YAMLException2;
        YAMLException2.prototype.toString = function toString(compact) {
            return this.name + ": " + formatError(this, compact);
        };
        exception = YAMLException2;
        return exception;
    }
    var snippet;
    var hasRequiredSnippet;
    function requireSnippet() {
        if (hasRequiredSnippet) return snippet;
        hasRequiredSnippet = 1;
        var common2 = requireCommon();
        function getLine(buffer, lineStart, lineEnd, position, maxLineLength) {
            var head = "";
            var tail = "";
            var maxHalfLength = Math.floor(maxLineLength / 2) - 1;
            if (position - lineStart > maxHalfLength) {
                head = " ... ";
                lineStart = position - maxHalfLength + head.length;
            }
            if (lineEnd - position > maxHalfLength) {
                tail = " ...";
                lineEnd = position + maxHalfLength - tail.length;
            }
            return {
                str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "→") + tail,
                pos: position - lineStart + head.length
            };
        }
        function padStart(string, max) {
            return common2.repeat(" ", max - string.length) + string;
        }
        function makeSnippet(mark, options) {
            options = Object.create(options || null);
            if (!mark.buffer) return null;
            if (!options.maxLength) options.maxLength = 79;
            if (typeof options.indent !== "number") options.indent = 1;
            if (typeof options.linesBefore !== "number") options.linesBefore = 3;
            if (typeof options.linesAfter !== "number") options.linesAfter = 2;
            var re = /\r?\n|\r|\0/g;
            var lineStarts = [ 0 ];
            var lineEnds = [];
            var match;
            var foundLineNo = -1;
            while (match = re.exec(mark.buffer)) {
                lineEnds.push(match.index);
                lineStarts.push(match.index + match[0].length);
                if (mark.position <= match.index && foundLineNo < 0) {
                    foundLineNo = lineStarts.length - 2;
                }
            }
            if (foundLineNo < 0) foundLineNo = lineStarts.length - 1;
            var result = "";
            var lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length;
            var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);
            for (var i = 1; i <= options.linesBefore; i++) {
                if (foundLineNo - i < 0) break;
                var _line = getLine(mark.buffer, lineStarts[foundLineNo - i], lineEnds[foundLineNo - i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]), maxLineLength);
                result = common2.repeat(" ", options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) + " | " + _line.str + "\n" + result;
            }
            var line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength);
            result += common2.repeat(" ", options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + " | " + line.str + "\n";
            result += common2.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n";
            for (var _i = 1; _i <= options.linesAfter; _i++) {
                if (foundLineNo + _i >= lineEnds.length) break;
                var _line2 = getLine(mark.buffer, lineStarts[foundLineNo + _i], lineEnds[foundLineNo + _i], mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + _i]), maxLineLength);
                result += common2.repeat(" ", options.indent) + padStart((mark.line + _i + 1).toString(), lineNoLength) + " | " + _line2.str + "\n";
            }
            return result.replace(/\n$/, "");
        }
        snippet = makeSnippet;
        return snippet;
    }
    var type;
    var hasRequiredType;
    function requireType() {
        if (hasRequiredType) return type;
        hasRequiredType = 1;
        var YAMLException2 = requireException();
        var TYPE_CONSTRUCTOR_OPTIONS = [ "kind", "multi", "resolve", "construct", "instanceOf", "predicate", "represent", "representName", "defaultStyle", "styleAliases" ];
        var YAML_NODE_KINDS = [ "scalar", "sequence", "mapping" ];
        function compileStyleAliases(map2) {
            var result = {};
            if (map2 !== null) {
                Object.keys(map2).forEach(function(style) {
                    map2[style].forEach(function(alias) {
                        result[String(alias)] = style;
                    });
                });
            }
            return result;
        }
        function Type2(tag, options) {
            options = options || {};
            Object.keys(options).forEach(function(name) {
                if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
                    throw new YAMLException2('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
                }
            });
            this.options = options;
            this.tag = tag;
            this.kind = options["kind"] || null;
            this.resolve = options["resolve"] || function() {
                return true;
            };
            this.construct = options["construct"] || function(data) {
                return data;
            };
            this.instanceOf = options["instanceOf"] || null;
            this.predicate = options["predicate"] || null;
            this.represent = options["represent"] || null;
            this.representName = options["representName"] || null;
            this.defaultStyle = options["defaultStyle"] || null;
            this.multi = options["multi"] || false;
            this.styleAliases = compileStyleAliases(options["styleAliases"] || null);
            if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
                throw new YAMLException2('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
            }
        }
        type = Type2;
        return type;
    }
    var schema;
    var hasRequiredSchema;
    function requireSchema() {
        if (hasRequiredSchema) return schema;
        hasRequiredSchema = 1;
        var YAMLException2 = requireException();
        var Type2 = requireType();
        function compileList(schema2, name) {
            var result = [];
            schema2[name].forEach(function(currentType) {
                var newIndex = result.length;
                result.forEach(function(previousType, previousIndex) {
                    if (previousType.tag === currentType.tag && previousType.kind === currentType.kind && previousType.multi === currentType.multi) {
                        newIndex = previousIndex;
                    }
                });
                result[newIndex] = currentType;
            });
            return result;
        }
        function compileMap() {
            var result = {
                scalar: {},
                sequence: {},
                mapping: {},
                fallback: {},
                multi: {
                    scalar: [],
                    sequence: [],
                    mapping: [],
                    fallback: []
                }
            };
            function collectType(type2) {
                if (type2.multi) {
                    result.multi[type2.kind].push(type2);
                    result.multi["fallback"].push(type2);
                } else {
                    result[type2.kind][type2.tag] = result["fallback"][type2.tag] = type2;
                }
            }
            for (var index = 0, length = arguments.length; index < length; index += 1) {
                arguments[index].forEach(collectType);
            }
            return result;
        }
        function Schema2(definition) {
            return this.extend(definition);
        }
        Schema2.prototype.extend = function extend(definition) {
            var implicit = [];
            var explicit = [];
            if (definition instanceof Type2) {
                explicit.push(definition);
            } else if (Array.isArray(definition)) {
                explicit = explicit.concat(definition);
            } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {
                if (definition.implicit) implicit = implicit.concat(definition.implicit);
                if (definition.explicit) explicit = explicit.concat(definition.explicit);
            } else {
                throw new YAMLException2("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");
            }
            implicit.forEach(function(type2) {
                if (!(type2 instanceof Type2)) {
                    throw new YAMLException2("Specified list of YAML types (or a single Type object) contains a non-Type object.");
                }
                if (type2.loadKind && type2.loadKind !== "scalar") {
                    throw new YAMLException2("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");
                }
                if (type2.multi) {
                    throw new YAMLException2("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.");
                }
            });
            explicit.forEach(function(type2) {
                if (!(type2 instanceof Type2)) {
                    throw new YAMLException2("Specified list of YAML types (or a single Type object) contains a non-Type object.");
                }
            });
            var result = Object.create(Schema2.prototype);
            result.implicit = (this.implicit || []).concat(implicit);
            result.explicit = (this.explicit || []).concat(explicit);
            result.compiledImplicit = compileList(result, "implicit");
            result.compiledExplicit = compileList(result, "explicit");
            result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit);
            return result;
        };
        schema = Schema2;
        return schema;
    }
    var str;
    var hasRequiredStr;
    function requireStr() {
        if (hasRequiredStr) return str;
        hasRequiredStr = 1;
        var Type2 = requireType();
        str = new Type2("tag:yaml.org,2002:str", {
            kind: "scalar",
            construct: function construct(data) {
                return data !== null ? data : "";
            }
        });
        return str;
    }
    var seq;
    var hasRequiredSeq;
    function requireSeq() {
        if (hasRequiredSeq) return seq;
        hasRequiredSeq = 1;
        var Type2 = requireType();
        seq = new Type2("tag:yaml.org,2002:seq", {
            kind: "sequence",
            construct: function construct(data) {
                return data !== null ? data : [];
            }
        });
        return seq;
    }
    var map;
    var hasRequiredMap;
    function requireMap() {
        if (hasRequiredMap) return map;
        hasRequiredMap = 1;
        var Type2 = requireType();
        map = new Type2("tag:yaml.org,2002:map", {
            kind: "mapping",
            construct: function construct(data) {
                return data !== null ? data : {};
            }
        });
        return map;
    }
    var failsafe;
    var hasRequiredFailsafe;
    function requireFailsafe() {
        if (hasRequiredFailsafe) return failsafe;
        hasRequiredFailsafe = 1;
        var Schema2 = requireSchema();
        failsafe = new Schema2({
            explicit: [ requireStr(), requireSeq(), requireMap() ]
        });
        return failsafe;
    }
    var _null;
    var hasRequired_null;
    function require_null() {
        if (hasRequired_null) return _null;
        hasRequired_null = 1;
        var Type2 = requireType();
        function resolveYamlNull(data) {
            if (data === null) return true;
            var max = data.length;
            return max === 1 && data === "~" || max === 4 && (data === "null" || data === "Null" || data === "NULL");
        }
        function constructYamlNull() {
            return null;
        }
        function isNull(object) {
            return object === null;
        }
        _null = new Type2("tag:yaml.org,2002:null", {
            kind: "scalar",
            resolve: resolveYamlNull,
            construct: constructYamlNull,
            predicate: isNull,
            represent: {
                canonical: function canonical() {
                    return "~";
                },
                lowercase: function lowercase() {
                    return "null";
                },
                uppercase: function uppercase() {
                    return "NULL";
                },
                camelcase: function camelcase() {
                    return "Null";
                },
                empty: function empty() {
                    return "";
                }
            },
            defaultStyle: "lowercase"
        });
        return _null;
    }
    var bool;
    var hasRequiredBool;
    function requireBool() {
        if (hasRequiredBool) return bool;
        hasRequiredBool = 1;
        var Type2 = requireType();
        function resolveYamlBoolean(data) {
            if (data === null) return false;
            var max = data.length;
            return max === 4 && (data === "true" || data === "True" || data === "TRUE") || max === 5 && (data === "false" || data === "False" || data === "FALSE");
        }
        function constructYamlBoolean(data) {
            return data === "true" || data === "True" || data === "TRUE";
        }
        function isBoolean(object) {
            return Object.prototype.toString.call(object) === "[object Boolean]";
        }
        bool = new Type2("tag:yaml.org,2002:bool", {
            kind: "scalar",
            resolve: resolveYamlBoolean,
            construct: constructYamlBoolean,
            predicate: isBoolean,
            represent: {
                lowercase: function lowercase(object) {
                    return object ? "true" : "false";
                },
                uppercase: function uppercase(object) {
                    return object ? "TRUE" : "FALSE";
                },
                camelcase: function camelcase(object) {
                    return object ? "True" : "False";
                }
            },
            defaultStyle: "lowercase"
        });
        return bool;
    }
    var int;
    var hasRequiredInt;
    function requireInt() {
        if (hasRequiredInt) return int;
        hasRequiredInt = 1;
        var common2 = requireCommon();
        var Type2 = requireType();
        function isHexCode(c) {
            return c >= 48 && c <= 57 || c >= 65 && c <= 70 || c >= 97 && c <= 102;
        }
        function isOctCode(c) {
            return c >= 48 && c <= 55;
        }
        function isDecCode(c) {
            return c >= 48 && c <= 57;
        }
        function resolveYamlInteger(data) {
            if (data === null) return false;
            var max = data.length;
            var index = 0;
            var hasDigits = false;
            if (!max) return false;
            var ch = data[index];
            if (ch === "-" || ch === "+") {
                ch = data[++index];
            }
            if (ch === "0") {
                if (index + 1 === max) return true;
                ch = data[++index];
                if (ch === "b") {
                    index++;
                    for (;index < max; index++) {
                        ch = data[index];
                        if (ch !== "0" && ch !== "1") return false;
                        hasDigits = true;
                    }
                    return hasDigits && isFinite(parseYamlInteger(data));
                }
                if (ch === "x") {
                    index++;
                    for (;index < max; index++) {
                        if (!isHexCode(data.charCodeAt(index))) return false;
                        hasDigits = true;
                    }
                    return hasDigits && isFinite(parseYamlInteger(data));
                }
                if (ch === "o") {
                    index++;
                    for (;index < max; index++) {
                        if (!isOctCode(data.charCodeAt(index))) return false;
                        hasDigits = true;
                    }
                    return hasDigits && isFinite(parseYamlInteger(data));
                }
            }
            for (;index < max; index++) {
                if (!isDecCode(data.charCodeAt(index))) {
                    return false;
                }
                hasDigits = true;
            }
            if (!hasDigits) return false;
            return isFinite(parseYamlInteger(data));
        }
        function parseYamlInteger(data) {
            var value = data;
            var sign = 1;
            var ch = value[0];
            if (ch === "-" || ch === "+") {
                if (ch === "-") sign = -1;
                value = value.slice(1);
                ch = value[0];
            }
            if (value === "0") return 0;
            if (ch === "0") {
                if (value[1] === "b") return sign * parseInt(value.slice(2), 2);
                if (value[1] === "x") return sign * parseInt(value.slice(2), 16);
                if (value[1] === "o") return sign * parseInt(value.slice(2), 8);
            }
            return sign * parseInt(value, 10);
        }
        function constructYamlInteger(data) {
            return parseYamlInteger(data);
        }
        function isInteger(object) {
            return Object.prototype.toString.call(object) === "[object Number]" && object % 1 === 0 && !common2.isNegativeZero(object);
        }
        int = new Type2("tag:yaml.org,2002:int", {
            kind: "scalar",
            resolve: resolveYamlInteger,
            construct: constructYamlInteger,
            predicate: isInteger,
            represent: {
                binary: function binary2(obj) {
                    return obj >= 0 ? "0b" + obj.toString(2) : "-0b" + obj.toString(2).slice(1);
                },
                octal: function octal(obj) {
                    return obj >= 0 ? "0o" + obj.toString(8) : "-0o" + obj.toString(8).slice(1);
                },
                decimal: function decimal(obj) {
                    return obj.toString(10);
                },
                hexadecimal: function hexadecimal(obj) {
                    return obj >= 0 ? "0x" + obj.toString(16).toUpperCase() : "-0x" + obj.toString(16).toUpperCase().slice(1);
                }
            },
            defaultStyle: "decimal",
            styleAliases: {
                binary: [ 2, "bin" ],
                octal: [ 8, "oct" ],
                decimal: [ 10, "dec" ],
                hexadecimal: [ 16, "hex" ]
            }
        });
        return int;
    }
    var float;
    var hasRequiredFloat;
    function requireFloat() {
        if (hasRequiredFloat) return float;
        hasRequiredFloat = 1;
        var common2 = requireCommon();
        var Type2 = requireType();
        var YAML_FLOAT_PATTERN = new RegExp("^(?:[-+]?(?:[0-9]+)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");
        var YAML_FLOAT_SPECIAL_PATTERN = new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");
        function resolveYamlFloat(data) {
            if (data === null) return false;
            if (!YAML_FLOAT_PATTERN.test(data)) {
                return false;
            }
            if (isFinite(parseFloat(data, 10))) {
                return true;
            }
            return YAML_FLOAT_SPECIAL_PATTERN.test(data);
        }
        function constructYamlFloat(data) {
            var value = data.toLowerCase();
            var sign = value[0] === "-" ? -1 : 1;
            if ("+-".indexOf(value[0]) >= 0) {
                value = value.slice(1);
            }
            if (value === ".inf") {
                return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
            } else if (value === ".nan") {
                return NaN;
            }
            return sign * parseFloat(value, 10);
        }
        var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
        function representYamlFloat(object, style) {
            if (isNaN(object)) {
                switch (style) {
                  case "lowercase":
                    return ".nan";

                  case "uppercase":
                    return ".NAN";

                  case "camelcase":
                    return ".NaN";
                }
            } else if (Number.POSITIVE_INFINITY === object) {
                switch (style) {
                  case "lowercase":
                    return ".inf";

                  case "uppercase":
                    return ".INF";

                  case "camelcase":
                    return ".Inf";
                }
            } else if (Number.NEGATIVE_INFINITY === object) {
                switch (style) {
                  case "lowercase":
                    return "-.inf";

                  case "uppercase":
                    return "-.INF";

                  case "camelcase":
                    return "-.Inf";
                }
            } else if (common2.isNegativeZero(object)) {
                return "-0.0";
            }
            var res = object.toString(10);
            return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace("e", ".e") : res;
        }
        function isFloat(object) {
            return Object.prototype.toString.call(object) === "[object Number]" && (object % 1 !== 0 || common2.isNegativeZero(object));
        }
        float = new Type2("tag:yaml.org,2002:float", {
            kind: "scalar",
            resolve: resolveYamlFloat,
            construct: constructYamlFloat,
            predicate: isFloat,
            represent: representYamlFloat,
            defaultStyle: "lowercase"
        });
        return float;
    }
    var json;
    var hasRequiredJson;
    function requireJson() {
        if (hasRequiredJson) return json;
        hasRequiredJson = 1;
        json = requireFailsafe().extend({
            implicit: [ require_null(), requireBool(), requireInt(), requireFloat() ]
        });
        return json;
    }
    var core;
    var hasRequiredCore;
    function requireCore() {
        if (hasRequiredCore) return core;
        hasRequiredCore = 1;
        core = requireJson();
        return core;
    }
    var timestamp;
    var hasRequiredTimestamp;
    function requireTimestamp() {
        if (hasRequiredTimestamp) return timestamp;
        hasRequiredTimestamp = 1;
        var Type2 = requireType();
        var YAML_DATE_REGEXP = new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$");
        var YAML_TIMESTAMP_REGEXP = new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");
        function resolveYamlTimestamp(data) {
            if (data === null) return false;
            if (YAML_DATE_REGEXP.exec(data) !== null) return true;
            if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
            return false;
        }
        function constructYamlTimestamp(data) {
            var fraction = 0;
            var delta = null;
            var match = YAML_DATE_REGEXP.exec(data);
            if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);
            if (match === null) throw new Error("Date resolve error");
            var year = +match[1];
            var month = +match[2] - 1;
            var day = +match[3];
            if (!match[4]) {
                return new Date(Date.UTC(year, month, day));
            }
            var hour = +match[4];
            var minute = +match[5];
            var second = +match[6];
            if (match[7]) {
                fraction = match[7].slice(0, 3);
                while (fraction.length < 3) {
                    fraction += "0";
                }
                fraction = +fraction;
            }
            if (match[9]) {
                var tzHour = +match[10];
                var tzMinute = +(match[11] || 0);
                delta = (tzHour * 60 + tzMinute) * 6e4;
                if (match[9] === "-") delta = -delta;
            }
            var date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));
            if (delta) date.setTime(date.getTime() - delta);
            return date;
        }
        function representYamlTimestamp(object) {
            return object.toISOString();
        }
        timestamp = new Type2("tag:yaml.org,2002:timestamp", {
            kind: "scalar",
            resolve: resolveYamlTimestamp,
            construct: constructYamlTimestamp,
            instanceOf: Date,
            represent: representYamlTimestamp
        });
        return timestamp;
    }
    var merge;
    var hasRequiredMerge;
    function requireMerge() {
        if (hasRequiredMerge) return merge;
        hasRequiredMerge = 1;
        var Type2 = requireType();
        function resolveYamlMerge(data) {
            return data === "<<" || data === null;
        }
        merge = new Type2("tag:yaml.org,2002:merge", {
            kind: "scalar",
            resolve: resolveYamlMerge
        });
        return merge;
    }
    var binary;
    var hasRequiredBinary;
    function requireBinary() {
        if (hasRequiredBinary) return binary;
        hasRequiredBinary = 1;
        var Type2 = requireType();
        var BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";
        function resolveYamlBinary(data) {
            if (data === null) return false;
            var bitlen = 0;
            var max = data.length;
            var map2 = BASE64_MAP;
            for (var idx = 0; idx < max; idx++) {
                var code = map2.indexOf(data.charAt(idx));
                if (code > 64) continue;
                if (code < 0) return false;
                bitlen += 6;
            }
            return bitlen % 8 === 0;
        }
        function constructYamlBinary(data) {
            var input = data.replace(/[\r\n=]/g, "");
            var max = input.length;
            var map2 = BASE64_MAP;
            var bits = 0;
            var result = [];
            for (var idx = 0; idx < max; idx++) {
                if (idx % 4 === 0 && idx) {
                    result.push(bits >> 16 & 255);
                    result.push(bits >> 8 & 255);
                    result.push(bits & 255);
                }
                bits = bits << 6 | map2.indexOf(input.charAt(idx));
            }
            var tailbits = max % 4 * 6;
            if (tailbits === 0) {
                result.push(bits >> 16 & 255);
                result.push(bits >> 8 & 255);
                result.push(bits & 255);
            } else if (tailbits === 18) {
                result.push(bits >> 10 & 255);
                result.push(bits >> 2 & 255);
            } else if (tailbits === 12) {
                result.push(bits >> 4 & 255);
            }
            return new Uint8Array(result);
        }
        function representYamlBinary(object) {
            var result = "";
            var bits = 0;
            var max = object.length;
            var map2 = BASE64_MAP;
            for (var idx = 0; idx < max; idx++) {
                if (idx % 3 === 0 && idx) {
                    result += map2[bits >> 18 & 63];
                    result += map2[bits >> 12 & 63];
                    result += map2[bits >> 6 & 63];
                    result += map2[bits & 63];
                }
                bits = (bits << 8) + object[idx];
            }
            var tail = max % 3;
            if (tail === 0) {
                result += map2[bits >> 18 & 63];
                result += map2[bits >> 12 & 63];
                result += map2[bits >> 6 & 63];
                result += map2[bits & 63];
            } else if (tail === 2) {
                result += map2[bits >> 10 & 63];
                result += map2[bits >> 4 & 63];
                result += map2[bits << 2 & 63];
                result += map2[64];
            } else if (tail === 1) {
                result += map2[bits >> 2 & 63];
                result += map2[bits << 4 & 63];
                result += map2[64];
                result += map2[64];
            }
            return result;
        }
        function isBinary(obj) {
            return Object.prototype.toString.call(obj) === "[object Uint8Array]";
        }
        binary = new Type2("tag:yaml.org,2002:binary", {
            kind: "scalar",
            resolve: resolveYamlBinary,
            construct: constructYamlBinary,
            predicate: isBinary,
            represent: representYamlBinary
        });
        return binary;
    }
    var omap;
    var hasRequiredOmap;
    function requireOmap() {
        if (hasRequiredOmap) return omap;
        hasRequiredOmap = 1;
        var Type2 = requireType();
        var _hasOwnProperty = Object.prototype.hasOwnProperty;
        var _toString = Object.prototype.toString;
        function resolveYamlOmap(data) {
            if (data === null) return true;
            var objectKeys = {};
            var object = data;
            for (var index = 0, length = object.length; index < length; index += 1) {
                var pair = object[index];
                var pairHasKey = false;
                if (_toString.call(pair) !== "[object Object]") return false;
                var pairKey = void 0;
                for (pairKey in pair) {
                    if (_hasOwnProperty.call(pair, pairKey)) {
                        if (!pairHasKey) pairHasKey = true; else return false;
                    }
                }
                if (!pairHasKey) return false;
                if (_hasOwnProperty.call(objectKeys, pairKey)) return false;
                Object.defineProperty(objectKeys, pairKey, {
                    value: true
                });
            }
            return true;
        }
        function constructYamlOmap(data) {
            return data !== null ? data : [];
        }
        omap = new Type2("tag:yaml.org,2002:omap", {
            kind: "sequence",
            resolve: resolveYamlOmap,
            construct: constructYamlOmap
        });
        return omap;
    }
    var pairs;
    var hasRequiredPairs;
    function requirePairs() {
        if (hasRequiredPairs) return pairs;
        hasRequiredPairs = 1;
        var Type2 = requireType();
        var _toString = Object.prototype.toString;
        function resolveYamlPairs(data) {
            if (data === null) return true;
            var object = data;
            var result = new Array(object.length);
            for (var index = 0, length = object.length; index < length; index += 1) {
                var pair = object[index];
                if (_toString.call(pair) !== "[object Object]") return false;
                var keys = Object.keys(pair);
                if (keys.length !== 1) return false;
                result[index] = [ keys[0], pair[keys[0]] ];
            }
            return true;
        }
        function constructYamlPairs(data) {
            if (data === null) return [];
            var object = data;
            var result = new Array(object.length);
            for (var index = 0, length = object.length; index < length; index += 1) {
                var pair = object[index];
                var keys = Object.keys(pair);
                result[index] = [ keys[0], pair[keys[0]] ];
            }
            return result;
        }
        pairs = new Type2("tag:yaml.org,2002:pairs", {
            kind: "sequence",
            resolve: resolveYamlPairs,
            construct: constructYamlPairs
        });
        return pairs;
    }
    var set;
    var hasRequiredSet;
    function requireSet() {
        if (hasRequiredSet) return set;
        hasRequiredSet = 1;
        var Type2 = requireType();
        var _hasOwnProperty = Object.prototype.hasOwnProperty;
        function resolveYamlSet(data) {
            if (data === null) return true;
            var object = data;
            for (var key in object) {
                if (_hasOwnProperty.call(object, key)) {
                    if (object[key] !== null) return false;
                }
            }
            return true;
        }
        function constructYamlSet(data) {
            return data !== null ? data : {};
        }
        set = new Type2("tag:yaml.org,2002:set", {
            kind: "mapping",
            resolve: resolveYamlSet,
            construct: constructYamlSet
        });
        return set;
    }
    var _default;
    var hasRequired_default;
    function require_default() {
        if (hasRequired_default) return _default;
        hasRequired_default = 1;
        _default = requireCore().extend({
            implicit: [ requireTimestamp(), requireMerge() ],
            explicit: [ requireBinary(), requireOmap(), requirePairs(), requireSet() ]
        });
        return _default;
    }
    var hasRequiredLoader;
    function requireLoader() {
        if (hasRequiredLoader) return loader;
        hasRequiredLoader = 1;
        function _typeof(o) {
            "@babel/helpers - typeof";
            return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
                return typeof o2;
            } : function(o2) {
                return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2;
            }, _typeof(o);
        }
        var common2 = requireCommon();
        var YAMLException2 = requireException();
        var makeSnippet = requireSnippet();
        var DEFAULT_SCHEMA2 = require_default();
        var _hasOwnProperty = Object.prototype.hasOwnProperty;
        var CONTEXT_FLOW_IN = 1;
        var CONTEXT_FLOW_OUT = 2;
        var CONTEXT_BLOCK_IN = 3;
        var CONTEXT_BLOCK_OUT = 4;
        var CHOMPING_CLIP = 1;
        var CHOMPING_STRIP = 2;
        var CHOMPING_KEEP = 3;
        var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
        var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
        var PATTERN_FLOW_INDICATORS = /[,\[\]{}]/;
        var PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/;
        var PATTERN_TAG_URI = /^(?:!|[^,\[\]{}])(?:%[0-9a-f]{2}|[0-9a-z\-#;/?:@&=+$,_.!~*'()\[\]])*$/i;
        function _class(obj) {
            return Object.prototype.toString.call(obj);
        }
        function isEol(c) {
            return c === 10 || c === 13;
        }
        function isWhiteSpace(c) {
            return c === 9 || c === 32;
        }
        function isWsOrEol(c) {
            return c === 9 || c === 32 || c === 10 || c === 13;
        }
        function isFlowIndicator(c) {
            return c === 44 || c === 91 || c === 93 || c === 123 || c === 125;
        }
        function fromHexCode(c) {
            if (c >= 48 && c <= 57) {
                return c - 48;
            }
            var lc = c | 32;
            if (lc >= 97 && lc <= 102) {
                return lc - 97 + 10;
            }
            return -1;
        }
        function escapedHexLen(c) {
            if (c === 120) {
                return 2;
            }
            if (c === 117) {
                return 4;
            }
            if (c === 85) {
                return 8;
            }
            return 0;
        }
        function fromDecimalCode(c) {
            if (c >= 48 && c <= 57) {
                return c - 48;
            }
            return -1;
        }
        function simpleEscapeSequence(c) {
            switch (c) {
              case 48:
                return "\0";

              case 97:
                return "";

              case 98:
                return "\b";

              case 116:
                return "\t";

              case 9:
                return "\t";

              case 110:
                return "\n";

              case 118:
                return "\v";

              case 102:
                return "\f";

              case 114:
                return "\r";

              case 101:
                return "";

              case 32:
                return " ";

              case 34:
                return '"';

              case 47:
                return "/";

              case 92:
                return "\\";

              case 78:
                return "";

              case 95:
                return " ";

              case 76:
                return "\u2028";

              case 80:
                return "\u2029";

              default:
                return "";
            }
        }
        function charFromCodepoint(c) {
            if (c <= 65535) {
                return String.fromCharCode(c);
            }
            return String.fromCharCode((c - 65536 >> 10) + 55296, (c - 65536 & 1023) + 56320);
        }
        function setProperty(object, key, value) {
            if (key === "__proto__") {
                Object.defineProperty(object, key, {
                    configurable: true,
                    enumerable: true,
                    writable: true,
                    value: value
                });
            } else {
                object[key] = value;
            }
        }
        var simpleEscapeCheck = new Array(256);
        var simpleEscapeMap = new Array(256);
        for (var i = 0; i < 256; i++) {
            simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;
            simpleEscapeMap[i] = simpleEscapeSequence(i);
        }
        function State(input, options) {
            this.input = input;
            this.filename = options["filename"] || null;
            this.schema = options["schema"] || DEFAULT_SCHEMA2;
            this.onWarning = options["onWarning"] || null;
            this.legacy = options["legacy"] || false;
            this.json = options["json"] || false;
            this.listener = options["listener"] || null;
            this.maxDepth = typeof options["maxDepth"] === "number" ? options["maxDepth"] : 100;
            this.maxTotalMergeKeys = typeof options["maxTotalMergeKeys"] === "number" ? options["maxTotalMergeKeys"] : 1e4;
            this.implicitTypes = this.schema.compiledImplicit;
            this.typeMap = this.schema.compiledTypeMap;
            this.length = input.length;
            this.position = 0;
            this.line = 0;
            this.lineStart = 0;
            this.lineIndent = 0;
            this.depth = 0;
            this.totalMergeKeys = 0;
            this.firstTabInLine = -1;
            this.documents = [];
            this.anchorMapTransactions = [];
        }
        function generateError(state, message) {
            var mark = {
                name: state.filename,
                buffer: state.input.slice(0, -1),
                position: state.position,
                line: state.line,
                column: state.position - state.lineStart
            };
            mark.snippet = makeSnippet(mark);
            return new YAMLException2(message, mark);
        }
        function throwError(state, message) {
            throw generateError(state, message);
        }
        function throwWarning(state, message) {
            if (state.onWarning) {
                state.onWarning.call(null, generateError(state, message));
            }
        }
        function storeAnchor(state, name, value) {
            var transactions = state.anchorMapTransactions;
            if (transactions.length !== 0) {
                var transaction = transactions[transactions.length - 1];
                if (!_hasOwnProperty.call(transaction, name)) {
                    transaction[name] = {
                        existed: _hasOwnProperty.call(state.anchorMap, name),
                        value: state.anchorMap[name]
                    };
                }
            }
            state.anchorMap[name] = value;
        }
        function beginAnchorTransaction(state) {
            state.anchorMapTransactions.push(Object.create(null));
        }
        function commitAnchorTransaction(state) {
            var transaction = state.anchorMapTransactions.pop();
            var transactions = state.anchorMapTransactions;
            if (transactions.length === 0) return;
            var parent = transactions[transactions.length - 1];
            var names = Object.keys(transaction);
            for (var index = 0, length = names.length; index < length; index += 1) {
                var name = names[index];
                if (!_hasOwnProperty.call(parent, name)) {
                    parent[name] = transaction[name];
                }
            }
        }
        function rollbackAnchorTransaction(state) {
            var transaction = state.anchorMapTransactions.pop();
            var names = Object.keys(transaction);
            for (var index = names.length - 1; index >= 0; index -= 1) {
                var entry = transaction[names[index]];
                if (entry.existed) {
                    state.anchorMap[names[index]] = entry.value;
                } else {
                    delete state.anchorMap[names[index]];
                }
            }
        }
        function snapshotState(state) {
            return {
                position: state.position,
                line: state.line,
                lineStart: state.lineStart,
                lineIndent: state.lineIndent,
                firstTabInLine: state.firstTabInLine,
                tag: state.tag,
                anchor: state.anchor,
                kind: state.kind,
                result: state.result
            };
        }
        function restoreState(state, snapshot) {
            state.position = snapshot.position;
            state.line = snapshot.line;
            state.lineStart = snapshot.lineStart;
            state.lineIndent = snapshot.lineIndent;
            state.firstTabInLine = snapshot.firstTabInLine;
            state.tag = snapshot.tag;
            state.anchor = snapshot.anchor;
            state.kind = snapshot.kind;
            state.result = snapshot.result;
        }
        var directiveHandlers = {
            YAML: function handleYamlDirective(state, name, args) {
                if (state.version !== null) {
                    throwError(state, "duplication of %YAML directive");
                }
                if (args.length !== 1) {
                    throwError(state, "YAML directive accepts exactly one argument");
                }
                var match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);
                if (match === null) {
                    throwError(state, "ill-formed argument of the YAML directive");
                }
                var major = parseInt(match[1], 10);
                var minor = parseInt(match[2], 10);
                if (major !== 1) {
                    throwError(state, "unacceptable YAML version of the document");
                }
                state.version = args[0];
                state.checkLineBreaks = minor < 2;
                if (minor !== 1 && minor !== 2) {
                    throwWarning(state, "unsupported YAML version of the document");
                }
            },
            TAG: function handleTagDirective(state, name, args) {
                var prefix;
                if (args.length !== 2) {
                    throwError(state, "TAG directive accepts exactly two arguments");
                }
                var handle = args[0];
                prefix = args[1];
                if (!PATTERN_TAG_HANDLE.test(handle)) {
                    throwError(state, "ill-formed tag handle (first argument) of the TAG directive");
                }
                if (_hasOwnProperty.call(state.tagMap, handle)) {
                    throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle');
                }
                if (!PATTERN_TAG_URI.test(prefix)) {
                    throwError(state, "ill-formed tag prefix (second argument) of the TAG directive");
                }
                try {
                    prefix = decodeURIComponent(prefix);
                } catch (err) {
                    throwError(state, "tag prefix is malformed: " + prefix);
                }
                state.tagMap[handle] = prefix;
            }
        };
        function captureSegment(state, start, end, checkJson) {
            if (start < end) {
                var _result = state.input.slice(start, end);
                if (checkJson) {
                    for (var _position = 0, _length = _result.length; _position < _length; _position += 1) {
                        var _character = _result.charCodeAt(_position);
                        if (!(_character === 9 || _character >= 32 && _character <= 1114111)) {
                            throwError(state, "expected valid JSON character");
                        }
                    }
                } else if (PATTERN_NON_PRINTABLE.test(_result)) {
                    throwError(state, "the stream contains non-printable characters");
                }
                state.result += _result;
            }
        }
        function mergeMappings(state, destination, source, overridableKeys) {
            if (!common2.isObject(source)) {
                throwError(state, "cannot merge mappings; the provided source object is unacceptable");
            }
            var sourceKeys = Object.keys(source);
            for (var index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
                var key = sourceKeys[index];
                if (state.maxTotalMergeKeys !== -1 && ++state.totalMergeKeys > state.maxTotalMergeKeys) {
                    throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
                }
                if (!_hasOwnProperty.call(destination, key)) {
                    setProperty(destination, key, source[key]);
                    overridableKeys[key] = true;
                }
            }
        }
        function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, startLine, startLineStart, startPos) {
            if (Array.isArray(keyNode)) {
                keyNode = Array.prototype.slice.call(keyNode);
                for (var index = 0, quantity = keyNode.length; index < quantity; index += 1) {
                    if (Array.isArray(keyNode[index])) {
                        throwError(state, "nested arrays are not supported inside keys");
                    }
                    if (_typeof(keyNode) === "object" && _class(keyNode[index]) === "[object Object]") {
                        keyNode[index] = "[object Object]";
                    }
                }
            }
            if (_typeof(keyNode) === "object" && _class(keyNode) === "[object Object]") {
                keyNode = "[object Object]";
            }
            keyNode = String(keyNode);
            if (_result === null) {
                _result = {};
            }
            if (keyTag === "tag:yaml.org,2002:merge") {
                if (Array.isArray(valueNode)) {
                    for (var _index = 0, _quantity = valueNode.length; _index < _quantity; _index += 1) {
                        mergeMappings(state, _result, valueNode[_index], overridableKeys);
                    }
                } else {
                    mergeMappings(state, _result, valueNode, overridableKeys);
                }
            } else {
                if (!state.json && !_hasOwnProperty.call(overridableKeys, keyNode) && _hasOwnProperty.call(_result, keyNode)) {
                    state.line = startLine || state.line;
                    state.lineStart = startLineStart || state.lineStart;
                    state.position = startPos || state.position;
                    throwError(state, "duplicated mapping key");
                }
                setProperty(_result, keyNode, valueNode);
                delete overridableKeys[keyNode];
            }
            return _result;
        }
        function readLineBreak(state) {
            var ch = state.input.charCodeAt(state.position);
            if (ch === 10) {
                state.position++;
            } else if (ch === 13) {
                state.position++;
                if (state.input.charCodeAt(state.position) === 10) {
                    state.position++;
                }
            } else {
                throwError(state, "a line break is expected");
            }
            state.line += 1;
            state.lineStart = state.position;
            state.firstTabInLine = -1;
        }
        function skipSeparationSpace(state, allowComments, checkIndent) {
            var lineBreaks = 0;
            var ch = state.input.charCodeAt(state.position);
            while (ch !== 0) {
                while (isWhiteSpace(ch)) {
                    if (ch === 9 && state.firstTabInLine === -1) {
                        state.firstTabInLine = state.position;
                    }
                    ch = state.input.charCodeAt(++state.position);
                }
                if (allowComments && ch === 35) {
                    do {
                        ch = state.input.charCodeAt(++state.position);
                    } while (ch !== 10 && ch !== 13 && ch !== 0);
                }
                if (isEol(ch)) {
                    readLineBreak(state);
                    ch = state.input.charCodeAt(state.position);
                    lineBreaks++;
                    state.lineIndent = 0;
                    while (ch === 32) {
                        state.lineIndent++;
                        ch = state.input.charCodeAt(++state.position);
                    }
                } else {
                    break;
                }
            }
            if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
                throwWarning(state, "deficient indentation");
            }
            return lineBreaks;
        }
        function testDocumentSeparator(state) {
            var _position = state.position;
            var ch = state.input.charCodeAt(_position);
            if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(_position + 1) && ch === state.input.charCodeAt(_position + 2)) {
                _position += 3;
                ch = state.input.charCodeAt(_position);
                if (ch === 0 || isWsOrEol(ch)) {
                    return true;
                }
            }
            return false;
        }
        function writeFoldedLines(state, count) {
            if (count === 1) {
                state.result += " ";
            } else if (count > 1) {
                state.result += common2.repeat("\n", count - 1);
            }
        }
        function readPlainScalar(state, nodeIndent, withinFlowCollection) {
            var captureStart;
            var captureEnd;
            var hasPendingContent;
            var _line;
            var _lineStart;
            var _lineIndent;
            var _kind = state.kind;
            var _result = state.result;
            var ch = state.input.charCodeAt(state.position);
            if (isWsOrEol(ch) || isFlowIndicator(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96) {
                return false;
            }
            if (ch === 63 || ch === 45) {
                var following = state.input.charCodeAt(state.position + 1);
                if (isWsOrEol(following) || withinFlowCollection && isFlowIndicator(following)) {
                    return false;
                }
            }
            state.kind = "scalar";
            state.result = "";
            captureStart = captureEnd = state.position;
            hasPendingContent = false;
            while (ch !== 0) {
                if (ch === 58) {
                    var _following = state.input.charCodeAt(state.position + 1);
                    if (isWsOrEol(_following) || withinFlowCollection && isFlowIndicator(_following)) {
                        break;
                    }
                } else if (ch === 35) {
                    var preceding = state.input.charCodeAt(state.position - 1);
                    if (isWsOrEol(preceding)) {
                        break;
                    }
                } else if (state.position === state.lineStart && testDocumentSeparator(state) || withinFlowCollection && isFlowIndicator(ch)) {
                    break;
                } else if (isEol(ch)) {
                    _line = state.line;
                    _lineStart = state.lineStart;
                    _lineIndent = state.lineIndent;
                    skipSeparationSpace(state, false, -1);
                    if (state.lineIndent >= nodeIndent) {
                        hasPendingContent = true;
                        ch = state.input.charCodeAt(state.position);
                        continue;
                    } else {
                        state.position = captureEnd;
                        state.line = _line;
                        state.lineStart = _lineStart;
                        state.lineIndent = _lineIndent;
                        break;
                    }
                }
                if (hasPendingContent) {
                    captureSegment(state, captureStart, captureEnd, false);
                    writeFoldedLines(state, state.line - _line);
                    captureStart = captureEnd = state.position;
                    hasPendingContent = false;
                }
                if (!isWhiteSpace(ch)) {
                    captureEnd = state.position + 1;
                }
                ch = state.input.charCodeAt(++state.position);
            }
            captureSegment(state, captureStart, captureEnd, false);
            if (state.result) {
                return true;
            }
            state.kind = _kind;
            state.result = _result;
            return false;
        }
        function readSingleQuotedScalar(state, nodeIndent) {
            var captureStart;
            var captureEnd;
            var ch = state.input.charCodeAt(state.position);
            if (ch !== 39) {
                return false;
            }
            state.kind = "scalar";
            state.result = "";
            state.position++;
            captureStart = captureEnd = state.position;
            while ((ch = state.input.charCodeAt(state.position)) !== 0) {
                if (ch === 39) {
                    captureSegment(state, captureStart, state.position, true);
                    ch = state.input.charCodeAt(++state.position);
                    if (ch === 39) {
                        captureStart = state.position;
                        state.position++;
                        captureEnd = state.position;
                    } else {
                        return true;
                    }
                } else if (isEol(ch)) {
                    captureSegment(state, captureStart, captureEnd, true);
                    writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
                    captureStart = captureEnd = state.position;
                } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
                    throwError(state, "unexpected end of the document within a single quoted scalar");
                } else {
                    state.position++;
                    if (!isWhiteSpace(ch)) {
                        captureEnd = state.position;
                    }
                }
            }
            throwError(state, "unexpected end of the stream within a single quoted scalar");
        }
        function readDoubleQuotedScalar(state, nodeIndent) {
            var captureStart;
            var captureEnd;
            var tmp;
            var ch = state.input.charCodeAt(state.position);
            if (ch !== 34) {
                return false;
            }
            state.kind = "scalar";
            state.result = "";
            state.position++;
            captureStart = captureEnd = state.position;
            while ((ch = state.input.charCodeAt(state.position)) !== 0) {
                if (ch === 34) {
                    captureSegment(state, captureStart, state.position, true);
                    state.position++;
                    return true;
                } else if (ch === 92) {
                    captureSegment(state, captureStart, state.position, true);
                    ch = state.input.charCodeAt(++state.position);
                    if (isEol(ch)) {
                        skipSeparationSpace(state, false, nodeIndent);
                    } else if (ch < 256 && simpleEscapeCheck[ch]) {
                        state.result += simpleEscapeMap[ch];
                        state.position++;
                    } else if ((tmp = escapedHexLen(ch)) > 0) {
                        var hexLength = tmp;
                        var hexResult = 0;
                        for (;hexLength > 0; hexLength--) {
                            ch = state.input.charCodeAt(++state.position);
                            if ((tmp = fromHexCode(ch)) >= 0) {
                                hexResult = (hexResult << 4) + tmp;
                            } else {
                                throwError(state, "expected hexadecimal character");
                            }
                        }
                        state.result += charFromCodepoint(hexResult);
                        state.position++;
                    } else {
                        throwError(state, "unknown escape sequence");
                    }
                    captureStart = captureEnd = state.position;
                } else if (isEol(ch)) {
                    captureSegment(state, captureStart, captureEnd, true);
                    writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
                    captureStart = captureEnd = state.position;
                } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
                    throwError(state, "unexpected end of the document within a double quoted scalar");
                } else {
                    state.position++;
                    if (!isWhiteSpace(ch)) {
                        captureEnd = state.position;
                    }
                }
            }
            throwError(state, "unexpected end of the stream within a double quoted scalar");
        }
        function readFlowCollection(state, nodeIndent) {
            var readNext = true;
            var _line;
            var _lineStart;
            var _pos;
            var _tag = state.tag;
            var _result;
            var _anchor = state.anchor;
            var terminator;
            var isPair;
            var isExplicitPair;
            var isMapping;
            var overridableKeys = Object.create(null);
            var keyNode;
            var keyTag;
            var valueNode;
            var ch = state.input.charCodeAt(state.position);
            if (ch === 91) {
                terminator = 93;
                isMapping = false;
                _result = [];
            } else if (ch === 123) {
                terminator = 125;
                isMapping = true;
                _result = {};
            } else {
                return false;
            }
            if (state.anchor !== null) {
                storeAnchor(state, state.anchor, _result);
            }
            ch = state.input.charCodeAt(++state.position);
            while (ch !== 0) {
                skipSeparationSpace(state, true, nodeIndent);
                ch = state.input.charCodeAt(state.position);
                if (ch === terminator) {
                    state.position++;
                    state.tag = _tag;
                    state.anchor = _anchor;
                    state.kind = isMapping ? "mapping" : "sequence";
                    state.result = _result;
                    return true;
                } else if (!readNext) {
                    throwError(state, "missed comma between flow collection entries");
                } else if (ch === 44) {
                    throwError(state, "expected the node content, but found ','");
                }
                keyTag = keyNode = valueNode = null;
                isPair = isExplicitPair = false;
                if (ch === 63) {
                    var following = state.input.charCodeAt(state.position + 1);
                    if (isWsOrEol(following)) {
                        isPair = isExplicitPair = true;
                        state.position++;
                        skipSeparationSpace(state, true, nodeIndent);
                    }
                }
                _line = state.line;
                _lineStart = state.lineStart;
                _pos = state.position;
                composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
                keyTag = state.tag;
                keyNode = state.result;
                skipSeparationSpace(state, true, nodeIndent);
                ch = state.input.charCodeAt(state.position);
                if ((isExplicitPair || state.line === _line) && ch === 58) {
                    isPair = true;
                    ch = state.input.charCodeAt(++state.position);
                    skipSeparationSpace(state, true, nodeIndent);
                    composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
                    valueNode = state.result;
                }
                if (isMapping) {
                    storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos);
                } else if (isPair) {
                    _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos));
                } else {
                    _result.push(keyNode);
                }
                skipSeparationSpace(state, true, nodeIndent);
                ch = state.input.charCodeAt(state.position);
                if (ch === 44) {
                    readNext = true;
                    ch = state.input.charCodeAt(++state.position);
                } else {
                    readNext = false;
                }
            }
            throwError(state, "unexpected end of the stream within a flow collection");
        }
        function readBlockScalar(state, nodeIndent) {
            var folding;
            var chomping = CHOMPING_CLIP;
            var didReadContent = false;
            var detectedIndent = false;
            var textIndent = nodeIndent;
            var emptyLines = 0;
            var atMoreIndented = false;
            var tmp;
            var ch = state.input.charCodeAt(state.position);
            if (ch === 124) {
                folding = false;
            } else if (ch === 62) {
                folding = true;
            } else {
                return false;
            }
            state.kind = "scalar";
            state.result = "";
            while (ch !== 0) {
                ch = state.input.charCodeAt(++state.position);
                if (ch === 43 || ch === 45) {
                    if (CHOMPING_CLIP === chomping) {
                        chomping = ch === 43 ? CHOMPING_KEEP : CHOMPING_STRIP;
                    } else {
                        throwError(state, "repeat of a chomping mode identifier");
                    }
                } else if ((tmp = fromDecimalCode(ch)) >= 0) {
                    if (tmp === 0) {
                        throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one");
                    } else if (!detectedIndent) {
                        textIndent = nodeIndent + tmp - 1;
                        detectedIndent = true;
                    } else {
                        throwError(state, "repeat of an indentation width identifier");
                    }
                } else {
                    break;
                }
            }
            if (isWhiteSpace(ch)) {
                do {
                    ch = state.input.charCodeAt(++state.position);
                } while (isWhiteSpace(ch));
                if (ch === 35) {
                    do {
                        ch = state.input.charCodeAt(++state.position);
                    } while (!isEol(ch) && ch !== 0);
                }
            }
            while (ch !== 0) {
                readLineBreak(state);
                state.lineIndent = 0;
                ch = state.input.charCodeAt(state.position);
                while ((!detectedIndent || state.lineIndent < textIndent) && ch === 32) {
                    state.lineIndent++;
                    ch = state.input.charCodeAt(++state.position);
                }
                if (!detectedIndent && state.lineIndent > textIndent) {
                    textIndent = state.lineIndent;
                }
                if (isEol(ch)) {
                    emptyLines++;
                    continue;
                }
                if (!detectedIndent && textIndent === 0) {
                    throwError(state, "missing indentation for block scalar");
                }
                if (state.lineIndent < textIndent) {
                    if (chomping === CHOMPING_KEEP) {
                        state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
                    } else if (chomping === CHOMPING_CLIP) {
                        if (didReadContent) {
                            state.result += "\n";
                        }
                    }
                    break;
                }
                if (folding) {
                    if (isWhiteSpace(ch)) {
                        atMoreIndented = true;
                        state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
                    } else if (atMoreIndented) {
                        atMoreIndented = false;
                        state.result += common2.repeat("\n", emptyLines + 1);
                    } else if (emptyLines === 0) {
                        if (didReadContent) {
                            state.result += " ";
                        }
                    } else {
                        state.result += common2.repeat("\n", emptyLines);
                    }
                } else {
                    state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
                }
                didReadContent = true;
                detectedIndent = true;
                emptyLines = 0;
                var captureStart = state.position;
                while (!isEol(ch) && ch !== 0) {
                    ch = state.input.charCodeAt(++state.position);
                }
                captureSegment(state, captureStart, state.position, false);
            }
            return true;
        }
        function readBlockSequence(state, nodeIndent) {
            var _tag = state.tag;
            var _anchor = state.anchor;
            var _result = [];
            var detected = false;
            if (state.firstTabInLine !== -1) return false;
            if (state.anchor !== null) {
                storeAnchor(state, state.anchor, _result);
            }
            var ch = state.input.charCodeAt(state.position);
            while (ch !== 0) {
                if (state.firstTabInLine !== -1) {
                    state.position = state.firstTabInLine;
                    throwError(state, "tab characters must not be used in indentation");
                }
                if (ch !== 45) {
                    break;
                }
                var following = state.input.charCodeAt(state.position + 1);
                if (!isWsOrEol(following)) {
                    break;
                }
                detected = true;
                state.position++;
                if (skipSeparationSpace(state, true, -1)) {
                    if (state.lineIndent <= nodeIndent) {
                        _result.push(null);
                        ch = state.input.charCodeAt(state.position);
                        continue;
                    }
                }
                var _line = state.line;
                composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);
                _result.push(state.result);
                skipSeparationSpace(state, true, -1);
                ch = state.input.charCodeAt(state.position);
                if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) {
                    throwError(state, "bad indentation of a sequence entry");
                } else if (state.lineIndent < nodeIndent) {
                    break;
                }
            }
            if (detected) {
                state.tag = _tag;
                state.anchor = _anchor;
                state.kind = "sequence";
                state.result = _result;
                return true;
            }
            return false;
        }
        function readBlockMapping(state, nodeIndent, flowIndent) {
            var allowCompact;
            var _keyLine;
            var _keyLineStart;
            var _keyPos;
            var _tag = state.tag;
            var _anchor = state.anchor;
            var _result = {};
            var overridableKeys = Object.create(null);
            var keyTag = null;
            var keyNode = null;
            var valueNode = null;
            var atExplicitKey = false;
            var detected = false;
            if (state.firstTabInLine !== -1) return false;
            if (state.anchor !== null) {
                storeAnchor(state, state.anchor, _result);
            }
            var ch = state.input.charCodeAt(state.position);
            while (ch !== 0) {
                if (!atExplicitKey && state.firstTabInLine !== -1) {
                    state.position = state.firstTabInLine;
                    throwError(state, "tab characters must not be used in indentation");
                }
                var following = state.input.charCodeAt(state.position + 1);
                var _line = state.line;
                if ((ch === 63 || ch === 58) && isWsOrEol(following)) {
                    if (ch === 63) {
                        if (atExplicitKey) {
                            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
                            keyTag = keyNode = valueNode = null;
                        }
                        detected = true;
                        atExplicitKey = true;
                        allowCompact = true;
                    } else if (atExplicitKey) {
                        atExplicitKey = false;
                        allowCompact = true;
                    } else {
                        throwError(state, "incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line");
                    }
                    state.position += 1;
                    ch = following;
                } else {
                    _keyLine = state.line;
                    _keyLineStart = state.lineStart;
                    _keyPos = state.position;
                    if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
                        break;
                    }
                    if (state.line === _line) {
                        ch = state.input.charCodeAt(state.position);
                        while (isWhiteSpace(ch)) {
                            ch = state.input.charCodeAt(++state.position);
                        }
                        if (ch === 58) {
                            ch = state.input.charCodeAt(++state.position);
                            if (!isWsOrEol(ch)) {
                                throwError(state, "a whitespace character is expected after the key-value separator within a block mapping");
                            }
                            if (atExplicitKey) {
                                storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
                                keyTag = keyNode = valueNode = null;
                            }
                            detected = true;
                            atExplicitKey = false;
                            allowCompact = false;
                            keyTag = state.tag;
                            keyNode = state.result;
                        } else if (detected) {
                            throwError(state, "can not read an implicit mapping pair; a colon is missed");
                        } else {
                            state.tag = _tag;
                            state.anchor = _anchor;
                            return true;
                        }
                    } else if (detected) {
                        throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key");
                    } else {
                        state.tag = _tag;
                        state.anchor = _anchor;
                        return true;
                    }
                }
                if (state.line === _line || state.lineIndent > nodeIndent) {
                    if (atExplicitKey) {
                        _keyLine = state.line;
                        _keyLineStart = state.lineStart;
                        _keyPos = state.position;
                    }
                    if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
                        if (atExplicitKey) {
                            keyNode = state.result;
                        } else {
                            valueNode = state.result;
                        }
                    }
                    if (!atExplicitKey) {
                        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos);
                        keyTag = keyNode = valueNode = null;
                    }
                    skipSeparationSpace(state, true, -1);
                    ch = state.input.charCodeAt(state.position);
                }
                if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) {
                    throwError(state, "bad indentation of a mapping entry");
                } else if (state.lineIndent < nodeIndent) {
                    break;
                }
            }
            if (atExplicitKey) {
                storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
            }
            if (detected) {
                state.tag = _tag;
                state.anchor = _anchor;
                state.kind = "mapping";
                state.result = _result;
            }
            return detected;
        }
        function readTagProperty(state) {
            var isVerbatim = false;
            var isNamed = false;
            var tagHandle;
            var tagName;
            var ch = state.input.charCodeAt(state.position);
            if (ch !== 33) return false;
            if (state.tag !== null) {
                throwError(state, "duplication of a tag property");
            }
            ch = state.input.charCodeAt(++state.position);
            if (ch === 60) {
                isVerbatim = true;
                ch = state.input.charCodeAt(++state.position);
            } else if (ch === 33) {
                isNamed = true;
                tagHandle = "!!";
                ch = state.input.charCodeAt(++state.position);
            } else {
                tagHandle = "!";
            }
            var _position = state.position;
            if (isVerbatim) {
                do {
                    ch = state.input.charCodeAt(++state.position);
                } while (ch !== 0 && ch !== 62);
                if (state.position < state.length) {
                    tagName = state.input.slice(_position, state.position);
                    ch = state.input.charCodeAt(++state.position);
                } else {
                    throwError(state, "unexpected end of the stream within a verbatim tag");
                }
            } else {
                while (ch !== 0 && !isWsOrEol(ch)) {
                    if (ch === 33) {
                        if (!isNamed) {
                            tagHandle = state.input.slice(_position - 1, state.position + 1);
                            if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
                                throwError(state, "named tag handle cannot contain such characters");
                            }
                            isNamed = true;
                            _position = state.position + 1;
                        } else {
                            throwError(state, "tag suffix cannot contain exclamation marks");
                        }
                    }
                    ch = state.input.charCodeAt(++state.position);
                }
                tagName = state.input.slice(_position, state.position);
                if (PATTERN_FLOW_INDICATORS.test(tagName)) {
                    throwError(state, "tag suffix cannot contain flow indicator characters");
                }
            }
            if (tagName && !PATTERN_TAG_URI.test(tagName)) {
                throwError(state, "tag name cannot contain such characters: " + tagName);
            }
            try {
                tagName = decodeURIComponent(tagName);
            } catch (err) {
                throwError(state, "tag name is malformed: " + tagName);
            }
            if (isVerbatim) {
                state.tag = tagName;
            } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {
                state.tag = state.tagMap[tagHandle] + tagName;
            } else if (tagHandle === "!") {
                state.tag = "!" + tagName;
            } else if (tagHandle === "!!") {
                state.tag = "tag:yaml.org,2002:" + tagName;
            } else {
                throwError(state, 'undeclared tag handle "' + tagHandle + '"');
            }
            return true;
        }
        function readAnchorProperty(state) {
            var ch = state.input.charCodeAt(state.position);
            if (ch !== 38) return false;
            if (state.anchor !== null) {
                throwError(state, "duplication of an anchor property");
            }
            ch = state.input.charCodeAt(++state.position);
            var _position = state.position;
            while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {
                ch = state.input.charCodeAt(++state.position);
            }
            if (state.position === _position) {
                throwError(state, "name of an anchor node must contain at least one character");
            }
            state.anchor = state.input.slice(_position, state.position);
            return true;
        }
        function readAlias(state) {
            var ch = state.input.charCodeAt(state.position);
            if (ch !== 42) return false;
            ch = state.input.charCodeAt(++state.position);
            var _position = state.position;
            while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {
                ch = state.input.charCodeAt(++state.position);
            }
            if (state.position === _position) {
                throwError(state, "name of an alias node must contain at least one character");
            }
            var alias = state.input.slice(_position, state.position);
            if (!_hasOwnProperty.call(state.anchorMap, alias)) {
                throwError(state, 'unidentified alias "' + alias + '"');
            }
            state.result = state.anchorMap[alias];
            skipSeparationSpace(state, true, -1);
            return true;
        }
        function tryReadBlockMappingFromProperty(state, propertyStart, nodeIndent, flowIndent) {
            var fallbackState = snapshotState(state);
            beginAnchorTransaction(state);
            restoreState(state, propertyStart);
            state.tag = null;
            state.anchor = null;
            state.kind = null;
            state.result = null;
            if (readBlockMapping(state, nodeIndent, flowIndent) && state.kind === "mapping") {
                commitAnchorTransaction(state);
                return true;
            }
            rollbackAnchorTransaction(state);
            restoreState(state, fallbackState);
            return false;
        }
        function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
            var allowBlockScalars;
            var allowBlockCollections;
            var indentStatus = 1;
            var atNewLine = false;
            var hasContent = false;
            var propertyStart = null;
            var type2;
            var flowIndent;
            var blockIndent;
            if (state.depth >= state.maxDepth) {
                throwError(state, "nesting exceeded maxDepth (" + state.maxDepth + ")");
            }
            state.depth += 1;
            if (state.listener !== null) {
                state.listener("open", state);
            }
            state.tag = null;
            state.anchor = null;
            state.kind = null;
            state.result = null;
            var allowBlockStyles = allowBlockScalars = allowBlockCollections = CONTEXT_BLOCK_OUT === nodeContext || CONTEXT_BLOCK_IN === nodeContext;
            if (allowToSeek) {
                if (skipSeparationSpace(state, true, -1)) {
                    atNewLine = true;
                    if (state.lineIndent > parentIndent) {
                        indentStatus = 1;
                    } else if (state.lineIndent === parentIndent) {
                        indentStatus = 0;
                    } else if (state.lineIndent < parentIndent) {
                        indentStatus = -1;
                    }
                }
            }
            if (indentStatus === 1) {
                while (true) {
                    var ch = state.input.charCodeAt(state.position);
                    var propertyState = snapshotState(state);
                    if (atNewLine && (ch === 33 && state.tag !== null || ch === 38 && state.anchor !== null)) {
                        break;
                    }
                    if (!readTagProperty(state) && !readAnchorProperty(state)) {
                        break;
                    }
                    if (propertyStart === null) {
                        propertyStart = propertyState;
                    }
                    if (skipSeparationSpace(state, true, -1)) {
                        atNewLine = true;
                        allowBlockCollections = allowBlockStyles;
                        if (state.lineIndent > parentIndent) {
                            indentStatus = 1;
                        } else if (state.lineIndent === parentIndent) {
                            indentStatus = 0;
                        } else if (state.lineIndent < parentIndent) {
                            indentStatus = -1;
                        }
                    } else {
                        allowBlockCollections = false;
                    }
                }
            }
            if (allowBlockCollections) {
                allowBlockCollections = atNewLine || allowCompact;
            }
            if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
                if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
                    flowIndent = parentIndent;
                } else {
                    flowIndent = parentIndent + 1;
                }
                blockIndent = state.position - state.lineStart;
                if (indentStatus === 1) {
                    if (allowBlockCollections && (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent)) || readFlowCollection(state, flowIndent)) {
                        hasContent = true;
                    } else {
                        var _ch = state.input.charCodeAt(state.position);
                        if (propertyStart !== null && allowBlockStyles && !allowBlockCollections && _ch !== 124 && _ch !== 62 && tryReadBlockMappingFromProperty(state, propertyStart, propertyStart.position - propertyStart.lineStart, flowIndent)) {
                            hasContent = true;
                        } else if (allowBlockScalars && readBlockScalar(state, flowIndent) || readSingleQuotedScalar(state, flowIndent) || readDoubleQuotedScalar(state, flowIndent)) {
                            hasContent = true;
                        } else if (readAlias(state)) {
                            hasContent = true;
                            if (state.tag !== null || state.anchor !== null) {
                                throwError(state, "alias node should not have any properties");
                            }
                        } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
                            hasContent = true;
                            if (state.tag === null) {
                                state.tag = "?";
                            }
                        }
                        if (state.anchor !== null) {
                            storeAnchor(state, state.anchor, state.result);
                        }
                    }
                } else if (indentStatus === 0) {
                    hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
                }
            }
            if (state.tag === null) {
                if (state.anchor !== null) {
                    storeAnchor(state, state.anchor, state.result);
                }
            } else if (state.tag === "?") {
                if (state.result !== null && state.kind !== "scalar") {
                    throwError(state, 'unacceptable node kind for !<?> tag; it should be "scalar", not "' + state.kind + '"');
                }
                for (var typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {
                    type2 = state.implicitTypes[typeIndex];
                    if (type2.resolve(state.result)) {
                        state.result = type2.construct(state.result);
                        state.tag = type2.tag;
                        if (state.anchor !== null) {
                            storeAnchor(state, state.anchor, state.result);
                        }
                        break;
                    }
                }
            } else if (state.tag !== "!") {
                if (_hasOwnProperty.call(state.typeMap[state.kind || "fallback"], state.tag)) {
                    type2 = state.typeMap[state.kind || "fallback"][state.tag];
                } else {
                    type2 = null;
                    var typeList = state.typeMap.multi[state.kind || "fallback"];
                    for (var _typeIndex = 0, _typeQuantity = typeList.length; _typeIndex < _typeQuantity; _typeIndex += 1) {
                        if (state.tag.slice(0, typeList[_typeIndex].tag.length) === typeList[_typeIndex].tag) {
                            type2 = typeList[_typeIndex];
                            break;
                        }
                    }
                }
                if (!type2) {
                    throwError(state, "unknown tag !<" + state.tag + ">");
                }
                if (state.result !== null && type2.kind !== state.kind) {
                    throwError(state, "unacceptable node kind for !<" + state.tag + '> tag; it should be "' + type2.kind + '", not "' + state.kind + '"');
                }
                if (!type2.resolve(state.result, state.tag)) {
                    throwError(state, "cannot resolve a node with !<" + state.tag + "> explicit tag");
                } else {
                    state.result = type2.construct(state.result, state.tag);
                    if (state.anchor !== null) {
                        storeAnchor(state, state.anchor, state.result);
                    }
                }
            }
            if (state.listener !== null) {
                state.listener("close", state);
            }
            state.depth -= 1;
            return state.tag !== null || state.anchor !== null || hasContent;
        }
        function readDocument(state) {
            var documentStart = state.position;
            var hasDirectives = false;
            var ch;
            state.version = null;
            state.checkLineBreaks = state.legacy;
            state.tagMap = Object.create(null);
            state.anchorMap = Object.create(null);
            while ((ch = state.input.charCodeAt(state.position)) !== 0) {
                skipSeparationSpace(state, true, -1);
                ch = state.input.charCodeAt(state.position);
                if (state.lineIndent > 0 || ch !== 37) {
                    break;
                }
                hasDirectives = true;
                ch = state.input.charCodeAt(++state.position);
                var _position = state.position;
                while (ch !== 0 && !isWsOrEol(ch)) {
                    ch = state.input.charCodeAt(++state.position);
                }
                var directiveName = state.input.slice(_position, state.position);
                var directiveArgs = [];
                if (directiveName.length < 1) {
                    throwError(state, "directive name must not be less than one character in length");
                }
                while (ch !== 0) {
                    while (isWhiteSpace(ch)) {
                        ch = state.input.charCodeAt(++state.position);
                    }
                    if (ch === 35) {
                        do {
                            ch = state.input.charCodeAt(++state.position);
                        } while (ch !== 0 && !isEol(ch));
                        break;
                    }
                    if (isEol(ch)) break;
                    _position = state.position;
                    while (ch !== 0 && !isWsOrEol(ch)) {
                        ch = state.input.charCodeAt(++state.position);
                    }
                    directiveArgs.push(state.input.slice(_position, state.position));
                }
                if (ch !== 0) readLineBreak(state);
                if (_hasOwnProperty.call(directiveHandlers, directiveName)) {
                    directiveHandlers[directiveName](state, directiveName, directiveArgs);
                } else {
                    throwWarning(state, 'unknown document directive "' + directiveName + '"');
                }
            }
            skipSeparationSpace(state, true, -1);
            if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45) {
                state.position += 3;
                skipSeparationSpace(state, true, -1);
            } else if (hasDirectives) {
                throwError(state, "directives end mark is expected");
            }
            composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
            skipSeparationSpace(state, true, -1);
            if (state.checkLineBreaks && PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
                throwWarning(state, "non-ASCII line breaks are interpreted as content");
            }
            state.documents.push(state.result);
            if (state.position === state.lineStart && testDocumentSeparator(state)) {
                if (state.input.charCodeAt(state.position) === 46) {
                    state.position += 3;
                    skipSeparationSpace(state, true, -1);
                }
                return;
            }
            if (state.position < state.length - 1) {
                throwError(state, "end of the stream or a document separator is expected");
            }
        }
        function loadDocuments(input, options) {
            input = String(input);
            options = options || {};
            if (input.length !== 0) {
                if (input.charCodeAt(input.length - 1) !== 10 && input.charCodeAt(input.length - 1) !== 13) {
                    input += "\n";
                }
                if (input.charCodeAt(0) === 65279) {
                    input = input.slice(1);
                }
            }
            var state = new State(input, options);
            var nullpos = input.indexOf("\0");
            if (nullpos !== -1) {
                state.position = nullpos;
                throwError(state, "null byte is not allowed in input");
            }
            state.input += "\0";
            while (state.input.charCodeAt(state.position) === 32) {
                state.lineIndent += 1;
                state.position += 1;
            }
            while (state.position < state.length - 1) {
                readDocument(state);
            }
            return state.documents;
        }
        function loadAll2(input, iterator, options) {
            if (iterator !== null && _typeof(iterator) === "object" && typeof options === "undefined") {
                options = iterator;
                iterator = null;
            }
            var documents = loadDocuments(input, options);
            if (typeof iterator !== "function") {
                return documents;
            }
            for (var index = 0, length = documents.length; index < length; index += 1) {
                iterator(documents[index]);
            }
        }
        function load2(input, options) {
            var documents = loadDocuments(input, options);
            if (documents.length === 0) {
                return void 0;
            } else if (documents.length === 1) {
                return documents[0];
            }
            throw new YAMLException2("expected a single document in the stream, but found more");
        }
        loader.loadAll = loadAll2;
        loader.load = load2;
        return loader;
    }
    var dumper = {};
    var hasRequiredDumper;
    function requireDumper() {
        if (hasRequiredDumper) return dumper;
        hasRequiredDumper = 1;
        function _typeof(o) {
            "@babel/helpers - typeof";
            return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
                return typeof o2;
            } : function(o2) {
                return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2;
            }, _typeof(o);
        }
        var common2 = requireCommon();
        var YAMLException2 = requireException();
        var DEFAULT_SCHEMA2 = require_default();
        var _toString = Object.prototype.toString;
        var _hasOwnProperty = Object.prototype.hasOwnProperty;
        var CHAR_BOM = 65279;
        var CHAR_TAB = 9;
        var CHAR_LINE_FEED = 10;
        var CHAR_CARRIAGE_RETURN = 13;
        var CHAR_SPACE = 32;
        var CHAR_EXCLAMATION = 33;
        var CHAR_DOUBLE_QUOTE = 34;
        var CHAR_SHARP = 35;
        var CHAR_PERCENT = 37;
        var CHAR_AMPERSAND = 38;
        var CHAR_SINGLE_QUOTE = 39;
        var CHAR_ASTERISK = 42;
        var CHAR_COMMA = 44;
        var CHAR_MINUS = 45;
        var CHAR_COLON = 58;
        var CHAR_EQUALS = 61;
        var CHAR_GREATER_THAN = 62;
        var CHAR_QUESTION = 63;
        var CHAR_COMMERCIAL_AT = 64;
        var CHAR_LEFT_SQUARE_BRACKET = 91;
        var CHAR_RIGHT_SQUARE_BRACKET = 93;
        var CHAR_GRAVE_ACCENT = 96;
        var CHAR_LEFT_CURLY_BRACKET = 123;
        var CHAR_VERTICAL_LINE = 124;
        var CHAR_RIGHT_CURLY_BRACKET = 125;
        var ESCAPE_SEQUENCES = {};
        ESCAPE_SEQUENCES[0] = "\\0";
        ESCAPE_SEQUENCES[7] = "\\a";
        ESCAPE_SEQUENCES[8] = "\\b";
        ESCAPE_SEQUENCES[9] = "\\t";
        ESCAPE_SEQUENCES[10] = "\\n";
        ESCAPE_SEQUENCES[11] = "\\v";
        ESCAPE_SEQUENCES[12] = "\\f";
        ESCAPE_SEQUENCES[13] = "\\r";
        ESCAPE_SEQUENCES[27] = "\\e";
        ESCAPE_SEQUENCES[34] = '\\"';
        ESCAPE_SEQUENCES[92] = "\\\\";
        ESCAPE_SEQUENCES[133] = "\\N";
        ESCAPE_SEQUENCES[160] = "\\_";
        ESCAPE_SEQUENCES[8232] = "\\L";
        ESCAPE_SEQUENCES[8233] = "\\P";
        var DEPRECATED_BOOLEANS_SYNTAX = [ "y", "Y", "yes", "Yes", "YES", "on", "On", "ON", "n", "N", "no", "No", "NO", "off", "Off", "OFF" ];
        var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;
        function compileStyleMap(schema2, map2) {
            if (map2 === null) return {};
            var result = {};
            var keys = Object.keys(map2);
            for (var index = 0, length = keys.length; index < length; index += 1) {
                var tag = keys[index];
                var style = String(map2[tag]);
                if (tag.slice(0, 2) === "!!") {
                    tag = "tag:yaml.org,2002:" + tag.slice(2);
                }
                var type2 = schema2.compiledTypeMap["fallback"][tag];
                if (type2 && _hasOwnProperty.call(type2.styleAliases, style)) {
                    style = type2.styleAliases[style];
                }
                result[tag] = style;
            }
            return result;
        }
        function encodeHex(character) {
            var handle;
            var length;
            var string = character.toString(16).toUpperCase();
            if (character <= 255) {
                handle = "x";
                length = 2;
            } else if (character <= 65535) {
                handle = "u";
                length = 4;
            } else if (character <= 4294967295) {
                handle = "U";
                length = 8;
            } else {
                throw new YAMLException2("code point within a string may not be greater than 0xFFFFFFFF");
            }
            return "\\" + handle + common2.repeat("0", length - string.length) + string;
        }
        var QUOTING_TYPE_SINGLE = 1;
        var QUOTING_TYPE_DOUBLE = 2;
        function State(options) {
            this.schema = options["schema"] || DEFAULT_SCHEMA2;
            this.indent = Math.max(1, options["indent"] || 2);
            this.noArrayIndent = options["noArrayIndent"] || false;
            this.skipInvalid = options["skipInvalid"] || false;
            this.flowLevel = common2.isNothing(options["flowLevel"]) ? -1 : options["flowLevel"];
            this.styleMap = compileStyleMap(this.schema, options["styles"] || null);
            this.sortKeys = options["sortKeys"] || false;
            this.lineWidth = options["lineWidth"] || 80;
            this.noRefs = options["noRefs"] || false;
            this.noCompatMode = options["noCompatMode"] || false;
            this.condenseFlow = options["condenseFlow"] || false;
            this.quotingType = options["quotingType"] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE;
            this.forceQuotes = options["forceQuotes"] || false;
            this.replacer = typeof options["replacer"] === "function" ? options["replacer"] : null;
            this.implicitTypes = this.schema.compiledImplicit;
            this.explicitTypes = this.schema.compiledExplicit;
            this.tag = null;
            this.result = "";
            this.duplicates = [];
            this.usedDuplicates = null;
        }
        function indentString(string, spaces) {
            var ind = common2.repeat(" ", spaces);
            var position = 0;
            var result = "";
            var length = string.length;
            while (position < length) {
                var line = void 0;
                var next = string.indexOf("\n", position);
                if (next === -1) {
                    line = string.slice(position);
                    position = length;
                } else {
                    line = string.slice(position, next + 1);
                    position = next + 1;
                }
                if (line.length && line !== "\n") result += ind;
                result += line;
            }
            return result;
        }
        function generateNextLine(state, level) {
            return "\n" + common2.repeat(" ", state.indent * level);
        }
        function testImplicitResolving(state, str2) {
            for (var index = 0, length = state.implicitTypes.length; index < length; index += 1) {
                var type2 = state.implicitTypes[index];
                if (type2.resolve(str2)) {
                    return true;
                }
            }
            return false;
        }
        function isWhitespace(c) {
            return c === CHAR_SPACE || c === CHAR_TAB;
        }
        function isPrintable(c) {
            return c >= 32 && c <= 126 || c >= 161 && c <= 55295 && c !== 8232 && c !== 8233 || c >= 57344 && c <= 65533 && c !== CHAR_BOM || c >= 65536 && c <= 1114111;
        }
        function isNsCharOrWhitespace(c) {
            return isPrintable(c) && c !== CHAR_BOM && c !== CHAR_CARRIAGE_RETURN && c !== CHAR_LINE_FEED;
        }
        function isPlainSafe(c, prev, inblock) {
            var cIsNsCharOrWhitespace = isNsCharOrWhitespace(c);
            var cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c);
            return (inblock ? cIsNsCharOrWhitespace : cIsNsCharOrWhitespace && c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET) && c !== CHAR_SHARP && !(prev === CHAR_COLON && !cIsNsChar) || isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP || prev === CHAR_COLON && cIsNsChar;
        }
        function isPlainSafeFirst(c) {
            return isPrintable(c) && c !== CHAR_BOM && !isWhitespace(c) && c !== CHAR_MINUS && c !== CHAR_QUESTION && c !== CHAR_COLON && c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET && c !== CHAR_SHARP && c !== CHAR_AMPERSAND && c !== CHAR_ASTERISK && c !== CHAR_EXCLAMATION && c !== CHAR_VERTICAL_LINE && c !== CHAR_EQUALS && c !== CHAR_GREATER_THAN && c !== CHAR_SINGLE_QUOTE && c !== CHAR_DOUBLE_QUOTE && c !== CHAR_PERCENT && c !== CHAR_COMMERCIAL_AT && c !== CHAR_GRAVE_ACCENT;
        }
        function isPlainSafeLast(c) {
            return !isWhitespace(c) && c !== CHAR_COLON;
        }
        function codePointAt(string, pos) {
            var first = string.charCodeAt(pos);
            var second;
            if (first >= 55296 && first <= 56319 && pos + 1 < string.length) {
                second = string.charCodeAt(pos + 1);
                if (second >= 56320 && second <= 57343) {
                    return (first - 55296) * 1024 + second - 56320 + 65536;
                }
            }
            return first;
        }
        function needIndentIndicator(string) {
            var leadingSpaceRe = /^\n* /;
            return leadingSpaceRe.test(string);
        }
        var STYLE_PLAIN = 1;
        var STYLE_SINGLE = 2;
        var STYLE_LITERAL = 3;
        var STYLE_FOLDED = 4;
        var STYLE_DOUBLE = 5;
        function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType, quotingType, forceQuotes, inblock) {
            var i;
            var char = 0;
            var prevChar = null;
            var hasLineBreak = false;
            var hasFoldableLine = false;
            var shouldTrackWidth = lineWidth !== -1;
            var previousLineBreak = -1;
            var plain = isPlainSafeFirst(codePointAt(string, 0)) && isPlainSafeLast(codePointAt(string, string.length - 1));
            if (singleLineOnly || forceQuotes) {
                for (i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
                    char = codePointAt(string, i);
                    if (!isPrintable(char)) {
                        return STYLE_DOUBLE;
                    }
                    plain = plain && isPlainSafe(char, prevChar, inblock);
                    prevChar = char;
                }
            } else {
                for (i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
                    char = codePointAt(string, i);
                    if (char === CHAR_LINE_FEED) {
                        hasLineBreak = true;
                        if (shouldTrackWidth) {
                            hasFoldableLine = hasFoldableLine || i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ";
                            previousLineBreak = i;
                        }
                    } else if (!isPrintable(char)) {
                        return STYLE_DOUBLE;
                    }
                    plain = plain && isPlainSafe(char, prevChar, inblock);
                    prevChar = char;
                }
                hasFoldableLine = hasFoldableLine || shouldTrackWidth && i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ";
            }
            if (!hasLineBreak && !hasFoldableLine) {
                if (plain && !forceQuotes && !testAmbiguousType(string)) {
                    return STYLE_PLAIN;
                }
                return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
            }
            if (indentPerLevel > 9 && needIndentIndicator(string)) {
                return STYLE_DOUBLE;
            }
            if (!forceQuotes) {
                return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
            }
            return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
        }
        function writeScalar(state, string, level, iskey, inblock) {
            state.dump = function() {
                if (string.length === 0) {
                    return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''";
                }
                if (!state.noCompatMode) {
                    if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {
                        return state.quotingType === QUOTING_TYPE_DOUBLE ? '"' + string + '"' : "'" + string + "'";
                    }
                }
                var indent = state.indent * Math.max(1, level);
                var lineWidth = state.lineWidth === -1 ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
                var singleLineOnly = iskey || state.flowLevel > -1 && level >= state.flowLevel;
                function testAmbiguity(string2) {
                    return testImplicitResolving(state, string2);
                }
                switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {
                  case STYLE_PLAIN:
                    return string;

                  case STYLE_SINGLE:
                    return "'" + string.replace(/'/g, "''") + "'";

                  case STYLE_LITERAL:
                    return "|" + blockHeader(string, state.indent) + dropEndingNewline(indentString(string, indent));

                  case STYLE_FOLDED:
                    return ">" + blockHeader(string, state.indent) + dropEndingNewline(indentString(foldString(string, lineWidth), indent));

                  case STYLE_DOUBLE:
                    return '"' + escapeString(string) + '"';

                  default:
                    throw new YAMLException2("impossible error: invalid scalar style");
                }
            }();
        }
        function blockHeader(string, indentPerLevel) {
            var indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : "";
            var clip = string[string.length - 1] === "\n";
            var keep = clip && (string[string.length - 2] === "\n" || string === "\n");
            var chomp = keep ? "+" : clip ? "" : "-";
            return indentIndicator + chomp + "\n";
        }
        function dropEndingNewline(string) {
            return string[string.length - 1] === "\n" ? string.slice(0, -1) : string;
        }
        function foldString(string, width) {
            var lineRe = /(\n+)([^\n]*)/g;
            var result = function() {
                var nextLF = string.indexOf("\n");
                nextLF = nextLF !== -1 ? nextLF : string.length;
                lineRe.lastIndex = nextLF;
                return foldLine(string.slice(0, nextLF), width);
            }();
            var prevMoreIndented = string[0] === "\n" || string[0] === " ";
            var moreIndented;
            var match;
            while (match = lineRe.exec(string)) {
                var prefix = match[1];
                var line = match[2];
                moreIndented = line[0] === " ";
                result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width);
                prevMoreIndented = moreIndented;
            }
            return result;
        }
        function foldLine(line, width) {
            if (line === "" || line[0] === " ") return line;
            var breakRe = / [^ ]/g;
            var match;
            var start = 0;
            var end;
            var curr = 0;
            var next = 0;
            var result = "";
            while (match = breakRe.exec(line)) {
                next = match.index;
                if (next - start > width) {
                    end = curr > start ? curr : next;
                    result += "\n" + line.slice(start, end);
                    start = end + 1;
                }
                curr = next;
            }
            result += "\n";
            if (line.length - start > width && curr > start) {
                result += line.slice(start, curr) + "\n" + line.slice(curr + 1);
            } else {
                result += line.slice(start);
            }
            return result.slice(1);
        }
        function escapeString(string) {
            var result = "";
            var char = 0;
            for (var i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
                char = codePointAt(string, i);
                var escapeSeq = ESCAPE_SEQUENCES[char];
                if (!escapeSeq && isPrintable(char)) {
                    result += string[i];
                    if (char >= 65536) result += string[i + 1];
                } else {
                    result += escapeSeq || encodeHex(char);
                }
            }
            return result;
        }
        function writeFlowSequence(state, level, object) {
            var _result = "";
            var _tag = state.tag;
            for (var index = 0, length = object.length; index < length; index += 1) {
                var value = object[index];
                if (state.replacer) {
                    value = state.replacer.call(object, String(index), value);
                }
                if (writeNode(state, level, value, false, false) || typeof value === "undefined" && writeNode(state, level, null, false, false)) {
                    if (_result !== "") _result += "," + (!state.condenseFlow ? " " : "");
                    _result += state.dump;
                }
            }
            state.tag = _tag;
            state.dump = "[" + _result + "]";
        }
        function writeBlockSequence(state, level, object, compact) {
            var _result = "";
            var _tag = state.tag;
            for (var index = 0, length = object.length; index < length; index += 1) {
                var value = object[index];
                if (state.replacer) {
                    value = state.replacer.call(object, String(index), value);
                }
                if (writeNode(state, level + 1, value, true, true, false, true) || typeof value === "undefined" && writeNode(state, level + 1, null, true, true, false, true)) {
                    if (!compact || _result !== "") {
                        _result += generateNextLine(state, level);
                    }
                    if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
                        _result += "-";
                    } else {
                        _result += "- ";
                    }
                    _result += state.dump;
                }
            }
            state.tag = _tag;
            state.dump = _result || "[]";
        }
        function writeFlowMapping(state, level, object) {
            var _result = "";
            var _tag = state.tag;
            var objectKeyList = Object.keys(object);
            for (var index = 0, length = objectKeyList.length; index < length; index += 1) {
                var pairBuffer = "";
                if (_result !== "") pairBuffer += ", ";
                if (state.condenseFlow) pairBuffer += '"';
                var objectKey = objectKeyList[index];
                var objectValue = object[objectKey];
                if (state.replacer) {
                    objectValue = state.replacer.call(object, objectKey, objectValue);
                }
                if (!writeNode(state, level, objectKey, false, false)) {
                    continue;
                }
                if (state.dump.length > 1024) pairBuffer += "? ";
                pairBuffer += state.dump + (state.condenseFlow ? '"' : "") + ":" + (state.condenseFlow ? "" : " ");
                if (!writeNode(state, level, objectValue, false, false)) {
                    continue;
                }
                pairBuffer += state.dump;
                _result += pairBuffer;
            }
            state.tag = _tag;
            state.dump = "{" + _result + "}";
        }
        function writeBlockMapping(state, level, object, compact) {
            var _result = "";
            var _tag = state.tag;
            var objectKeyList = Object.keys(object);
            if (state.sortKeys === true) {
                objectKeyList.sort();
            } else if (typeof state.sortKeys === "function") {
                objectKeyList.sort(state.sortKeys);
            } else if (state.sortKeys) {
                throw new YAMLException2("sortKeys must be a boolean or a function");
            }
            for (var index = 0, length = objectKeyList.length; index < length; index += 1) {
                var pairBuffer = "";
                if (!compact || _result !== "") {
                    pairBuffer += generateNextLine(state, level);
                }
                var objectKey = objectKeyList[index];
                var objectValue = object[objectKey];
                if (state.replacer) {
                    objectValue = state.replacer.call(object, objectKey, objectValue);
                }
                if (!writeNode(state, level + 1, objectKey, true, true, true)) {
                    continue;
                }
                var explicitPair = state.tag !== null && state.tag !== "?" || state.dump && state.dump.length > 1024;
                if (explicitPair) {
                    if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
                        pairBuffer += "?";
                    } else {
                        pairBuffer += "? ";
                    }
                }
                pairBuffer += state.dump;
                if (explicitPair) {
                    pairBuffer += generateNextLine(state, level);
                }
                if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
                    continue;
                }
                if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
                    pairBuffer += ":";
                } else {
                    pairBuffer += ": ";
                }
                pairBuffer += state.dump;
                _result += pairBuffer;
            }
            state.tag = _tag;
            state.dump = _result || "{}";
        }
        function detectType(state, object, explicit) {
            var typeList = explicit ? state.explicitTypes : state.implicitTypes;
            for (var index = 0, length = typeList.length; index < length; index += 1) {
                var type2 = typeList[index];
                if ((type2.instanceOf || type2.predicate) && (!type2.instanceOf || _typeof(object) === "object" && object instanceof type2.instanceOf) && (!type2.predicate || type2.predicate(object))) {
                    if (explicit) {
                        if (type2.multi && type2.representName) {
                            state.tag = type2.representName(object);
                        } else {
                            state.tag = type2.tag;
                        }
                    } else {
                        state.tag = "?";
                    }
                    if (type2.represent) {
                        var style = state.styleMap[type2.tag] || type2.defaultStyle;
                        var _result = void 0;
                        if (_toString.call(type2.represent) === "[object Function]") {
                            _result = type2.represent(object, style);
                        } else if (_hasOwnProperty.call(type2.represent, style)) {
                            _result = type2.represent[style](object, style);
                        } else {
                            throw new YAMLException2("!<" + type2.tag + '> tag resolver accepts not "' + style + '" style');
                        }
                        state.dump = _result;
                    }
                    return true;
                }
            }
            return false;
        }
        function writeNode(state, level, object, block, compact, iskey, isblockseq) {
            state.tag = null;
            state.dump = object;
            if (!detectType(state, object, false)) {
                detectType(state, object, true);
            }
            var type2 = _toString.call(state.dump);
            var inblock = block;
            if (block) {
                block = state.flowLevel < 0 || state.flowLevel > level;
            }
            var objectOrArray = type2 === "[object Object]" || type2 === "[object Array]";
            var duplicateIndex;
            var duplicate;
            if (objectOrArray) {
                duplicateIndex = state.duplicates.indexOf(object);
                duplicate = duplicateIndex !== -1;
            }
            if (state.tag !== null && state.tag !== "?" || duplicate || state.indent !== 2 && level > 0) {
                compact = false;
            }
            if (duplicate && state.usedDuplicates[duplicateIndex]) {
                state.dump = "*ref_" + duplicateIndex;
            } else {
                if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
                    state.usedDuplicates[duplicateIndex] = true;
                }
                if (type2 === "[object Object]") {
                    if (block && Object.keys(state.dump).length !== 0) {
                        writeBlockMapping(state, level, state.dump, compact);
                        if (duplicate) {
                            state.dump = "&ref_" + duplicateIndex + state.dump;
                        }
                    } else {
                        writeFlowMapping(state, level, state.dump);
                        if (duplicate) {
                            state.dump = "&ref_" + duplicateIndex + " " + state.dump;
                        }
                    }
                } else if (type2 === "[object Array]") {
                    if (block && state.dump.length !== 0) {
                        if (state.noArrayIndent && !isblockseq && level > 0) {
                            writeBlockSequence(state, level - 1, state.dump, compact);
                        } else {
                            writeBlockSequence(state, level, state.dump, compact);
                        }
                        if (duplicate) {
                            state.dump = "&ref_" + duplicateIndex + state.dump;
                        }
                    } else {
                        writeFlowSequence(state, level, state.dump);
                        if (duplicate) {
                            state.dump = "&ref_" + duplicateIndex + " " + state.dump;
                        }
                    }
                } else if (type2 === "[object String]") {
                    if (state.tag !== "?") {
                        writeScalar(state, state.dump, level, iskey, inblock);
                    }
                } else if (type2 === "[object Undefined]") {
                    return false;
                } else {
                    if (state.skipInvalid) return false;
                    throw new YAMLException2("unacceptable kind of an object to dump " + type2);
                }
                if (state.tag !== null && state.tag !== "?") {
                    var tagStr = encodeURI(state.tag[0] === "!" ? state.tag.slice(1) : state.tag).replace(/!/g, "%21");
                    if (state.tag[0] === "!") {
                        tagStr = "!" + tagStr;
                    } else if (tagStr.slice(0, 18) === "tag:yaml.org,2002:") {
                        tagStr = "!!" + tagStr.slice(18);
                    } else {
                        tagStr = "!<" + tagStr + ">";
                    }
                    state.dump = tagStr + " " + state.dump;
                }
            }
            return true;
        }
        function getDuplicateReferences(object, state) {
            var objects = [];
            var duplicatesIndexes = [];
            inspectNode(object, objects, duplicatesIndexes);
            var length = duplicatesIndexes.length;
            for (var index = 0; index < length; index += 1) {
                state.duplicates.push(objects[duplicatesIndexes[index]]);
            }
            state.usedDuplicates = new Array(length);
        }
        function inspectNode(object, objects, duplicatesIndexes) {
            if (object !== null && _typeof(object) === "object") {
                var index = objects.indexOf(object);
                if (index !== -1) {
                    if (duplicatesIndexes.indexOf(index) === -1) {
                        duplicatesIndexes.push(index);
                    }
                } else {
                    objects.push(object);
                    if (Array.isArray(object)) {
                        for (var i = 0, length = object.length; i < length; i += 1) {
                            inspectNode(object[i], objects, duplicatesIndexes);
                        }
                    } else {
                        var objectKeyList = Object.keys(object);
                        for (var _i = 0, _length = objectKeyList.length; _i < _length; _i += 1) {
                            inspectNode(object[objectKeyList[_i]], objects, duplicatesIndexes);
                        }
                    }
                }
            }
        }
        function dump2(input, options) {
            options = options || {};
            var state = new State(options);
            if (!state.noRefs) getDuplicateReferences(input, state);
            var value = input;
            if (state.replacer) {
                value = state.replacer.call({
                    "": value
                }, "", value);
            }
            if (writeNode(state, 0, value, true, true)) return state.dump + "\n";
            return "";
        }
        dumper.dump = dump2;
        return dumper;
    }
    var hasRequiredJsYaml;
    function requireJsYaml() {
        if (hasRequiredJsYaml) return jsYaml;
        hasRequiredJsYaml = 1;
        var loader2 = requireLoader();
        var dumper2 = requireDumper();
        function renamed(from, to) {
            return function() {
                throw new Error("Function yaml." + from + " is removed in js-yaml 4. Use yaml." + to + " instead, which is now safe by default.");
            };
        }
        jsYaml.Type = requireType();
        jsYaml.Schema = requireSchema();
        jsYaml.FAILSAFE_SCHEMA = requireFailsafe();
        jsYaml.JSON_SCHEMA = requireJson();
        jsYaml.CORE_SCHEMA = requireCore();
        jsYaml.DEFAULT_SCHEMA = require_default();
        jsYaml.load = loader2.load;
        jsYaml.loadAll = loader2.loadAll;
        jsYaml.dump = dumper2.dump;
        jsYaml.YAMLException = requireException();
        jsYaml.types = {
            binary: requireBinary(),
            float: requireFloat(),
            map: requireMap(),
            null: require_null(),
            pairs: requirePairs(),
            set: requireSet(),
            timestamp: requireTimestamp(),
            bool: requireBool(),
            int: requireInt(),
            merge: requireMerge(),
            omap: requireOmap(),
            seq: requireSeq(),
            str: requireStr()
        };
        jsYaml.safeLoad = renamed("safeLoad", "load");
        jsYaml.safeLoadAll = renamed("safeLoadAll", "loadAll");
        jsYaml.safeDump = renamed("safeDump", "dump");
        return jsYaml;
    }
    var jsYamlExports = requireJsYaml();
    var yaml = getDefaultExportFromCjs(jsYamlExports);
    var Type = yaml.Type, Schema = yaml.Schema, FAILSAFE_SCHEMA = yaml.FAILSAFE_SCHEMA, JSON_SCHEMA = yaml.JSON_SCHEMA, CORE_SCHEMA = yaml.CORE_SCHEMA, DEFAULT_SCHEMA = yaml.DEFAULT_SCHEMA, load = yaml.load, loadAll = yaml.loadAll, dump = yaml.dump, YAMLException = yaml.YAMLException, types = yaml.types, safeLoad = yaml.safeLoad, safeLoadAll = yaml.safeLoadAll, safeDump = yaml.safeDump;
    exports2.CORE_SCHEMA = CORE_SCHEMA;
    exports2.DEFAULT_SCHEMA = DEFAULT_SCHEMA;
    exports2.FAILSAFE_SCHEMA = FAILSAFE_SCHEMA;
    exports2.JSON_SCHEMA = JSON_SCHEMA;
    exports2.Schema = Schema;
    exports2.Type = Type;
    exports2.YAMLException = YAMLException;
    exports2.default = yaml;
    exports2.dump = dump;
    exports2.load = load;
    exports2.loadAll = loadAll;
    exports2.safeDump = safeDump;
    exports2.safeLoad = safeLoad;
    exports2.safeLoadAll = safeLoadAll;
    exports2.types = types;
    Object.defineProperty(exports2, "__esModule", {
        value: true
    });
});
//# sourceMappingURL=js-yaml.js.map
{"version":3,"file":"js-yaml.js","sources":["../lib/common.js","../lib/exception.js","../lib/snippet.js","../lib/type.js","../lib/schema.js","../lib/type/str.js","../lib/type/seq.js","../lib/type/map.js","../lib/schema/failsafe.js","../lib/type/null.js","../lib/type/bool.js","../lib/type/int.js","../lib/type/float.js","../lib/schema/json.js","../lib/schema/core.js","../lib/type/timestamp.js","../lib/type/merge.js","../lib/type/binary.js","../lib/type/omap.js","../lib/type/pairs.js","../lib/type/set.js","../lib/schema/default.js","../lib/loader.js","../lib/dumper.js","../index.js","../lib/index_vite_proxy.tmp.mjs"],"sourcesContent":["'use strict'\n\nfunction isNothing (subject) {\n  return (typeof subject === 'undefined') || (subject === null)\n}\n\nfunction isObject (subject) {\n  return (typeof subject === 'object') && (subject !== null)\n}\n\nfunction toArray (sequence) {\n  if (Array.isArray(sequence)) return sequence\n  else if (isNothing(sequence)) return []\n\n  return [sequence]\n}\n\nfunction extend (target, source) {\n  if (source) {\n    const sourceKeys = Object.keys(source)\n\n    for (let index = 0, length = sourceKeys.length; index < length; index += 1) {\n      const key = sourceKeys[index]\n      target[key] = source[key]\n    }\n  }\n\n  return target\n}\n\nfunction repeat (string, count) {\n  let result = ''\n\n  for (let cycle = 0; cycle < count; cycle += 1) {\n    result += string\n  }\n\n  return result\n}\n\nfunction isNegativeZero (number) {\n  return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number)\n}\n\nmodule.exports.isNothing = isNothing\nmodule.exports.isObject = isObject\nmodule.exports.toArray = toArray\nmodule.exports.repeat = repeat\nmodule.exports.isNegativeZero = isNegativeZero\nmodule.exports.extend = extend\n","// YAML error class. http://stackoverflow.com/questions/8458984\n//\n'use strict'\n\nfunction formatError (exception, compact) {\n  let where = ''\n  const message = exception.reason || '(unknown reason)'\n\n  if (!exception.mark) return message\n\n  if (exception.mark.name) {\n    where += 'in \"' + exception.mark.name + '\" '\n  }\n\n  where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')'\n\n  if (!compact && exception.mark.snippet) {\n    where += '\\n\\n' + exception.mark.snippet\n  }\n\n  return message + ' ' + where\n}\n\nfunction YAMLException (reason, mark) {\n  // Super constructor\n  Error.call(this)\n\n  this.name = 'YAMLException'\n  this.reason = reason\n  this.mark = mark\n  this.message = formatError(this, false)\n\n  // Include stack trace in error object\n  if (Error.captureStackTrace) {\n    // Chrome and NodeJS\n    Error.captureStackTrace(this, this.constructor)\n  } else {\n    // FF, IE 10+ and Safari 6+. Fallback for others\n    this.stack = (new Error()).stack || ''\n  }\n}\n\n// Inherit from Error\nYAMLException.prototype = Object.create(Error.prototype)\nYAMLException.prototype.constructor = YAMLException\n\nYAMLException.prototype.toString = function toString (compact) {\n  return this.name + ': ' + formatError(this, compact)\n}\n\nmodule.exports = YAMLException\n","'use strict'\n\nconst common = require('./common')\n\n// get snippet for a single line, respecting maxLength\nfunction getLine (buffer, lineStart, lineEnd, position, maxLineLength) {\n  let head = ''\n  let tail = ''\n  const maxHalfLength = Math.floor(maxLineLength / 2) - 1\n\n  if (position - lineStart > maxHalfLength) {\n    head = ' ... '\n    lineStart = position - maxHalfLength + head.length\n  }\n\n  if (lineEnd - position > maxHalfLength) {\n    tail = ' ...'\n    lineEnd = position + maxHalfLength - tail.length\n  }\n\n  return {\n    str: head + buffer.slice(lineStart, lineEnd).replace(/\\t/g, '→') + tail,\n    pos: position - lineStart + head.length // relative position\n  }\n}\n\nfunction padStart (string, max) {\n  return common.repeat(' ', max - string.length) + string\n}\n\nfunction makeSnippet (mark, options) {\n  options = Object.create(options || null)\n\n  if (!mark.buffer) return null\n\n  if (!options.maxLength) options.maxLength = 79\n  if (typeof options.indent !== 'number') options.indent = 1\n  if (typeof options.linesBefore !== 'number') options.linesBefore = 3\n  if (typeof options.linesAfter !== 'number') options.linesAfter = 2\n\n  const re = /\\r?\\n|\\r|\\0/g\n  const lineStarts = [0]\n  const lineEnds = []\n  let match\n  let foundLineNo = -1\n\n  while ((match = re.exec(mark.buffer))) {\n    lineEnds.push(match.index)\n    lineStarts.push(match.index + match[0].length)\n\n    if (mark.position <= match.index && foundLineNo < 0) {\n      foundLineNo = lineStarts.length - 2\n    }\n  }\n\n  if (foundLineNo < 0) foundLineNo = lineStarts.length - 1\n\n  let result = ''\n  const lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length\n  const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3)\n\n  for (let i = 1; i <= options.linesBefore; i++) {\n    if (foundLineNo - i < 0) break\n    const line = getLine(\n      mark.buffer,\n      lineStarts[foundLineNo - i],\n      lineEnds[foundLineNo - i],\n      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),\n      maxLineLength\n    )\n    result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) +\n      ' | ' + line.str + '\\n' + result\n  }\n\n  const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength)\n  result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) +\n    ' | ' + line.str + '\\n'\n  result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\\n'\n\n  for (let i = 1; i <= options.linesAfter; i++) {\n    if (foundLineNo + i >= lineEnds.length) break\n    const line = getLine(\n      mark.buffer,\n      lineStarts[foundLineNo + i],\n      lineEnds[foundLineNo + i],\n      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),\n      maxLineLength\n    )\n    result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) +\n      ' | ' + line.str + '\\n'\n  }\n\n  return result.replace(/\\n$/, '')\n}\n\nmodule.exports = makeSnippet\n","'use strict'\n\nconst YAMLException = require('./exception')\n\nconst TYPE_CONSTRUCTOR_OPTIONS = [\n  'kind',\n  'multi',\n  'resolve',\n  'construct',\n  'instanceOf',\n  'predicate',\n  'represent',\n  'representName',\n  'defaultStyle',\n  'styleAliases'\n]\n\nconst YAML_NODE_KINDS = [\n  'scalar',\n  'sequence',\n  'mapping'\n]\n\nfunction compileStyleAliases (map) {\n  const result = {}\n\n  if (map !== null) {\n    Object.keys(map).forEach(function (style) {\n      map[style].forEach(function (alias) {\n        result[String(alias)] = style\n      })\n    })\n  }\n\n  return result\n}\n\nfunction Type (tag, options) {\n  options = options || {}\n\n  Object.keys(options).forEach(function (name) {\n    if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {\n      throw new YAMLException('Unknown option \"' + name + '\" is met in definition of \"' + tag + '\" YAML type.')\n    }\n  })\n\n  // TODO: Add tag format check.\n  this.options = options // keep original options in case user wants to extend this type later\n  this.tag = tag\n  this.kind = options['kind'] || null\n  this.resolve = options['resolve'] || function () { return true }\n  this.construct = options['construct'] || function (data) { return data }\n  this.instanceOf = options['instanceOf'] || null\n  this.predicate = options['predicate'] || null\n  this.represent = options['represent'] || null\n  this.representName = options['representName'] || null\n  this.defaultStyle = options['defaultStyle'] || null\n  this.multi = options['multi'] || false\n  this.styleAliases = compileStyleAliases(options['styleAliases'] || null)\n\n  if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {\n    throw new YAMLException('Unknown kind \"' + this.kind + '\" is specified for \"' + tag + '\" YAML type.')\n  }\n}\n\nmodule.exports = Type\n","'use strict'\n\nconst YAMLException = require('./exception')\nconst Type = require('./type')\n\nfunction compileList (schema, name) {\n  const result = []\n\n  schema[name].forEach(function (currentType) {\n    let newIndex = result.length\n\n    result.forEach(function (previousType, previousIndex) {\n      if (previousType.tag === currentType.tag &&\n          previousType.kind === currentType.kind &&\n          previousType.multi === currentType.multi) {\n        newIndex = previousIndex\n      }\n    })\n\n    result[newIndex] = currentType\n  })\n\n  return result\n}\n\nfunction compileMap (/* lists... */) {\n  const result = {\n    scalar: {},\n    sequence: {},\n    mapping: {},\n    fallback: {},\n    multi: {\n      scalar: [],\n      sequence: [],\n      mapping: [],\n      fallback: []\n    }\n  }\n  function collectType (type) {\n    if (type.multi) {\n      result.multi[type.kind].push(type)\n      result.multi['fallback'].push(type)\n    } else {\n      result[type.kind][type.tag] = result['fallback'][type.tag] = type\n    }\n  }\n\n  for (let index = 0, length = arguments.length; index < length; index += 1) {\n    arguments[index].forEach(collectType)\n  }\n  return result\n}\n\nfunction Schema (definition) {\n  return this.extend(definition)\n}\n\nSchema.prototype.extend = function extend (definition) {\n  let implicit = []\n  let explicit = []\n\n  if (definition instanceof Type) {\n    // Schema.extend(type)\n    explicit.push(definition)\n  } else if (Array.isArray(definition)) {\n    // Schema.extend([ type1, type2, ... ])\n    explicit = explicit.concat(definition)\n  } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {\n    // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] })\n    if (definition.implicit) implicit = implicit.concat(definition.implicit)\n    if (definition.explicit) explicit = explicit.concat(definition.explicit)\n  } else {\n    throw new YAMLException('Schema.extend argument should be a Type, [ Type ], ' +\n      'or a schema definition ({ implicit: [...], explicit: [...] })')\n  }\n\n  implicit.forEach(function (type) {\n    if (!(type instanceof Type)) {\n      throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')\n    }\n\n    if (type.loadKind && type.loadKind !== 'scalar') {\n      throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.')\n    }\n\n    if (type.multi) {\n      throw new YAMLException('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.')\n    }\n  })\n\n  explicit.forEach(function (type) {\n    if (!(type instanceof Type)) {\n      throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')\n    }\n  })\n\n  const result = Object.create(Schema.prototype)\n\n  result.implicit = (this.implicit || []).concat(implicit)\n  result.explicit = (this.explicit || []).concat(explicit)\n\n  result.compiledImplicit = compileList(result, 'implicit')\n  result.compiledExplicit = compileList(result, 'explicit')\n  result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit)\n\n  return result\n}\n\nmodule.exports = Schema\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:str', {\n  kind: 'scalar',\n  construct: function (data) { return data !== null ? data : '' }\n})\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:seq', {\n  kind: 'sequence',\n  construct: function (data) { return data !== null ? data : [] }\n})\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:map', {\n  kind: 'mapping',\n  construct: function (data) { return data !== null ? data : {} }\n})\n","// Standard YAML's Failsafe schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2802346\n\n'use strict'\n\nconst Schema = require('../schema')\n\nmodule.exports = new Schema({\n  explicit: [\n    require('../type/str'),\n    require('../type/seq'),\n    require('../type/map')\n  ]\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlNull (data) {\n  if (data === null) return true\n\n  const max = data.length\n\n  return (max === 1 && data === '~') ||\n         (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'))\n}\n\nfunction constructYamlNull () {\n  return null\n}\n\nfunction isNull (object) {\n  return object === null\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:null', {\n  kind: 'scalar',\n  resolve: resolveYamlNull,\n  construct: constructYamlNull,\n  predicate: isNull,\n  represent: {\n    canonical: function () { return '~' },\n    lowercase: function () { return 'null' },\n    uppercase: function () { return 'NULL' },\n    camelcase: function () { return 'Null' },\n    empty: function () { return '' }\n  },\n  defaultStyle: 'lowercase'\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlBoolean (data) {\n  if (data === null) return false\n\n  const max = data.length\n\n  return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||\n         (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'))\n}\n\nfunction constructYamlBoolean (data) {\n  return data === 'true' ||\n         data === 'True' ||\n         data === 'TRUE'\n}\n\nfunction isBoolean (object) {\n  return Object.prototype.toString.call(object) === '[object Boolean]'\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:bool', {\n  kind: 'scalar',\n  resolve: resolveYamlBoolean,\n  construct: constructYamlBoolean,\n  predicate: isBoolean,\n  represent: {\n    lowercase: function (object) { return object ? 'true' : 'false' },\n    uppercase: function (object) { return object ? 'TRUE' : 'FALSE' },\n    camelcase: function (object) { return object ? 'True' : 'False' }\n  },\n  defaultStyle: 'lowercase'\n})\n","'use strict'\n\nconst common = require('../common')\nconst Type = require('../type')\n\nfunction isHexCode (c) {\n  return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) ||\n         ((c >= 0x41/* A */) && (c <= 0x46/* F */)) ||\n         ((c >= 0x61/* a */) && (c <= 0x66/* f */))\n}\n\nfunction isOctCode (c) {\n  return ((c >= 0x30/* 0 */) && (c <= 0x37/* 7 */))\n}\n\nfunction isDecCode (c) {\n  return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */))\n}\n\nfunction resolveYamlInteger (data) {\n  if (data === null) return false\n\n  const max = data.length\n  let index = 0\n  let hasDigits = false\n\n  if (!max) return false\n\n  let ch = data[index]\n\n  // sign\n  if (ch === '-' || ch === '+') {\n    ch = data[++index]\n  }\n\n  if (ch === '0') {\n    // 0\n    if (index + 1 === max) return true\n    ch = data[++index]\n\n    // base 2, base 8, base 16\n\n    if (ch === 'b') {\n      // base 2\n      index++\n\n      for (; index < max; index++) {\n        ch = data[index]\n        if (ch !== '0' && ch !== '1') return false\n        hasDigits = true\n      }\n      return hasDigits && isFinite(parseYamlInteger(data))\n    }\n\n    if (ch === 'x') {\n      // base 16\n      index++\n\n      for (; index < max; index++) {\n        if (!isHexCode(data.charCodeAt(index))) return false\n        hasDigits = true\n      }\n      return hasDigits && isFinite(parseYamlInteger(data))\n    }\n\n    if (ch === 'o') {\n      // base 8\n      index++\n\n      for (; index < max; index++) {\n        if (!isOctCode(data.charCodeAt(index))) return false\n        hasDigits = true\n      }\n      return hasDigits && isFinite(parseYamlInteger(data))\n    }\n  }\n\n  // base 10 (except 0)\n\n  for (; index < max; index++) {\n    if (!isDecCode(data.charCodeAt(index))) {\n      return false\n    }\n    hasDigits = true\n  }\n\n  if (!hasDigits) return false\n\n  return isFinite(parseYamlInteger(data))\n}\n\nfunction parseYamlInteger (data) {\n  let value = data\n  let sign = 1\n\n  let ch = value[0]\n\n  if (ch === '-' || ch === '+') {\n    if (ch === '-') sign = -1\n    value = value.slice(1)\n    ch = value[0]\n  }\n\n  if (value === '0') return 0\n\n  if (ch === '0') {\n    if (value[1] === 'b') return sign * parseInt(value.slice(2), 2)\n    if (value[1] === 'x') return sign * parseInt(value.slice(2), 16)\n    if (value[1] === 'o') return sign * parseInt(value.slice(2), 8)\n  }\n\n  return sign * parseInt(value, 10)\n}\n\nfunction constructYamlInteger (data) {\n  return parseYamlInteger(data)\n}\n\nfunction isInteger (object) {\n  return (Object.prototype.toString.call(object)) === '[object Number]' &&\n         (object % 1 === 0 && !common.isNegativeZero(object))\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:int', {\n  kind: 'scalar',\n  resolve: resolveYamlInteger,\n  construct: constructYamlInteger,\n  predicate: isInteger,\n  represent: {\n    binary: function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1) },\n    octal: function (obj) { return obj >= 0 ? '0o' + obj.toString(8) : '-0o' + obj.toString(8).slice(1) },\n    decimal: function (obj) { return obj.toString(10) },\n    hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() : '-0x' + obj.toString(16).toUpperCase().slice(1) }\n  },\n  defaultStyle: 'decimal',\n  styleAliases: {\n    binary: [2, 'bin'],\n    octal: [8, 'oct'],\n    decimal: [10, 'dec'],\n    hexadecimal: [16, 'hex']\n  }\n})\n","'use strict'\n\nconst common = require('../common')\nconst Type = require('../type')\n\nconst YAML_FLOAT_PATTERN = new RegExp(\n  // 2.5e4, 2.5 and integers\n  '^(?:[-+]?(?:[0-9]+)(?:\\\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?' +\n  // .2e4, .2\n  // special case, seems not from spec\n  '|\\\\.[0-9]+(?:[eE][-+]?[0-9]+)?' +\n  // .inf\n  '|[-+]?\\\\.(?:inf|Inf|INF)' +\n  // .nan\n  '|\\\\.(?:nan|NaN|NAN))$')\n\nconst YAML_FLOAT_SPECIAL_PATTERN = new RegExp(\n  '^(?:' +\n  // .inf\n  '[-+]?\\\\.(?:inf|Inf|INF)' +\n  // .nan\n  '|\\\\.(?:nan|NaN|NAN))$')\n\nfunction resolveYamlFloat (data) {\n  if (data === null) return false\n\n  if (!YAML_FLOAT_PATTERN.test(data)) {\n    return false\n  }\n\n  if (isFinite(parseFloat(data, 10))) {\n    return true\n  }\n\n  return YAML_FLOAT_SPECIAL_PATTERN.test(data)\n}\n\nfunction constructYamlFloat (data) {\n  let value = data.toLowerCase()\n  const sign = value[0] === '-' ? -1 : 1\n\n  if ('+-'.indexOf(value[0]) >= 0) {\n    value = value.slice(1)\n  }\n\n  if (value === '.inf') {\n    return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY\n  } else if (value === '.nan') {\n    return NaN\n  }\n  return sign * parseFloat(value, 10)\n}\n\nconst SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/\n\nfunction representYamlFloat (object, style) {\n  if (isNaN(object)) {\n    switch (style) {\n      case 'lowercase': return '.nan'\n      case 'uppercase': return '.NAN'\n      case 'camelcase': return '.NaN'\n    }\n  } else if (Number.POSITIVE_INFINITY === object) {\n    switch (style) {\n      case 'lowercase': return '.inf'\n      case 'uppercase': return '.INF'\n      case 'camelcase': return '.Inf'\n    }\n  } else if (Number.NEGATIVE_INFINITY === object) {\n    switch (style) {\n      case 'lowercase': return '-.inf'\n      case 'uppercase': return '-.INF'\n      case 'camelcase': return '-.Inf'\n    }\n  } else if (common.isNegativeZero(object)) {\n    return '-0.0'\n  }\n\n  const res = object.toString(10)\n\n  // JS stringifier can build scientific format without dots: 5e-100,\n  // while YAML requres dot: 5.e-100. Fix it with simple hack\n\n  return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res\n}\n\nfunction isFloat (object) {\n  return (Object.prototype.toString.call(object) === '[object Number]') &&\n         (object % 1 !== 0 || common.isNegativeZero(object))\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:float', {\n  kind: 'scalar',\n  resolve: resolveYamlFloat,\n  construct: constructYamlFloat,\n  predicate: isFloat,\n  represent: representYamlFloat,\n  defaultStyle: 'lowercase'\n})\n","// Standard YAML's JSON schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2803231\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, this schema is not such strict as defined in the YAML specification.\n// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.\n\n'use strict'\n\nmodule.exports = require('./failsafe').extend({\n  implicit: [\n    require('../type/null'),\n    require('../type/bool'),\n    require('../type/int'),\n    require('../type/float')\n  ]\n})\n","// Standard YAML's Core schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2804923\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, Core schema has no distinctions from JSON schema is JS-YAML.\n\n'use strict'\n\nmodule.exports = require('./json')\n","'use strict'\n\nconst Type = require('../type')\n\nconst YAML_DATE_REGEXP = new RegExp(\n  '^([0-9][0-9][0-9][0-9])' + // [1] year\n  '-([0-9][0-9])' + // [2] month\n  '-([0-9][0-9])$')                   // [3] day\n\nconst YAML_TIMESTAMP_REGEXP = new RegExp(\n  '^([0-9][0-9][0-9][0-9])' + // [1] year\n  '-([0-9][0-9]?)' + // [2] month\n  '-([0-9][0-9]?)' + // [3] day\n  '(?:[Tt]|[ \\\\t]+)' + // ...\n  '([0-9][0-9]?)' + // [4] hour\n  ':([0-9][0-9])' + // [5] minute\n  ':([0-9][0-9])' + // [6] second\n  '(?:\\\\.([0-9]*))?' + // [7] fraction\n  '(?:[ \\\\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tzHour\n  '(?::([0-9][0-9]))?))?$')           // [11] tzMinute\n\nfunction resolveYamlTimestamp (data) {\n  if (data === null) return false\n  if (YAML_DATE_REGEXP.exec(data) !== null) return true\n  if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true\n  return false\n}\n\nfunction constructYamlTimestamp (data) {\n  let fraction = 0\n  let delta = null\n\n  let match = YAML_DATE_REGEXP.exec(data)\n  if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data)\n\n  if (match === null) throw new Error('Date resolve error')\n\n  // match: [1] year [2] month [3] day\n\n  const year = +(match[1])\n  const month = +(match[2]) - 1 // JS month starts with 0\n  const day = +(match[3])\n\n  if (!match[4]) { // no hour\n    return new Date(Date.UTC(year, month, day))\n  }\n\n  // match: [4] hour [5] minute [6] second [7] fraction\n\n  const hour = +(match[4])\n  const minute = +(match[5])\n  const second = +(match[6])\n\n  if (match[7]) {\n    fraction = match[7].slice(0, 3)\n    while (fraction.length < 3) { // milli-seconds\n      fraction += '0'\n    }\n    fraction = +fraction\n  }\n\n  // match: [8] tz [9] tz_sign [10] tzHour [11] tzMinute\n\n  if (match[9]) {\n    const tzHour = +(match[10])\n    const tzMinute = +(match[11] || 0)\n    delta = (tzHour * 60 + tzMinute) * 60000 // delta in mili-seconds\n    if (match[9] === '-') delta = -delta\n  }\n\n  const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction))\n\n  if (delta) date.setTime(date.getTime() - delta)\n\n  return date\n}\n\nfunction representYamlTimestamp (object /*, style */) {\n  return object.toISOString()\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:timestamp', {\n  kind: 'scalar',\n  resolve: resolveYamlTimestamp,\n  construct: constructYamlTimestamp,\n  instanceOf: Date,\n  represent: representYamlTimestamp\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlMerge (data) {\n  return data === '<<' || data === null\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:merge', {\n  kind: 'scalar',\n  resolve: resolveYamlMerge\n})\n","'use strict'\n\nconst Type = require('../type')\n\n// [ 64, 65, 66 ] -> [ padding, CR, LF ]\nconst BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\\n\\r'\n\nfunction resolveYamlBinary (data) {\n  if (data === null) return false\n\n  let bitlen = 0\n  const max = data.length\n  const map = BASE64_MAP\n\n  // Convert one by one.\n  for (let idx = 0; idx < max; idx++) {\n    const code = map.indexOf(data.charAt(idx))\n\n    // Skip CR/LF\n    if (code > 64) continue\n\n    // Fail on illegal characters\n    if (code < 0) return false\n\n    bitlen += 6\n  }\n\n  // If there are any bits left, source was corrupted\n  return (bitlen % 8) === 0\n}\n\nfunction constructYamlBinary (data) {\n  const input = data.replace(/[\\r\\n=]/g, '') // remove CR/LF & padding to simplify scan\n  const max = input.length\n  const map = BASE64_MAP\n  let bits = 0\n  const result = []\n\n  // Collect by 6*4 bits (3 bytes)\n\n  for (let idx = 0; idx < max; idx++) {\n    if ((idx % 4 === 0) && idx) {\n      result.push((bits >> 16) & 0xFF)\n      result.push((bits >> 8) & 0xFF)\n      result.push(bits & 0xFF)\n    }\n\n    bits = (bits << 6) | map.indexOf(input.charAt(idx))\n  }\n\n  // Dump tail\n\n  const tailbits = (max % 4) * 6\n\n  if (tailbits === 0) {\n    result.push((bits >> 16) & 0xFF)\n    result.push((bits >> 8) & 0xFF)\n    result.push(bits & 0xFF)\n  } else if (tailbits === 18) {\n    result.push((bits >> 10) & 0xFF)\n    result.push((bits >> 2) & 0xFF)\n  } else if (tailbits === 12) {\n    result.push((bits >> 4) & 0xFF)\n  }\n\n  return new Uint8Array(result)\n}\n\nfunction representYamlBinary (object /*, style */) {\n  let result = ''\n  let bits = 0\n  const max = object.length\n  const map = BASE64_MAP\n\n  // Convert every three bytes to 4 ASCII characters.\n\n  for (let idx = 0; idx < max; idx++) {\n    if ((idx % 3 === 0) && idx) {\n      result += map[(bits >> 18) & 0x3F]\n      result += map[(bits >> 12) & 0x3F]\n      result += map[(bits >> 6) & 0x3F]\n      result += map[bits & 0x3F]\n    }\n\n    bits = (bits << 8) + object[idx]\n  }\n\n  // Dump tail\n\n  const tail = max % 3\n\n  if (tail === 0) {\n    result += map[(bits >> 18) & 0x3F]\n    result += map[(bits >> 12) & 0x3F]\n    result += map[(bits >> 6) & 0x3F]\n    result += map[bits & 0x3F]\n  } else if (tail === 2) {\n    result += map[(bits >> 10) & 0x3F]\n    result += map[(bits >> 4) & 0x3F]\n    result += map[(bits << 2) & 0x3F]\n    result += map[64]\n  } else if (tail === 1) {\n    result += map[(bits >> 2) & 0x3F]\n    result += map[(bits << 4) & 0x3F]\n    result += map[64]\n    result += map[64]\n  }\n\n  return result\n}\n\nfunction isBinary (obj) {\n  return Object.prototype.toString.call(obj) === '[object Uint8Array]'\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:binary', {\n  kind: 'scalar',\n  resolve: resolveYamlBinary,\n  construct: constructYamlBinary,\n  predicate: isBinary,\n  represent: representYamlBinary\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\nconst _toString = Object.prototype.toString\n\nfunction resolveYamlOmap (data) {\n  if (data === null) return true\n\n  const objectKeys = {}\n  const object = data\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    const pair = object[index]\n    let pairHasKey = false\n\n    if (_toString.call(pair) !== '[object Object]') return false\n\n    let pairKey\n    for (pairKey in pair) {\n      if (_hasOwnProperty.call(pair, pairKey)) {\n        if (!pairHasKey) pairHasKey = true\n        else return false\n      }\n    }\n\n    if (!pairHasKey) return false\n\n    if (_hasOwnProperty.call(objectKeys, pairKey)) return false\n    Object.defineProperty(objectKeys, pairKey, { value: true })\n  }\n\n  return true\n}\n\nfunction constructYamlOmap (data) {\n  return data !== null ? data : []\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:omap', {\n  kind: 'sequence',\n  resolve: resolveYamlOmap,\n  construct: constructYamlOmap\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _toString = Object.prototype.toString\n\nfunction resolveYamlPairs (data) {\n  if (data === null) return true\n\n  const object = data\n\n  const result = new Array(object.length)\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    const pair = object[index]\n\n    if (_toString.call(pair) !== '[object Object]') return false\n\n    const keys = Object.keys(pair)\n\n    if (keys.length !== 1) return false\n\n    result[index] = [keys[0], pair[keys[0]]]\n  }\n\n  return true\n}\n\nfunction constructYamlPairs (data) {\n  if (data === null) return []\n\n  const object = data\n  const result = new Array(object.length)\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    const pair = object[index]\n\n    const keys = Object.keys(pair)\n\n    result[index] = [keys[0], pair[keys[0]]]\n  }\n\n  return result\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:pairs', {\n  kind: 'sequence',\n  resolve: resolveYamlPairs,\n  construct: constructYamlPairs\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nfunction resolveYamlSet (data) {\n  if (data === null) return true\n\n  const object = data\n\n  for (const key in object) {\n    if (_hasOwnProperty.call(object, key)) {\n      if (object[key] !== null) return false\n    }\n  }\n\n  return true\n}\n\nfunction constructYamlSet (data) {\n  return data !== null ? data : {}\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:set', {\n  kind: 'mapping',\n  resolve: resolveYamlSet,\n  construct: constructYamlSet\n})\n","// JS-YAML's default schema for `safeLoad` function.\n// It is not described in the YAML specification.\n//\n// This schema is based on standard YAML's Core schema and includes most of\n// extra types described at YAML tag repository. (http://yaml.org/type/)\n\n'use strict'\n\nmodule.exports = require('./core').extend({\n  implicit: [\n    require('../type/timestamp'),\n    require('../type/merge')\n  ],\n  explicit: [\n    require('../type/binary'),\n    require('../type/omap'),\n    require('../type/pairs'),\n    require('../type/set')\n  ]\n})\n","'use strict'\n\nconst common = require('./common')\nconst YAMLException = require('./exception')\nconst makeSnippet = require('./snippet')\nconst DEFAULT_SCHEMA = require('./schema/default')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nconst CONTEXT_FLOW_IN = 1\nconst CONTEXT_FLOW_OUT = 2\nconst CONTEXT_BLOCK_IN = 3\nconst CONTEXT_BLOCK_OUT = 4\n\nconst CHOMPING_CLIP = 1\nconst CHOMPING_STRIP = 2\nconst CHOMPING_KEEP = 3\n\n// eslint-disable-next-line no-control-regex\nconst PATTERN_NON_PRINTABLE = /[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x84\\x86-\\x9F\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/\nconst PATTERN_NON_ASCII_LINE_BREAKS = /[\\x85\\u2028\\u2029]/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_FLOW_INDICATORS = /[,\\[\\]{}]/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_TAG_URI = /^(?:!|[^,\\[\\]{}])(?:%[0-9a-f]{2}|[0-9a-z\\-#;/?:@&=+$,_.!~*'()\\[\\]])*$/i\n\nfunction _class (obj) { return Object.prototype.toString.call(obj) }\n\nfunction isEol (c) {\n  return (c === 0x0A/* LF */) || (c === 0x0D/* CR */)\n}\n\nfunction isWhiteSpace (c) {\n  return (c === 0x09/* Tab */) || (c === 0x20/* Space */)\n}\n\nfunction isWsOrEol (c) {\n  return (c === 0x09/* Tab */) ||\n         (c === 0x20/* Space */) ||\n         (c === 0x0A/* LF */) ||\n         (c === 0x0D/* CR */)\n}\n\nfunction isFlowIndicator (c) {\n  return c === 0x2C/* , */ ||\n         c === 0x5B/* [ */ ||\n         c === 0x5D/* ] */ ||\n         c === 0x7B/* { */ ||\n         c === 0x7D/* } */\n}\n\nfunction fromHexCode (c) {\n  if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {\n    return c - 0x30\n  }\n\n  const lc = c | 0x20\n\n  if ((lc >= 0x61/* a */) && (lc <= 0x66/* f */)) {\n    return lc - 0x61 + 10\n  }\n\n  return -1\n}\n\nfunction escapedHexLen (c) {\n  if (c === 0x78/* x */) { return 2 }\n  if (c === 0x75/* u */) { return 4 }\n  if (c === 0x55/* U */) { return 8 }\n  return 0\n}\n\nfunction fromDecimalCode (c) {\n  if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {\n    return c - 0x30\n  }\n\n  return -1\n}\n\nfunction simpleEscapeSequence (c) {\n  switch (c) {\n    case 0x30/* 0 */: return '\\x00'\n    case 0x61/* a */: return '\\x07'\n    case 0x62/* b */: return '\\x08'\n    case 0x74/* t */: return '\\x09'\n    case 0x09/* Tab */: return '\\x09'\n    case 0x6E/* n */: return '\\x0A'\n    case 0x76/* v */: return '\\x0B'\n    case 0x66/* f */: return '\\x0C'\n    case 0x72/* r */: return '\\x0D'\n    case 0x65/* e */: return '\\x1B'\n    case 0x20/* Space */: return ' '\n    case 0x22/* \" */: return '\\x22'\n    case 0x2F/* / */: return '/'\n    case 0x5C/* \\ */: return '\\x5C'\n    case 0x4E/* N */: return '\\x85'\n    case 0x5F/* _ */: return '\\xA0'\n    case 0x4C/* L */: return '\\u2028'\n    case 0x50/* P */: return '\\u2029'\n    default: return ''\n  }\n}\n\nfunction charFromCodepoint (c) {\n  if (c <= 0xFFFF) {\n    return String.fromCharCode(c)\n  }\n  // Encode UTF-16 surrogate pair\n  // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF\n  return String.fromCharCode(\n    ((c - 0x010000) >> 10) + 0xD800,\n    ((c - 0x010000) & 0x03FF) + 0xDC00\n  )\n}\n\n// set a property of a literal object, while protecting against prototype pollution,\n// see https://github.com/nodeca/js-yaml/issues/164 for more details\nfunction setProperty (object, key, value) {\n  // used for this specific key only because Object.defineProperty is slow\n  if (key === '__proto__') {\n    Object.defineProperty(object, key, {\n      configurable: true,\n      enumerable: true,\n      writable: true,\n      value: value\n    })\n  } else {\n    object[key] = value\n  }\n}\n\nconst simpleEscapeCheck = new Array(256) // integer, for fast access\nconst simpleEscapeMap = new Array(256)\nfor (let i = 0; i < 256; i++) {\n  simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0\n  simpleEscapeMap[i] = simpleEscapeSequence(i)\n}\n\nfunction State (input, options) {\n  this.input = input\n\n  this.filename = options['filename'] || null\n  this.schema = options['schema'] || DEFAULT_SCHEMA\n  this.onWarning = options['onWarning'] || null\n  // (Hidden) Remove? makes the loader to expect YAML 1.1 documents\n  // if such documents have no explicit %YAML directive\n  this.legacy = options['legacy'] || false\n\n  this.json = options['json'] || false\n  this.listener = options['listener'] || null\n  this.maxDepth = typeof options['maxDepth'] === 'number' ? options['maxDepth'] : 100\n  this.maxTotalMergeKeys = typeof options['maxTotalMergeKeys'] === 'number' ? options['maxTotalMergeKeys'] : 10000\n\n  this.implicitTypes = this.schema.compiledImplicit\n  this.typeMap = this.schema.compiledTypeMap\n\n  this.length = input.length\n  this.position = 0\n  this.line = 0\n  this.lineStart = 0\n  this.lineIndent = 0\n  this.depth = 0\n  this.totalMergeKeys = 0\n\n  // position of first leading tab in the current line,\n  // used to make sure there are no tabs in the indentation\n  this.firstTabInLine = -1\n\n  this.documents = []\n  this.anchorMapTransactions = []\n\n  /*\n  this.version;\n  this.checkLineBreaks;\n  this.tagMap;\n  this.anchorMap;\n  this.tag;\n  this.anchor;\n  this.kind;\n  this.result; */\n}\n\nfunction generateError (state, message) {\n  const mark = {\n    name: state.filename,\n    buffer: state.input.slice(0, -1), // omit trailing \\0\n    position: state.position,\n    line: state.line,\n    column: state.position - state.lineStart\n  }\n\n  mark.snippet = makeSnippet(mark)\n\n  return new YAMLException(message, mark)\n}\n\nfunction throwError (state, message) {\n  throw generateError(state, message)\n}\n\nfunction throwWarning (state, message) {\n  if (state.onWarning) {\n    state.onWarning.call(null, generateError(state, message))\n  }\n}\n\nfunction storeAnchor (state, name, value) {\n  const transactions = state.anchorMapTransactions\n\n  if (transactions.length !== 0) {\n    const transaction = transactions[transactions.length - 1]\n\n    if (!_hasOwnProperty.call(transaction, name)) {\n      transaction[name] = {\n        existed: _hasOwnProperty.call(state.anchorMap, name),\n        value: state.anchorMap[name]\n      }\n    }\n  }\n\n  state.anchorMap[name] = value\n}\n\nfunction beginAnchorTransaction (state) {\n  state.anchorMapTransactions.push(Object.create(null))\n}\n\nfunction commitAnchorTransaction (state) {\n  const transaction = state.anchorMapTransactions.pop()\n  const transactions = state.anchorMapTransactions\n\n  if (transactions.length === 0) return\n\n  const parent = transactions[transactions.length - 1]\n  const names = Object.keys(transaction)\n\n  for (let index = 0, length = names.length; index < length; index += 1) {\n    const name = names[index]\n\n    if (!_hasOwnProperty.call(parent, name)) {\n      parent[name] = transaction[name]\n    }\n  }\n}\n\nfunction rollbackAnchorTransaction (state) {\n  const transaction = state.anchorMapTransactions.pop()\n  const names = Object.keys(transaction)\n\n  for (let index = names.length - 1; index >= 0; index -= 1) {\n    const entry = transaction[names[index]]\n\n    if (entry.existed) {\n      state.anchorMap[names[index]] = entry.value\n    } else {\n      delete state.anchorMap[names[index]]\n    }\n  }\n}\n\nfunction snapshotState (state) {\n  return {\n    position: state.position,\n    line: state.line,\n    lineStart: state.lineStart,\n    lineIndent: state.lineIndent,\n    firstTabInLine: state.firstTabInLine,\n    tag: state.tag,\n    anchor: state.anchor,\n    kind: state.kind,\n    result: state.result\n  }\n}\n\nfunction restoreState (state, snapshot) {\n  state.position = snapshot.position\n  state.line = snapshot.line\n  state.lineStart = snapshot.lineStart\n  state.lineIndent = snapshot.lineIndent\n  state.firstTabInLine = snapshot.firstTabInLine\n  state.tag = snapshot.tag\n  state.anchor = snapshot.anchor\n  state.kind = snapshot.kind\n  state.result = snapshot.result\n}\n\nconst directiveHandlers = {\n\n  YAML: function handleYamlDirective (state, name, args) {\n    if (state.version !== null) {\n      throwError(state, 'duplication of %YAML directive')\n    }\n\n    if (args.length !== 1) {\n      throwError(state, 'YAML directive accepts exactly one argument')\n    }\n\n    const match = /^([0-9]+)\\.([0-9]+)$/.exec(args[0])\n\n    if (match === null) {\n      throwError(state, 'ill-formed argument of the YAML directive')\n    }\n\n    const major = parseInt(match[1], 10)\n    const minor = parseInt(match[2], 10)\n\n    if (major !== 1) {\n      throwError(state, 'unacceptable YAML version of the document')\n    }\n\n    state.version = args[0]\n    state.checkLineBreaks = (minor < 2)\n\n    if (minor !== 1 && minor !== 2) {\n      throwWarning(state, 'unsupported YAML version of the document')\n    }\n  },\n\n  TAG: function handleTagDirective (state, name, args) {\n    let prefix\n\n    if (args.length !== 2) {\n      throwError(state, 'TAG directive accepts exactly two arguments')\n    }\n\n    const handle = args[0]\n    prefix = args[1]\n\n    if (!PATTERN_TAG_HANDLE.test(handle)) {\n      throwError(state, 'ill-formed tag handle (first argument) of the TAG directive')\n    }\n\n    if (_hasOwnProperty.call(state.tagMap, handle)) {\n      throwError(state, 'there is a previously declared suffix for \"' + handle + '\" tag handle')\n    }\n\n    if (!PATTERN_TAG_URI.test(prefix)) {\n      throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive')\n    }\n\n    try {\n      prefix = decodeURIComponent(prefix)\n    } catch (err) {\n      throwError(state, 'tag prefix is malformed: ' + prefix)\n    }\n\n    state.tagMap[handle] = prefix\n  }\n}\n\nfunction captureSegment (state, start, end, checkJson) {\n  if (start < end) {\n    const _result = state.input.slice(start, end)\n\n    if (checkJson) {\n      for (let _position = 0, _length = _result.length; _position < _length; _position += 1) {\n        const _character = _result.charCodeAt(_position)\n        if (!(_character === 0x09 ||\n              (_character >= 0x20 && _character <= 0x10FFFF))) {\n          throwError(state, 'expected valid JSON character')\n        }\n      }\n    } else if (PATTERN_NON_PRINTABLE.test(_result)) {\n      throwError(state, 'the stream contains non-printable characters')\n    }\n\n    state.result += _result\n  }\n}\n\nfunction mergeMappings (state, destination, source, overridableKeys) {\n  if (!common.isObject(source)) {\n    throwError(state, 'cannot merge mappings; the provided source object is unacceptable')\n  }\n\n  const sourceKeys = Object.keys(source)\n\n  for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {\n    const key = sourceKeys[index]\n\n    if (state.maxTotalMergeKeys !== -1 && ++state.totalMergeKeys > state.maxTotalMergeKeys) {\n      throwError(state, 'merge keys exceeded maxTotalMergeKeys (' + state.maxTotalMergeKeys + ')')\n    }\n\n    if (!_hasOwnProperty.call(destination, key)) {\n      setProperty(destination, key, source[key])\n      overridableKeys[key] = true\n    }\n  }\n}\n\nfunction storeMappingPair (state, _result, overridableKeys, keyTag, keyNode, valueNode,\n  startLine, startLineStart, startPos) {\n  // The output is a plain object here, so keys can only be strings.\n  // We need to convert keyNode to a string, but doing so can hang the process\n  // (deeply nested arrays that explode exponentially using aliases).\n  if (Array.isArray(keyNode)) {\n    keyNode = Array.prototype.slice.call(keyNode)\n\n    for (let index = 0, quantity = keyNode.length; index < quantity; index += 1) {\n      if (Array.isArray(keyNode[index])) {\n        throwError(state, 'nested arrays are not supported inside keys')\n      }\n\n      if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {\n        keyNode[index] = '[object Object]'\n      }\n    }\n  }\n\n  // Avoid code execution in load() via toString property\n  // (still use its own toString for arrays, timestamps,\n  // and whatever user schema extensions happen to have @@toStringTag)\n  if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {\n    keyNode = '[object Object]'\n  }\n\n  keyNode = String(keyNode)\n\n  if (_result === null) {\n    _result = {}\n  }\n\n  if (keyTag === 'tag:yaml.org,2002:merge') {\n    if (Array.isArray(valueNode)) {\n      for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {\n        mergeMappings(state, _result, valueNode[index], overridableKeys)\n      }\n    } else {\n      mergeMappings(state, _result, valueNode, overridableKeys)\n    }\n  } else {\n    if (!state.json &&\n        !_hasOwnProperty.call(overridableKeys, keyNode) &&\n        _hasOwnProperty.call(_result, keyNode)) {\n      state.line = startLine || state.line\n      state.lineStart = startLineStart || state.lineStart\n      state.position = startPos || state.position\n      throwError(state, 'duplicated mapping key')\n    }\n\n    setProperty(_result, keyNode, valueNode)\n    delete overridableKeys[keyNode]\n  }\n\n  return _result\n}\n\nfunction readLineBreak (state) {\n  const ch = state.input.charCodeAt(state.position)\n\n  if (ch === 0x0A/* LF */) {\n    state.position++\n  } else if (ch === 0x0D/* CR */) {\n    state.position++\n    if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {\n      state.position++\n    }\n  } else {\n    throwError(state, 'a line break is expected')\n  }\n\n  state.line += 1\n  state.lineStart = state.position\n  state.firstTabInLine = -1\n}\n\nfunction skipSeparationSpace (state, allowComments, checkIndent) {\n  let lineBreaks = 0\n  let ch = state.input.charCodeAt(state.position)\n\n  while (ch !== 0) {\n    while (isWhiteSpace(ch)) {\n      if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) {\n        state.firstTabInLine = state.position\n      }\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    if (allowComments && ch === 0x23/* # */) {\n      do {\n        ch = state.input.charCodeAt(++state.position)\n      } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0)\n    }\n\n    if (isEol(ch)) {\n      readLineBreak(state)\n\n      ch = state.input.charCodeAt(state.position)\n      lineBreaks++\n      state.lineIndent = 0\n\n      while (ch === 0x20/* Space */) {\n        state.lineIndent++\n        ch = state.input.charCodeAt(++state.position)\n      }\n    } else {\n      break\n    }\n  }\n\n  if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {\n    throwWarning(state, 'deficient indentation')\n  }\n\n  return lineBreaks\n}\n\nfunction testDocumentSeparator (state) {\n  let _position = state.position\n  let ch = state.input.charCodeAt(_position)\n\n  // Condition state.position === state.lineStart is tested\n  // in parent on each call, for efficiency. No needs to test here again.\n  if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&\n      ch === state.input.charCodeAt(_position + 1) &&\n      ch === state.input.charCodeAt(_position + 2)) {\n    _position += 3\n\n    ch = state.input.charCodeAt(_position)\n\n    if (ch === 0 || isWsOrEol(ch)) {\n      return true\n    }\n  }\n\n  return false\n}\n\nfunction writeFoldedLines (state, count) {\n  if (count === 1) {\n    state.result += ' '\n  } else if (count > 1) {\n    state.result += common.repeat('\\n', count - 1)\n  }\n}\n\nfunction readPlainScalar (state, nodeIndent, withinFlowCollection) {\n  let captureStart\n  let captureEnd\n  let hasPendingContent\n  let _line\n  let _lineStart\n  let _lineIndent\n  const _kind = state.kind\n  const _result = state.result\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (isWsOrEol(ch) ||\n      isFlowIndicator(ch) ||\n      ch === 0x23/* # */ ||\n      ch === 0x26/* & */ ||\n      ch === 0x2A/* * */ ||\n      ch === 0x21/* ! */ ||\n      ch === 0x7C/* | */ ||\n      ch === 0x3E/* > */ ||\n      ch === 0x27/* ' */ ||\n      ch === 0x22/* \" */ ||\n      ch === 0x25/* % */ ||\n      ch === 0x40/* @ */ ||\n      ch === 0x60/* ` */) {\n    return false\n  }\n\n  if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {\n    const following = state.input.charCodeAt(state.position + 1)\n\n    if (isWsOrEol(following) ||\n        (withinFlowCollection && isFlowIndicator(following))) {\n      return false\n    }\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n  captureStart = captureEnd = state.position\n  hasPendingContent = false\n\n  while (ch !== 0) {\n    if (ch === 0x3A/* : */) {\n      const following = state.input.charCodeAt(state.position + 1)\n\n      if (isWsOrEol(following) ||\n          (withinFlowCollection && isFlowIndicator(following))) {\n        break\n      }\n    } else if (ch === 0x23/* # */) {\n      const preceding = state.input.charCodeAt(state.position - 1)\n\n      if (isWsOrEol(preceding)) {\n        break\n      }\n    } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||\n               (withinFlowCollection && isFlowIndicator(ch))) {\n      break\n    } else if (isEol(ch)) {\n      _line = state.line\n      _lineStart = state.lineStart\n      _lineIndent = state.lineIndent\n      skipSeparationSpace(state, false, -1)\n\n      if (state.lineIndent >= nodeIndent) {\n        hasPendingContent = true\n        ch = state.input.charCodeAt(state.position)\n        continue\n      } else {\n        state.position = captureEnd\n        state.line = _line\n        state.lineStart = _lineStart\n        state.lineIndent = _lineIndent\n        break\n      }\n    }\n\n    if (hasPendingContent) {\n      captureSegment(state, captureStart, captureEnd, false)\n      writeFoldedLines(state, state.line - _line)\n      captureStart = captureEnd = state.position\n      hasPendingContent = false\n    }\n\n    if (!isWhiteSpace(ch)) {\n      captureEnd = state.position + 1\n    }\n\n    ch = state.input.charCodeAt(++state.position)\n  }\n\n  captureSegment(state, captureStart, captureEnd, false)\n\n  if (state.result) {\n    return true\n  }\n\n  state.kind = _kind\n  state.result = _result\n  return false\n}\n\nfunction readSingleQuotedScalar (state, nodeIndent) {\n  let captureStart\n  let captureEnd\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x27/* ' */) {\n    return false\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n  state.position++\n  captureStart = captureEnd = state.position\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    if (ch === 0x27/* ' */) {\n      captureSegment(state, captureStart, state.position, true)\n      ch = state.input.charCodeAt(++state.position)\n\n      if (ch === 0x27/* ' */) {\n        captureStart = state.position\n        state.position++\n        captureEnd = state.position\n      } else {\n        return true\n      }\n    } else if (isEol(ch)) {\n      captureSegment(state, captureStart, captureEnd, true)\n      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))\n      captureStart = captureEnd = state.position\n    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n      throwError(state, 'unexpected end of the document within a single quoted scalar')\n    } else {\n      state.position++\n      if (!isWhiteSpace(ch)) {\n        captureEnd = state.position\n      }\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a single quoted scalar')\n}\n\nfunction readDoubleQuotedScalar (state, nodeIndent) {\n  let captureStart\n  let captureEnd\n  let tmp\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x22/* \" */) {\n    return false\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n  state.position++\n  captureStart = captureEnd = state.position\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    if (ch === 0x22/* \" */) {\n      captureSegment(state, captureStart, state.position, true)\n      state.position++\n      return true\n    } else if (ch === 0x5C/* \\ */) {\n      captureSegment(state, captureStart, state.position, true)\n      ch = state.input.charCodeAt(++state.position)\n\n      if (isEol(ch)) {\n        skipSeparationSpace(state, false, nodeIndent)\n\n        // TODO: rework to inline fn with no type cast?\n      } else if (ch < 256 && simpleEscapeCheck[ch]) {\n        state.result += simpleEscapeMap[ch]\n        state.position++\n      } else if ((tmp = escapedHexLen(ch)) > 0) {\n        let hexLength = tmp\n        let hexResult = 0\n\n        for (; hexLength > 0; hexLength--) {\n          ch = state.input.charCodeAt(++state.position)\n\n          if ((tmp = fromHexCode(ch)) >= 0) {\n            hexResult = (hexResult << 4) + tmp\n          } else {\n            throwError(state, 'expected hexadecimal character')\n          }\n        }\n\n        state.result += charFromCodepoint(hexResult)\n\n        state.position++\n      } else {\n        throwError(state, 'unknown escape sequence')\n      }\n\n      captureStart = captureEnd = state.position\n    } else if (isEol(ch)) {\n      captureSegment(state, captureStart, captureEnd, true)\n      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))\n      captureStart = captureEnd = state.position\n    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n      throwError(state, 'unexpected end of the document within a double quoted scalar')\n    } else {\n      state.position++\n      if (!isWhiteSpace(ch)) {\n        captureEnd = state.position\n      }\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a double quoted scalar')\n}\n\nfunction readFlowCollection (state, nodeIndent) {\n  let readNext = true\n  let _line\n  let _lineStart\n  let _pos\n  const _tag = state.tag\n  let _result\n  const _anchor = state.anchor\n  let terminator\n  let isPair\n  let isExplicitPair\n  let isMapping\n  const overridableKeys = Object.create(null)\n  let keyNode\n  let keyTag\n  let valueNode\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch === 0x5B/* [ */) {\n    terminator = 0x5D/* ] */\n    isMapping = false\n    _result = []\n  } else if (ch === 0x7B/* { */) {\n    terminator = 0x7D/* } */\n    isMapping = true\n    _result = {}\n  } else {\n    return false\n  }\n\n  if (state.anchor !== null) {\n    storeAnchor(state, state.anchor, _result)\n  }\n\n  ch = state.input.charCodeAt(++state.position)\n\n  while (ch !== 0) {\n    skipSeparationSpace(state, true, nodeIndent)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if (ch === terminator) {\n      state.position++\n      state.tag = _tag\n      state.anchor = _anchor\n      state.kind = isMapping ? 'mapping' : 'sequence'\n      state.result = _result\n      return true\n    } else if (!readNext) {\n      throwError(state, 'missed comma between flow collection entries')\n    } else if (ch === 0x2C/* , */) {\n      // \"flow collection entries can never be completely empty\", as per YAML 1.2, section 7.4\n      throwError(state, \"expected the node content, but found ','\")\n    }\n\n    keyTag = keyNode = valueNode = null\n    isPair = isExplicitPair = false\n\n    if (ch === 0x3F/* ? */) {\n      const following = state.input.charCodeAt(state.position + 1)\n\n      if (isWsOrEol(following)) {\n        isPair = isExplicitPair = true\n        state.position++\n        skipSeparationSpace(state, true, nodeIndent)\n      }\n    }\n\n    _line = state.line // Save the current line.\n    _lineStart = state.lineStart\n    _pos = state.position\n    composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)\n    keyTag = state.tag\n    keyNode = state.result\n    skipSeparationSpace(state, true, nodeIndent)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {\n      isPair = true\n      ch = state.input.charCodeAt(++state.position)\n      skipSeparationSpace(state, true, nodeIndent)\n      composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)\n      valueNode = state.result\n    }\n\n    if (isMapping) {\n      storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)\n    } else if (isPair) {\n      _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos))\n    } else {\n      _result.push(keyNode)\n    }\n\n    skipSeparationSpace(state, true, nodeIndent)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if (ch === 0x2C/* , */) {\n      readNext = true\n      ch = state.input.charCodeAt(++state.position)\n    } else {\n      readNext = false\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a flow collection')\n}\n\nfunction readBlockScalar (state, nodeIndent) {\n  let folding\n  let chomping = CHOMPING_CLIP\n  let didReadContent = false\n  let detectedIndent = false\n  let textIndent = nodeIndent\n  let emptyLines = 0\n  let atMoreIndented = false\n  let tmp\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch === 0x7C/* | */) {\n    folding = false\n  } else if (ch === 0x3E/* > */) {\n    folding = true\n  } else {\n    return false\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n\n  while (ch !== 0) {\n    ch = state.input.charCodeAt(++state.position)\n\n    if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {\n      if (CHOMPING_CLIP === chomping) {\n        chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP\n      } else {\n        throwError(state, 'repeat of a chomping mode identifier')\n      }\n    } else if ((tmp = fromDecimalCode(ch)) >= 0) {\n      if (tmp === 0) {\n        throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one')\n      } else if (!detectedIndent) {\n        textIndent = nodeIndent + tmp - 1\n        detectedIndent = true\n      } else {\n        throwError(state, 'repeat of an indentation width identifier')\n      }\n    } else {\n      break\n    }\n  }\n\n  if (isWhiteSpace(ch)) {\n    do { ch = state.input.charCodeAt(++state.position) }\n    while (isWhiteSpace(ch))\n\n    if (ch === 0x23/* # */) {\n      do { ch = state.input.charCodeAt(++state.position) }\n      while (!isEol(ch) && (ch !== 0))\n    }\n  }\n\n  while (ch !== 0) {\n    readLineBreak(state)\n    state.lineIndent = 0\n\n    ch = state.input.charCodeAt(state.position)\n\n    // eslint-disable-next-line no-unmodified-loop-condition\n    while ((!detectedIndent || state.lineIndent < textIndent) &&\n           (ch === 0x20/* Space */)) {\n      state.lineIndent++\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    if (!detectedIndent && state.lineIndent > textIndent) {\n      textIndent = state.lineIndent\n    }\n\n    if (isEol(ch)) {\n      emptyLines++\n      continue\n    }\n\n    if (!detectedIndent && textIndent === 0) {\n      throwError(state, 'missing indentation for block scalar')\n    }\n\n    // End of the scalar.\n    if (state.lineIndent < textIndent) {\n      // Perform the chomping.\n      if (chomping === CHOMPING_KEEP) {\n        state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n      } else if (chomping === CHOMPING_CLIP) {\n        if (didReadContent) { // i.e. only if the scalar is not empty.\n          state.result += '\\n'\n        }\n      }\n\n      // Break this `while` cycle and go to the funciton's epilogue.\n      break\n    }\n\n    // Folded style: use fancy rules to handle line breaks.\n    if (folding) {\n      // Lines starting with white space characters (more-indented lines) are not folded.\n      if (isWhiteSpace(ch)) {\n        atMoreIndented = true\n        // except for the first content line (cf. Example 8.1)\n        state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n\n      // End of more-indented block.\n      } else if (atMoreIndented) {\n        atMoreIndented = false\n        state.result += common.repeat('\\n', emptyLines + 1)\n\n      // Just one line break - perceive as the same line.\n      } else if (emptyLines === 0) {\n        if (didReadContent) { // i.e. only if we have already read some scalar content.\n          state.result += ' '\n        }\n\n      // Several line breaks - perceive as different lines.\n      } else {\n        state.result += common.repeat('\\n', emptyLines)\n      }\n\n    // Literal style: just add exact number of line breaks between content lines.\n    } else {\n      // Keep all line breaks except the header line break.\n      state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n    }\n\n    didReadContent = true\n    detectedIndent = true\n    emptyLines = 0\n    const captureStart = state.position\n\n    while (!isEol(ch) && (ch !== 0)) {\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    captureSegment(state, captureStart, state.position, false)\n  }\n\n  return true\n}\n\nfunction readBlockSequence (state, nodeIndent) {\n  const _tag = state.tag\n  const _anchor = state.anchor\n  const _result = []\n  let detected = false\n\n  // there is a leading tab before this token, so it can't be a block sequence/mapping;\n  // it can still be flow sequence/mapping or a scalar\n  if (state.firstTabInLine !== -1) return false\n\n  if (state.anchor !== null) {\n    storeAnchor(state, state.anchor, _result)\n  }\n\n  let ch = state.input.charCodeAt(state.position)\n\n  while (ch !== 0) {\n    if (state.firstTabInLine !== -1) {\n      state.position = state.firstTabInLine\n      throwError(state, 'tab characters must not be used in indentation')\n    }\n\n    if (ch !== 0x2D/* - */) {\n      break\n    }\n\n    const following = state.input.charCodeAt(state.position + 1)\n\n    if (!isWsOrEol(following)) {\n      break\n    }\n\n    detected = true\n    state.position++\n\n    if (skipSeparationSpace(state, true, -1)) {\n      if (state.lineIndent <= nodeIndent) {\n        _result.push(null)\n        ch = state.input.charCodeAt(state.position)\n        continue\n      }\n    }\n\n    const _line = state.line\n    composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true)\n    _result.push(state.result)\n    skipSeparationSpace(state, true, -1)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n      throwError(state, 'bad indentation of a sequence entry')\n    } else if (state.lineIndent < nodeIndent) {\n      break\n    }\n  }\n\n  if (detected) {\n    state.tag = _tag\n    state.anchor = _anchor\n    state.kind = 'sequence'\n    state.result = _result\n    return true\n  }\n  return false\n}\n\nfunction readBlockMapping (state, nodeIndent, flowIndent) {\n  let allowCompact\n  let _keyLine\n  let _keyLineStart\n  let _keyPos\n  const _tag = state.tag\n  const _anchor = state.anchor\n  const _result = {}\n  const overridableKeys = Object.create(null)\n  let keyTag = null\n  let keyNode = null\n  let valueNode = null\n  let atExplicitKey = false\n  let detected = false\n\n  // there is a leading tab before this token, so it can't be a block sequence/mapping;\n  // it can still be flow sequence/mapping or a scalar\n  if (state.firstTabInLine !== -1) return false\n\n  if (state.anchor !== null) {\n    storeAnchor(state, state.anchor, _result)\n  }\n\n  let ch = state.input.charCodeAt(state.position)\n\n  while (ch !== 0) {\n    if (!atExplicitKey && state.firstTabInLine !== -1) {\n      state.position = state.firstTabInLine\n      throwError(state, 'tab characters must not be used in indentation')\n    }\n\n    const following = state.input.charCodeAt(state.position + 1)\n    const _line = state.line // Save the current line.\n\n    //\n    // Explicit notation case. There are two separate blocks:\n    // first for the key (denoted by \"?\") and second for the value (denoted by \":\")\n    //\n    if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && isWsOrEol(following)) {\n      if (ch === 0x3F/* ? */) {\n        if (atExplicitKey) {\n          storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n          keyTag = keyNode = valueNode = null\n        }\n\n        detected = true\n        atExplicitKey = true\n        allowCompact = true\n      } else if (atExplicitKey) {\n        // i.e. 0x3A/* : */ === character after the explicit key.\n        atExplicitKey = false\n        allowCompact = true\n      } else {\n        throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line')\n      }\n\n      state.position += 1\n      ch = following\n\n    //\n    // Implicit notation case. Flow-style node as the key first, then \":\", and the value.\n    //\n    } else {\n      _keyLine = state.line\n      _keyLineStart = state.lineStart\n      _keyPos = state.position\n\n      if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {\n        // Neither implicit nor explicit notation.\n        // Reading is done. Go to the epilogue.\n        break\n      }\n\n      if (state.line === _line) {\n        ch = state.input.charCodeAt(state.position)\n\n        while (isWhiteSpace(ch)) {\n          ch = state.input.charCodeAt(++state.position)\n        }\n\n        if (ch === 0x3A/* : */) {\n          ch = state.input.charCodeAt(++state.position)\n\n          if (!isWsOrEol(ch)) {\n            throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping')\n          }\n\n          if (atExplicitKey) {\n            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n            keyTag = keyNode = valueNode = null\n          }\n\n          detected = true\n          atExplicitKey = false\n          allowCompact = false\n          keyTag = state.tag\n          keyNode = state.result\n        } else if (detected) {\n          throwError(state, 'can not read an implicit mapping pair; a colon is missed')\n        } else {\n          state.tag = _tag\n          state.anchor = _anchor\n          return true // Keep the result of `composeNode`.\n        }\n      } else if (detected) {\n        throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key')\n      } else {\n        state.tag = _tag\n        state.anchor = _anchor\n        return true // Keep the result of `composeNode`.\n      }\n    }\n\n    //\n    // Common reading code for both explicit and implicit notations.\n    //\n    if (state.line === _line || state.lineIndent > nodeIndent) {\n      if (atExplicitKey) {\n        _keyLine = state.line\n        _keyLineStart = state.lineStart\n        _keyPos = state.position\n      }\n\n      if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {\n        if (atExplicitKey) {\n          keyNode = state.result\n        } else {\n          valueNode = state.result\n        }\n      }\n\n      if (!atExplicitKey) {\n        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos)\n        keyTag = keyNode = valueNode = null\n      }\n\n      skipSeparationSpace(state, true, -1)\n      ch = state.input.charCodeAt(state.position)\n    }\n\n    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n      throwError(state, 'bad indentation of a mapping entry')\n    } else if (state.lineIndent < nodeIndent) {\n      break\n    }\n  }\n\n  //\n  // Epilogue.\n  //\n\n  // Special case: last mapping's node contains only the key in explicit notation.\n  if (atExplicitKey) {\n    storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n  }\n\n  // Expose the resulting mapping.\n  if (detected) {\n    state.tag = _tag\n    state.anchor = _anchor\n    state.kind = 'mapping'\n    state.result = _result\n  }\n\n  return detected\n}\n\nfunction readTagProperty (state) {\n  let isVerbatim = false\n  let isNamed = false\n  let tagHandle\n  let tagName\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x21/* ! */) return false\n\n  if (state.tag !== null) {\n    throwError(state, 'duplication of a tag property')\n  }\n\n  ch = state.input.charCodeAt(++state.position)\n\n  if (ch === 0x3C/* < */) {\n    isVerbatim = true\n    ch = state.input.charCodeAt(++state.position)\n  } else if (ch === 0x21/* ! */) {\n    isNamed = true\n    tagHandle = '!!'\n    ch = state.input.charCodeAt(++state.position)\n  } else {\n    tagHandle = '!'\n  }\n\n  let _position = state.position\n\n  if (isVerbatim) {\n    do { ch = state.input.charCodeAt(++state.position) }\n    while (ch !== 0 && ch !== 0x3E/* > */)\n\n    if (state.position < state.length) {\n      tagName = state.input.slice(_position, state.position)\n      ch = state.input.charCodeAt(++state.position)\n    } else {\n      throwError(state, 'unexpected end of the stream within a verbatim tag')\n    }\n  } else {\n    while (ch !== 0 && !isWsOrEol(ch)) {\n      if (ch === 0x21/* ! */) {\n        if (!isNamed) {\n          tagHandle = state.input.slice(_position - 1, state.position + 1)\n\n          if (!PATTERN_TAG_HANDLE.test(tagHandle)) {\n            throwError(state, 'named tag handle cannot contain such characters')\n          }\n\n          isNamed = true\n          _position = state.position + 1\n        } else {\n          throwError(state, 'tag suffix cannot contain exclamation marks')\n        }\n      }\n\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    tagName = state.input.slice(_position, state.position)\n\n    if (PATTERN_FLOW_INDICATORS.test(tagName)) {\n      throwError(state, 'tag suffix cannot contain flow indicator characters')\n    }\n  }\n\n  if (tagName && !PATTERN_TAG_URI.test(tagName)) {\n    throwError(state, 'tag name cannot contain such characters: ' + tagName)\n  }\n\n  try {\n    tagName = decodeURIComponent(tagName)\n  } catch (err) {\n    throwError(state, 'tag name is malformed: ' + tagName)\n  }\n\n  if (isVerbatim) {\n    state.tag = tagName\n  } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {\n    state.tag = state.tagMap[tagHandle] + tagName\n  } else if (tagHandle === '!') {\n    state.tag = '!' + tagName\n  } else if (tagHandle === '!!') {\n    state.tag = 'tag:yaml.org,2002:' + tagName\n  } else {\n    throwError(state, 'undeclared tag handle \"' + tagHandle + '\"')\n  }\n\n  return true\n}\n\nfunction readAnchorProperty (state) {\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x26/* & */) return false\n\n  if (state.anchor !== null) {\n    throwError(state, 'duplication of an anchor property')\n  }\n\n  ch = state.input.charCodeAt(++state.position)\n  const _position = state.position\n\n  while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {\n    ch = state.input.charCodeAt(++state.position)\n  }\n\n  if (state.position === _position) {\n    throwError(state, 'name of an anchor node must contain at least one character')\n  }\n\n  state.anchor = state.input.slice(_position, state.position)\n  return true\n}\n\nfunction readAlias (state) {\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x2A/* * */) return false\n\n  ch = state.input.charCodeAt(++state.position)\n  const _position = state.position\n\n  while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {\n    ch = state.input.charCodeAt(++state.position)\n  }\n\n  if (state.position === _position) {\n    throwError(state, 'name of an alias node must contain at least one character')\n  }\n\n  const alias = state.input.slice(_position, state.position)\n\n  if (!_hasOwnProperty.call(state.anchorMap, alias)) {\n    throwError(state, 'unidentified alias \"' + alias + '\"')\n  }\n\n  state.result = state.anchorMap[alias]\n  skipSeparationSpace(state, true, -1)\n  return true\n}\n\nfunction tryReadBlockMappingFromProperty (state, propertyStart, nodeIndent, flowIndent) {\n  const fallbackState = snapshotState(state)\n\n  beginAnchorTransaction(state)\n  restoreState(state, propertyStart)\n\n  // Re-read the leading properties as part of the first implicit key, not as\n  // properties of the current node.\n  state.tag = null\n  state.anchor = null\n  state.kind = null\n  state.result = null\n\n  if (readBlockMapping(state, nodeIndent, flowIndent) && state.kind === 'mapping') {\n    commitAnchorTransaction(state)\n    return true\n  }\n\n  rollbackAnchorTransaction(state)\n  restoreState(state, fallbackState)\n  return false\n}\n\nfunction composeNode (state, parentIndent, nodeContext, allowToSeek, allowCompact) {\n  let allowBlockScalars\n  let allowBlockCollections\n  let indentStatus = 1 // 1: this>parent, 0: this=parent, -1: this<parent\n  let atNewLine = false\n  let hasContent = false\n  let propertyStart = null\n  let type\n  let flowIndent\n  let blockIndent\n\n  if (state.depth >= state.maxDepth) {\n    throwError(state, 'nesting exceeded maxDepth (' + state.maxDepth + ')')\n  }\n\n  state.depth += 1\n\n  if (state.listener !== null) {\n    state.listener('open', state)\n  }\n\n  state.tag = null\n  state.anchor = null\n  state.kind = null\n  state.result = null\n\n  const allowBlockStyles = allowBlockScalars = allowBlockCollections =\n    CONTEXT_BLOCK_OUT === nodeContext ||\n    CONTEXT_BLOCK_IN === nodeContext\n\n  if (allowToSeek) {\n    if (skipSeparationSpace(state, true, -1)) {\n      atNewLine = true\n\n      if (state.lineIndent > parentIndent) {\n        indentStatus = 1\n      } else if (state.lineIndent === parentIndent) {\n        indentStatus = 0\n      } else if (state.lineIndent < parentIndent) {\n        indentStatus = -1\n      }\n    }\n  }\n\n  if (indentStatus === 1) {\n    while (true) {\n      const ch = state.input.charCodeAt(state.position)\n      const propertyState = snapshotState(state)\n\n      // A duplicate property token after a line break can be the first key of\n      // a nested block mapping, e.g. `!!map\\n  !!str key: value`.\n      if (atNewLine &&\n          ((ch === 0x21/* ! */ && state.tag !== null) ||\n           (ch === 0x26/* & */ && state.anchor !== null))) {\n        break\n      }\n\n      if (!readTagProperty(state) && !readAnchorProperty(state)) {\n        break\n      }\n\n      if (propertyStart === null) {\n        propertyStart = propertyState\n      }\n\n      if (skipSeparationSpace(state, true, -1)) {\n        atNewLine = true\n        allowBlockCollections = allowBlockStyles\n\n        if (state.lineIndent > parentIndent) {\n          indentStatus = 1\n        } else if (state.lineIndent === parentIndent) {\n          indentStatus = 0\n        } else if (state.lineIndent < parentIndent) {\n          indentStatus = -1\n        }\n      } else {\n        allowBlockCollections = false\n      }\n    }\n  }\n\n  if (allowBlockCollections) {\n    allowBlockCollections = atNewLine || allowCompact\n  }\n\n  if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {\n    if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {\n      flowIndent = parentIndent\n    } else {\n      flowIndent = parentIndent + 1\n    }\n\n    blockIndent = state.position - state.lineStart\n\n    if (indentStatus === 1) {\n      if ((allowBlockCollections &&\n          (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent))) ||\n          readFlowCollection(state, flowIndent)) {\n        hasContent = true\n      } else {\n        const ch = state.input.charCodeAt(state.position)\n\n        if (propertyStart !== null && allowBlockStyles && !allowBlockCollections &&\n            ch !== 0x7C/* | */ && ch !== 0x3E/* > */ &&\n            tryReadBlockMappingFromProperty(\n              state,\n              propertyStart,\n              propertyStart.position - propertyStart.lineStart,\n              flowIndent\n            )) {\n          hasContent = true\n        } else if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||\n            readSingleQuotedScalar(state, flowIndent) ||\n            readDoubleQuotedScalar(state, flowIndent)) {\n          hasContent = true\n        } else if (readAlias(state)) {\n          hasContent = true\n\n          if (state.tag !== null || state.anchor !== null) {\n            throwError(state, 'alias node should not have any properties')\n          }\n        } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {\n          hasContent = true\n\n          if (state.tag === null) {\n            state.tag = '?'\n          }\n        }\n\n        if (state.anchor !== null) {\n          storeAnchor(state, state.anchor, state.result)\n        }\n      }\n    } else if (indentStatus === 0) {\n      // Special case: block sequences are allowed to have same indentation level as the parent.\n      // http://www.yaml.org/spec/1.2/spec.html#id2799784\n      hasContent = allowBlockCollections && readBlockSequence(state, blockIndent)\n    }\n  }\n\n  if (state.tag === null) {\n    if (state.anchor !== null) {\n      storeAnchor(state, state.anchor, state.result)\n    }\n  } else if (state.tag === '?') {\n    // Implicit resolving is not allowed for non-scalar types, and '?'\n    // non-specific tag is only automatically assigned to plain scalars.\n    //\n    // We only need to check kind conformity in case user explicitly assigns '?'\n    // tag, for example like this: \"!<?> [0]\"\n    //\n    if (state.result !== null && state.kind !== 'scalar') {\n      throwError(state, 'unacceptable node kind for !<?> tag; it should be \"scalar\", not \"' + state.kind + '\"')\n    }\n\n    for (let typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {\n      type = state.implicitTypes[typeIndex]\n\n      if (type.resolve(state.result)) { // `state.result` updated in resolver if matched\n        state.result = type.construct(state.result)\n        state.tag = type.tag\n        if (state.anchor !== null) {\n          storeAnchor(state, state.anchor, state.result)\n        }\n        break\n      }\n    }\n  } else if (state.tag !== '!') {\n    if (_hasOwnProperty.call(state.typeMap[state.kind || 'fallback'], state.tag)) {\n      type = state.typeMap[state.kind || 'fallback'][state.tag]\n    } else {\n      // looking for multi type\n      type = null\n      const typeList = state.typeMap.multi[state.kind || 'fallback']\n\n      for (let typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {\n        if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {\n          type = typeList[typeIndex]\n          break\n        }\n      }\n    }\n\n    if (!type) {\n      throwError(state, 'unknown tag !<' + state.tag + '>')\n    }\n\n    if (state.result !== null && type.kind !== state.kind) {\n      throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be \"' + type.kind + '\", not \"' + state.kind + '\"')\n    }\n\n    if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched\n      throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag')\n    } else {\n      state.result = type.construct(state.result, state.tag)\n      if (state.anchor !== null) {\n        storeAnchor(state, state.anchor, state.result)\n      }\n    }\n  }\n\n  if (state.listener !== null) {\n    state.listener('close', state)\n  }\n\n  state.depth -= 1\n  return state.tag !== null || state.anchor !== null || hasContent\n}\n\nfunction readDocument (state) {\n  const documentStart = state.position\n  let hasDirectives = false\n  let ch\n\n  state.version = null\n  state.checkLineBreaks = state.legacy\n  state.tagMap = Object.create(null)\n  state.anchorMap = Object.create(null)\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    skipSeparationSpace(state, true, -1)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if (state.lineIndent > 0 || ch !== 0x25/* % */) {\n      break\n    }\n\n    hasDirectives = true\n    ch = state.input.charCodeAt(++state.position)\n    let _position = state.position\n\n    while (ch !== 0 && !isWsOrEol(ch)) {\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    const directiveName = state.input.slice(_position, state.position)\n    const directiveArgs = []\n\n    if (directiveName.length < 1) {\n      throwError(state, 'directive name must not be less than one character in length')\n    }\n\n    while (ch !== 0) {\n      while (isWhiteSpace(ch)) {\n        ch = state.input.charCodeAt(++state.position)\n      }\n\n      if (ch === 0x23/* # */) {\n        do { ch = state.input.charCodeAt(++state.position) }\n        while (ch !== 0 && !isEol(ch))\n        break\n      }\n\n      if (isEol(ch)) break\n\n      _position = state.position\n\n      while (ch !== 0 && !isWsOrEol(ch)) {\n        ch = state.input.charCodeAt(++state.position)\n      }\n\n      directiveArgs.push(state.input.slice(_position, state.position))\n    }\n\n    if (ch !== 0) readLineBreak(state)\n\n    if (_hasOwnProperty.call(directiveHandlers, directiveName)) {\n      directiveHandlers[directiveName](state, directiveName, directiveArgs)\n    } else {\n      throwWarning(state, 'unknown document directive \"' + directiveName + '\"')\n    }\n  }\n\n  skipSeparationSpace(state, true, -1)\n\n  if (state.lineIndent === 0 &&\n      state.input.charCodeAt(state.position) === 0x2D/* - */ &&\n      state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&\n      state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {\n    state.position += 3\n    skipSeparationSpace(state, true, -1)\n  } else if (hasDirectives) {\n    throwError(state, 'directives end mark is expected')\n  }\n\n  composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true)\n  skipSeparationSpace(state, true, -1)\n\n  if (state.checkLineBreaks &&\n      PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {\n    throwWarning(state, 'non-ASCII line breaks are interpreted as content')\n  }\n\n  state.documents.push(state.result)\n\n  if (state.position === state.lineStart && testDocumentSeparator(state)) {\n    if (state.input.charCodeAt(state.position) === 0x2E/* . */) {\n      state.position += 3\n      skipSeparationSpace(state, true, -1)\n    }\n    return\n  }\n\n  if (state.position < (state.length - 1)) {\n    throwError(state, 'end of the stream or a document separator is expected')\n  }\n}\n\nfunction loadDocuments (input, options) {\n  input = String(input)\n  options = options || {}\n\n  if (input.length !== 0) {\n    // Add tailing `\\n` if not exists\n    if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&\n        input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {\n      input += '\\n'\n    }\n\n    // Strip BOM\n    if (input.charCodeAt(0) === 0xFEFF) {\n      input = input.slice(1)\n    }\n  }\n\n  const state = new State(input, options)\n\n  const nullpos = input.indexOf('\\0')\n\n  if (nullpos !== -1) {\n    state.position = nullpos\n    throwError(state, 'null byte is not allowed in input')\n  }\n\n  // Use 0 as string terminator. That significantly simplifies bounds check.\n  state.input += '\\0'\n\n  while (state.input.charCodeAt(state.position) === 0x20/* Space */) {\n    state.lineIndent += 1\n    state.position += 1\n  }\n\n  while (state.position < (state.length - 1)) {\n    readDocument(state)\n  }\n\n  return state.documents\n}\n\nfunction loadAll (input, iterator, options) {\n  if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {\n    options = iterator\n    iterator = null\n  }\n\n  const documents = loadDocuments(input, options)\n\n  if (typeof iterator !== 'function') {\n    return documents\n  }\n\n  for (let index = 0, length = documents.length; index < length; index += 1) {\n    iterator(documents[index])\n  }\n}\n\nfunction load (input, options) {\n  const documents = loadDocuments(input, options)\n\n  if (documents.length === 0) {\n    return undefined\n  } else if (documents.length === 1) {\n    return documents[0]\n  }\n  throw new YAMLException('expected a single document in the stream, but found more')\n}\n\nmodule.exports.loadAll = loadAll\nmodule.exports.load = load\n","'use strict'\n\nconst common = require('./common')\nconst YAMLException = require('./exception')\nconst DEFAULT_SCHEMA = require('./schema/default')\n\nconst _toString = Object.prototype.toString\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nconst CHAR_BOM = 0xFEFF\nconst CHAR_TAB = 0x09 /* Tab */\nconst CHAR_LINE_FEED = 0x0A /* LF */\nconst CHAR_CARRIAGE_RETURN = 0x0D /* CR */\nconst CHAR_SPACE = 0x20 /* Space */\nconst CHAR_EXCLAMATION = 0x21 /* ! */\nconst CHAR_DOUBLE_QUOTE = 0x22 /* \" */\nconst CHAR_SHARP = 0x23 /* # */\nconst CHAR_PERCENT = 0x25 /* % */\nconst CHAR_AMPERSAND = 0x26 /* & */\nconst CHAR_SINGLE_QUOTE = 0x27 /* ' */\nconst CHAR_ASTERISK = 0x2A /* * */\nconst CHAR_COMMA = 0x2C /* , */\nconst CHAR_MINUS = 0x2D /* - */\nconst CHAR_COLON = 0x3A /* : */\nconst CHAR_EQUALS = 0x3D /* = */\nconst CHAR_GREATER_THAN = 0x3E /* > */\nconst CHAR_QUESTION = 0x3F /* ? */\nconst CHAR_COMMERCIAL_AT = 0x40 /* @ */\nconst CHAR_LEFT_SQUARE_BRACKET = 0x5B /* [ */\nconst CHAR_RIGHT_SQUARE_BRACKET = 0x5D /* ] */\nconst CHAR_GRAVE_ACCENT = 0x60 /* ` */\nconst CHAR_LEFT_CURLY_BRACKET = 0x7B /* { */\nconst CHAR_VERTICAL_LINE = 0x7C /* | */\nconst CHAR_RIGHT_CURLY_BRACKET = 0x7D /* } */\n\nconst ESCAPE_SEQUENCES = {}\n\nESCAPE_SEQUENCES[0x00] = '\\\\0'\nESCAPE_SEQUENCES[0x07] = '\\\\a'\nESCAPE_SEQUENCES[0x08] = '\\\\b'\nESCAPE_SEQUENCES[0x09] = '\\\\t'\nESCAPE_SEQUENCES[0x0A] = '\\\\n'\nESCAPE_SEQUENCES[0x0B] = '\\\\v'\nESCAPE_SEQUENCES[0x0C] = '\\\\f'\nESCAPE_SEQUENCES[0x0D] = '\\\\r'\nESCAPE_SEQUENCES[0x1B] = '\\\\e'\nESCAPE_SEQUENCES[0x22] = '\\\\\"'\nESCAPE_SEQUENCES[0x5C] = '\\\\\\\\'\nESCAPE_SEQUENCES[0x85] = '\\\\N'\nESCAPE_SEQUENCES[0xA0] = '\\\\_'\nESCAPE_SEQUENCES[0x2028] = '\\\\L'\nESCAPE_SEQUENCES[0x2029] = '\\\\P'\n\nconst DEPRECATED_BOOLEANS_SYNTAX = [\n  'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',\n  'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'\n]\n\nconst DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\\.[0-9_]*)?$/\n\nfunction compileStyleMap (schema, map) {\n  if (map === null) return {}\n\n  const result = {}\n  const keys = Object.keys(map)\n\n  for (let index = 0, length = keys.length; index < length; index += 1) {\n    let tag = keys[index]\n    let style = String(map[tag])\n\n    if (tag.slice(0, 2) === '!!') {\n      tag = 'tag:yaml.org,2002:' + tag.slice(2)\n    }\n    const type = schema.compiledTypeMap['fallback'][tag]\n\n    if (type && _hasOwnProperty.call(type.styleAliases, style)) {\n      style = type.styleAliases[style]\n    }\n\n    result[tag] = style\n  }\n\n  return result\n}\n\nfunction encodeHex (character) {\n  let handle\n  let length\n\n  const string = character.toString(16).toUpperCase()\n\n  if (character <= 0xFF) {\n    handle = 'x'\n    length = 2\n  } else if (character <= 0xFFFF) {\n    handle = 'u'\n    length = 4\n  } else if (character <= 0xFFFFFFFF) {\n    handle = 'U'\n    length = 8\n  } else {\n    throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF')\n  }\n\n  return '\\\\' + handle + common.repeat('0', length - string.length) + string\n}\n\nconst QUOTING_TYPE_SINGLE = 1\nconst QUOTING_TYPE_DOUBLE = 2\n\nfunction State (options) {\n  this.schema = options['schema'] || DEFAULT_SCHEMA\n  this.indent = Math.max(1, (options['indent'] || 2))\n  this.noArrayIndent = options['noArrayIndent'] || false\n  this.skipInvalid = options['skipInvalid'] || false\n  this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel'])\n  this.styleMap = compileStyleMap(this.schema, options['styles'] || null)\n  this.sortKeys = options['sortKeys'] || false\n  this.lineWidth = options['lineWidth'] || 80\n  this.noRefs = options['noRefs'] || false\n  this.noCompatMode = options['noCompatMode'] || false\n  this.condenseFlow = options['condenseFlow'] || false\n  this.quotingType = options['quotingType'] === '\"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE\n  this.forceQuotes = options['forceQuotes'] || false\n  this.replacer = typeof options['replacer'] === 'function' ? options['replacer'] : null\n\n  this.implicitTypes = this.schema.compiledImplicit\n  this.explicitTypes = this.schema.compiledExplicit\n\n  this.tag = null\n  this.result = ''\n\n  this.duplicates = []\n  this.usedDuplicates = null\n}\n\n// Indents every line in a string. Empty lines (\\n only) are not indented.\nfunction indentString (string, spaces) {\n  const ind = common.repeat(' ', spaces)\n  let position = 0\n  let result = ''\n  const length = string.length\n\n  while (position < length) {\n    let line\n    const next = string.indexOf('\\n', position)\n    if (next === -1) {\n      line = string.slice(position)\n      position = length\n    } else {\n      line = string.slice(position, next + 1)\n      position = next + 1\n    }\n\n    if (line.length && line !== '\\n') result += ind\n\n    result += line\n  }\n\n  return result\n}\n\nfunction generateNextLine (state, level) {\n  return '\\n' + common.repeat(' ', state.indent * level)\n}\n\nfunction testImplicitResolving (state, str) {\n  for (let index = 0, length = state.implicitTypes.length; index < length; index += 1) {\n    const type = state.implicitTypes[index]\n\n    if (type.resolve(str)) {\n      return true\n    }\n  }\n\n  return false\n}\n\n// [33] s-white ::= s-space | s-tab\nfunction isWhitespace (c) {\n  return c === CHAR_SPACE || c === CHAR_TAB\n}\n\n// Returns true if the character can be printed without escaping.\n// From YAML 1.2: \"any allowed characters known to be non-printable\n// should also be escaped. [However,] This isn’t mandatory\"\n// Derived from nb-char - \\t - #x85 - #xA0 - #x2028 - #x2029.\nfunction isPrintable (c) {\n  return (c >= 0x00020 && c <= 0x00007E) ||\n    ((c >= 0x000A1 && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029) ||\n    ((c >= 0x0E000 && c <= 0x00FFFD) && c !== CHAR_BOM) ||\n    (c >= 0x10000 && c <= 0x10FFFF)\n}\n\n// [34] ns-char ::= nb-char - s-white\n// [27] nb-char ::= c-printable - b-char - c-byte-order-mark\n// [26] b-char  ::= b-line-feed | b-carriage-return\n// Including s-white (for some reason, examples doesn't match specs in this aspect)\n// ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark\nfunction isNsCharOrWhitespace (c) {\n  return isPrintable(c) &&\n    c !== CHAR_BOM &&\n    // - b-char\n    c !== CHAR_CARRIAGE_RETURN &&\n    c !== CHAR_LINE_FEED\n}\n\n// [127]  ns-plain-safe(c) ::= c = flow-out  ⇒ ns-plain-safe-out\n//                             c = flow-in   ⇒ ns-plain-safe-in\n//                             c = block-key ⇒ ns-plain-safe-out\n//                             c = flow-key  ⇒ ns-plain-safe-in\n// [128] ns-plain-safe-out ::= ns-char\n// [129]  ns-plain-safe-in ::= ns-char - c-flow-indicator\n// [130]  ns-plain-char(c) ::=  ( ns-plain-safe(c) - “:” - “#” )\n//                            | ( /* An ns-char preceding */ “#” )\n//                            | ( “:” /* Followed by an ns-plain-safe(c) */ )\nfunction isPlainSafe (c, prev, inblock) {\n  const cIsNsCharOrWhitespace = isNsCharOrWhitespace(c)\n  const cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c)\n  return (\n    (\n      // ns-plain-safe\n      inblock // c = flow-in\n        ? cIsNsCharOrWhitespace\n        : cIsNsCharOrWhitespace &&\n          // - c-flow-indicator\n          c !== CHAR_COMMA &&\n          c !== CHAR_LEFT_SQUARE_BRACKET &&\n          c !== CHAR_RIGHT_SQUARE_BRACKET &&\n          c !== CHAR_LEFT_CURLY_BRACKET &&\n          c !== CHAR_RIGHT_CURLY_BRACKET\n    ) &&\n    // ns-plain-char\n    c !== CHAR_SHARP && // false on '#'\n    !(prev === CHAR_COLON && !cIsNsChar)\n  ) || // false on ': '\n  (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP) || // change to true on '[^ ]#'\n  (prev === CHAR_COLON && cIsNsChar) // change to true on ':[^ ]'\n}\n\n// Simplified test for values allowed as the first character in plain style.\nfunction isPlainSafeFirst (c) {\n  // Uses a subset of ns-char - c-indicator\n  // where ns-char = nb-char - s-white.\n  // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part\n  return isPrintable(c) &&\n    c !== CHAR_BOM &&\n    !isWhitespace(c) && // - s-white\n    // - (c-indicator ::=\n    // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”\n    c !== CHAR_MINUS &&\n    c !== CHAR_QUESTION &&\n    c !== CHAR_COLON &&\n    c !== CHAR_COMMA &&\n    c !== CHAR_LEFT_SQUARE_BRACKET &&\n    c !== CHAR_RIGHT_SQUARE_BRACKET &&\n    c !== CHAR_LEFT_CURLY_BRACKET &&\n    c !== CHAR_RIGHT_CURLY_BRACKET &&\n    // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “\"”\n    c !== CHAR_SHARP &&\n    c !== CHAR_AMPERSAND &&\n    c !== CHAR_ASTERISK &&\n    c !== CHAR_EXCLAMATION &&\n    c !== CHAR_VERTICAL_LINE &&\n    c !== CHAR_EQUALS &&\n    c !== CHAR_GREATER_THAN &&\n    c !== CHAR_SINGLE_QUOTE &&\n    c !== CHAR_DOUBLE_QUOTE &&\n    // | “%” | “@” | “`”)\n    c !== CHAR_PERCENT &&\n    c !== CHAR_COMMERCIAL_AT &&\n    c !== CHAR_GRAVE_ACCENT\n}\n\n// Simplified test for values allowed as the last character in plain style.\nfunction isPlainSafeLast (c) {\n  // just not whitespace or colon, it will be checked to be plain character later\n  return !isWhitespace(c) && c !== CHAR_COLON\n}\n\n// Same as 'string'.codePointAt(pos), but works in older browsers.\nfunction codePointAt (string, pos) {\n  const first = string.charCodeAt(pos)\n  let second\n\n  if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) {\n    second = string.charCodeAt(pos + 1)\n    if (second >= 0xDC00 && second <= 0xDFFF) {\n      // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae\n      return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000\n    }\n  }\n  return first\n}\n\n// Determines whether block indentation indicator is required.\nfunction needIndentIndicator (string) {\n  const leadingSpaceRe = /^\\n* /\n  return leadingSpaceRe.test(string)\n}\n\nconst STYLE_PLAIN = 1\nconst STYLE_SINGLE = 2\nconst STYLE_LITERAL = 3\nconst STYLE_FOLDED = 4\nconst STYLE_DOUBLE = 5\n\n// Determines which scalar styles are possible and returns the preferred style.\n// lineWidth = -1 => no limit.\n// Pre-conditions: str.length > 0.\n// Post-conditions:\n//    STYLE_PLAIN or STYLE_SINGLE => no \\n are in the string.\n//    STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).\n//    STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).\nfunction chooseScalarStyle (string, singleLineOnly, indentPerLevel, lineWidth,\n  testAmbiguousType, quotingType, forceQuotes, inblock) {\n  let i\n  let char = 0\n  let prevChar = null\n  let hasLineBreak = false\n  let hasFoldableLine = false // only checked if shouldTrackWidth\n  const shouldTrackWidth = lineWidth !== -1\n  let previousLineBreak = -1 // count the first line correctly\n  let plain = isPlainSafeFirst(codePointAt(string, 0)) &&\n    isPlainSafeLast(codePointAt(string, string.length - 1))\n\n  if (singleLineOnly || forceQuotes) {\n    // Case: no block styles.\n    // Check for disallowed characters to rule out plain and single.\n    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n      char = codePointAt(string, i)\n      if (!isPrintable(char)) {\n        return STYLE_DOUBLE\n      }\n      plain = plain && isPlainSafe(char, prevChar, inblock)\n      prevChar = char\n    }\n  } else {\n    // Case: block styles permitted.\n    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n      char = codePointAt(string, i)\n      if (char === CHAR_LINE_FEED) {\n        hasLineBreak = true\n        // Check if any line can be folded.\n        if (shouldTrackWidth) {\n          hasFoldableLine = hasFoldableLine ||\n            // Foldable line = too long, and not more-indented.\n            (i - previousLineBreak - 1 > lineWidth &&\n             string[previousLineBreak + 1] !== ' ')\n          previousLineBreak = i\n        }\n      } else if (!isPrintable(char)) {\n        return STYLE_DOUBLE\n      }\n      plain = plain && isPlainSafe(char, prevChar, inblock)\n      prevChar = char\n    }\n    // in case the end is missing a \\n\n    hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&\n      (i - previousLineBreak - 1 > lineWidth &&\n       string[previousLineBreak + 1] !== ' '))\n  }\n  // Although every style can represent \\n without escaping, prefer block styles\n  // for multiline, since they're more readable and they don't add empty lines.\n  // Also prefer folding a super-long line.\n  if (!hasLineBreak && !hasFoldableLine) {\n    // Strings interpretable as another type have to be quoted;\n    // e.g. the string 'true' vs. the boolean true.\n    if (plain && !forceQuotes && !testAmbiguousType(string)) {\n      return STYLE_PLAIN\n    }\n    return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE\n  }\n  // Edge case: block indentation indicator can only have one digit.\n  if (indentPerLevel > 9 && needIndentIndicator(string)) {\n    return STYLE_DOUBLE\n  }\n  // At this point we know block styles are valid.\n  // Prefer literal style unless we want to fold.\n  if (!forceQuotes) {\n    return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL\n  }\n  return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE\n}\n\n// Note: line breaking/folding is implemented for only the folded style.\n// NB. We drop the last trailing newline (if any) of a returned block scalar\n//  since the dumper adds its own newline. This always works:\n//    • No ending newline => unaffected; already using strip \"-\" chomping.\n//    • Ending newline    => removed then restored.\n//  Importantly, this keeps the \"+\" chomp indicator from gaining an extra line.\nfunction writeScalar (state, string, level, iskey, inblock) {\n  state.dump = (function () {\n    if (string.length === 0) {\n      return state.quotingType === QUOTING_TYPE_DOUBLE ? '\"\"' : \"''\"\n    }\n    if (!state.noCompatMode) {\n      if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {\n        return state.quotingType === QUOTING_TYPE_DOUBLE ? ('\"' + string + '\"') : (\"'\" + string + \"'\")\n      }\n    }\n\n    const indent = state.indent * Math.max(1, level) // no 0-indent scalars\n    // As indentation gets deeper, let the width decrease monotonically\n    // to the lower bound min(state.lineWidth, 40).\n    // Note that this implies\n    //  state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.\n    //  state.lineWidth > 40 + state.indent: width decreases until the lower bound.\n    // This behaves better than a constant minimum width which disallows narrower options,\n    // or an indent threshold which causes the width to suddenly increase.\n    const lineWidth = (state.lineWidth === -1)\n      ? -1\n      : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent)\n\n    // Without knowing if keys are implicit/explicit, assume implicit for safety.\n    const singleLineOnly = iskey ||\n      // No block styles in flow mode.\n      (state.flowLevel > -1 && level >= state.flowLevel)\n    function testAmbiguity (string) {\n      return testImplicitResolving(state, string)\n    }\n\n    switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth,\n      testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {\n      case STYLE_PLAIN:\n        return string\n      case STYLE_SINGLE:\n        return \"'\" + string.replace(/'/g, \"''\") + \"'\"\n      case STYLE_LITERAL:\n        return '|' + blockHeader(string, state.indent) +\n          dropEndingNewline(indentString(string, indent))\n      case STYLE_FOLDED:\n        return '>' + blockHeader(string, state.indent) +\n          dropEndingNewline(indentString(foldString(string, lineWidth), indent))\n      case STYLE_DOUBLE:\n        return '\"' + escapeString(string, lineWidth) + '\"'\n      default:\n        throw new YAMLException('impossible error: invalid scalar style')\n    }\n  }())\n}\n\n// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.\nfunction blockHeader (string, indentPerLevel) {\n  const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : ''\n\n  // note the special case: the string '\\n' counts as a \"trailing\" empty line.\n  const clip = string[string.length - 1] === '\\n'\n  const keep = clip && (string[string.length - 2] === '\\n' || string === '\\n')\n  const chomp = keep ? '+' : (clip ? '' : '-')\n\n  return indentIndicator + chomp + '\\n'\n}\n\n// (See the note for writeScalar.)\nfunction dropEndingNewline (string) {\n  return string[string.length - 1] === '\\n' ? string.slice(0, -1) : string\n}\n\n// Note: a long line without a suitable break point will exceed the width limit.\n// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.\nfunction foldString (string, width) {\n  // In folded style, $k$ consecutive newlines output as $k+1$ newlines—\n  // unless they're before or after a more-indented line, or at the very\n  // beginning or end, in which case $k$ maps to $k$.\n  // Therefore, parse each chunk as newline(s) followed by a content line.\n  const lineRe = /(\\n+)([^\\n]*)/g\n\n  // first line (possibly an empty line)\n  let result = (function () {\n    let nextLF = string.indexOf('\\n')\n    nextLF = nextLF !== -1 ? nextLF : string.length\n    lineRe.lastIndex = nextLF\n    return foldLine(string.slice(0, nextLF), width)\n  }())\n  // If we haven't reached the first content line yet, don't add an extra \\n.\n  let prevMoreIndented = string[0] === '\\n' || string[0] === ' '\n  let moreIndented\n\n  // rest of the lines\n  let match\n  while ((match = lineRe.exec(string))) {\n    const prefix = match[1]\n    const line = match[2]\n\n    moreIndented = (line[0] === ' ')\n    result += prefix +\n      ((!prevMoreIndented && !moreIndented && line !== '') ? '\\n' : '') +\n      foldLine(line, width)\n    prevMoreIndented = moreIndented\n  }\n\n  return result\n}\n\n// Greedy line breaking.\n// Picks the longest line under the limit each time,\n// otherwise settles for the shortest line over the limit.\n// NB. More-indented lines *cannot* be folded, as that would add an extra \\n.\nfunction foldLine (line, width) {\n  if (line === '' || line[0] === ' ') return line\n\n  // Since a more-indented line adds a \\n, breaks can't be followed by a space.\n  const breakRe = / [^ ]/g // note: the match index will always be <= length-2.\n  let match\n  // start is an inclusive index. end, curr, and next are exclusive.\n  let start = 0\n  let end\n  let curr = 0\n  let next = 0\n  let result = ''\n\n  // Invariants: 0 <= start <= length-1.\n  //   0 <= curr <= next <= max(0, length-2). curr - start <= width.\n  // Inside the loop:\n  //   A match implies length >= 2, so curr and next are <= length-2.\n  while ((match = breakRe.exec(line))) {\n    next = match.index\n    // maintain invariant: curr - start <= width\n    if (next - start > width) {\n      end = (curr > start) ? curr : next // derive end <= length-2\n      result += '\\n' + line.slice(start, end)\n      // skip the space that was output as \\n\n      start = end + 1                    // derive start <= length-1\n    }\n    curr = next\n  }\n\n  // By the invariants, start <= length-1, so there is something left over.\n  // It is either the whole string or a part starting from non-whitespace.\n  result += '\\n'\n  // Insert a break if the remainder is too long and there is a break available.\n  if (line.length - start > width && curr > start) {\n    result += line.slice(start, curr) + '\\n' + line.slice(curr + 1)\n  } else {\n    result += line.slice(start)\n  }\n\n  return result.slice(1) // drop extra \\n joiner\n}\n\n// Escapes a double-quoted string.\nfunction escapeString (string) {\n  let result = ''\n  let char = 0\n\n  for (let i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n    char = codePointAt(string, i)\n    const escapeSeq = ESCAPE_SEQUENCES[char]\n\n    if (!escapeSeq && isPrintable(char)) {\n      result += string[i]\n      if (char >= 0x10000) result += string[i + 1]\n    } else {\n      result += escapeSeq || encodeHex(char)\n    }\n  }\n\n  return result\n}\n\nfunction writeFlowSequence (state, level, object) {\n  let _result = ''\n  const _tag = state.tag\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    let value = object[index]\n\n    if (state.replacer) {\n      value = state.replacer.call(object, String(index), value)\n    }\n\n    // Write only valid elements, put null instead of invalid elements.\n    if (writeNode(state, level, value, false, false) ||\n        (typeof value === 'undefined' &&\n         writeNode(state, level, null, false, false))) {\n      if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : '')\n      _result += state.dump\n    }\n  }\n\n  state.tag = _tag\n  state.dump = '[' + _result + ']'\n}\n\nfunction writeBlockSequence (state, level, object, compact) {\n  let _result = ''\n  const _tag = state.tag\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    let value = object[index]\n\n    if (state.replacer) {\n      value = state.replacer.call(object, String(index), value)\n    }\n\n    // Write only valid elements, put null instead of invalid elements.\n    if (writeNode(state, level + 1, value, true, true, false, true) ||\n        (typeof value === 'undefined' &&\n         writeNode(state, level + 1, null, true, true, false, true))) {\n      if (!compact || _result !== '') {\n        _result += generateNextLine(state, level)\n      }\n\n      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n        _result += '-'\n      } else {\n        _result += '- '\n      }\n\n      _result += state.dump\n    }\n  }\n\n  state.tag = _tag\n  state.dump = _result || '[]' // Empty sequence if no valid values.\n}\n\nfunction writeFlowMapping (state, level, object) {\n  let _result = ''\n  const _tag = state.tag\n  const objectKeyList = Object.keys(object)\n\n  for (let index = 0, length = objectKeyList.length; index < length; index += 1) {\n    let pairBuffer = ''\n    if (_result !== '') pairBuffer += ', '\n\n    if (state.condenseFlow) pairBuffer += '\"'\n\n    const objectKey = objectKeyList[index]\n    let objectValue = object[objectKey]\n\n    if (state.replacer) {\n      objectValue = state.replacer.call(object, objectKey, objectValue)\n    }\n\n    if (!writeNode(state, level, objectKey, false, false)) {\n      continue // Skip this pair because of invalid key;\n    }\n\n    if (state.dump.length > 1024) pairBuffer += '? '\n\n    pairBuffer += state.dump + (state.condenseFlow ? '\"' : '') + ':' + (state.condenseFlow ? '' : ' ')\n\n    if (!writeNode(state, level, objectValue, false, false)) {\n      continue // Skip this pair because of invalid value.\n    }\n\n    pairBuffer += state.dump\n\n    // Both key and value are valid.\n    _result += pairBuffer\n  }\n\n  state.tag = _tag\n  state.dump = '{' + _result + '}'\n}\n\nfunction writeBlockMapping (state, level, object, compact) {\n  let _result = ''\n  const _tag = state.tag\n  const objectKeyList = Object.keys(object)\n\n  // Allow sorting keys so that the output file is deterministic\n  if (state.sortKeys === true) {\n    // Default sorting\n    objectKeyList.sort()\n  } else if (typeof state.sortKeys === 'function') {\n    // Custom sort function\n    objectKeyList.sort(state.sortKeys)\n  } else if (state.sortKeys) {\n    // Something is wrong\n    throw new YAMLException('sortKeys must be a boolean or a function')\n  }\n\n  for (let index = 0, length = objectKeyList.length; index < length; index += 1) {\n    let pairBuffer = ''\n\n    if (!compact || _result !== '') {\n      pairBuffer += generateNextLine(state, level)\n    }\n\n    const objectKey = objectKeyList[index]\n    let objectValue = object[objectKey]\n\n    if (state.replacer) {\n      objectValue = state.replacer.call(object, objectKey, objectValue)\n    }\n\n    if (!writeNode(state, level + 1, objectKey, true, true, true)) {\n      continue // Skip this pair because of invalid key.\n    }\n\n    const explicitPair = (state.tag !== null && state.tag !== '?') ||\n                   (state.dump && state.dump.length > 1024)\n\n    if (explicitPair) {\n      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n        pairBuffer += '?'\n      } else {\n        pairBuffer += '? '\n      }\n    }\n\n    pairBuffer += state.dump\n\n    if (explicitPair) {\n      pairBuffer += generateNextLine(state, level)\n    }\n\n    if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {\n      continue // Skip this pair because of invalid value.\n    }\n\n    if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n      pairBuffer += ':'\n    } else {\n      pairBuffer += ': '\n    }\n\n    pairBuffer += state.dump\n\n    // Both key and value are valid.\n    _result += pairBuffer\n  }\n\n  state.tag = _tag\n  state.dump = _result || '{}' // Empty mapping if no valid pairs.\n}\n\nfunction detectType (state, object, explicit) {\n  const typeList = explicit ? state.explicitTypes : state.implicitTypes\n\n  for (let index = 0, length = typeList.length; index < length; index += 1) {\n    const type = typeList[index]\n\n    if ((type.instanceOf || type.predicate) &&\n        (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&\n        (!type.predicate || type.predicate(object))) {\n      if (explicit) {\n        if (type.multi && type.representName) {\n          state.tag = type.representName(object)\n        } else {\n          state.tag = type.tag\n        }\n      } else {\n        state.tag = '?'\n      }\n\n      if (type.represent) {\n        const style = state.styleMap[type.tag] || type.defaultStyle\n\n        let _result\n        if (_toString.call(type.represent) === '[object Function]') {\n          _result = type.represent(object, style)\n        } else if (_hasOwnProperty.call(type.represent, style)) {\n          _result = type.represent[style](object, style)\n        } else {\n          throw new YAMLException('!<' + type.tag + '> tag resolver accepts not \"' + style + '\" style')\n        }\n\n        state.dump = _result\n      }\n\n      return true\n    }\n  }\n\n  return false\n}\n\n// Serializes `object` and writes it to global `result`.\n// Returns true on success, or false on invalid object.\n//\nfunction writeNode (state, level, object, block, compact, iskey, isblockseq) {\n  state.tag = null\n  state.dump = object\n\n  if (!detectType(state, object, false)) {\n    detectType(state, object, true)\n  }\n\n  const type = _toString.call(state.dump)\n  const inblock = block\n\n  if (block) {\n    block = (state.flowLevel < 0 || state.flowLevel > level)\n  }\n\n  const objectOrArray = type === '[object Object]' || type === '[object Array]'\n  let duplicateIndex\n  let duplicate\n\n  if (objectOrArray) {\n    duplicateIndex = state.duplicates.indexOf(object)\n    duplicate = duplicateIndex !== -1\n  }\n\n  if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {\n    compact = false\n  }\n\n  if (duplicate && state.usedDuplicates[duplicateIndex]) {\n    state.dump = '*ref_' + duplicateIndex\n  } else {\n    if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {\n      state.usedDuplicates[duplicateIndex] = true\n    }\n    if (type === '[object Object]') {\n      if (block && (Object.keys(state.dump).length !== 0)) {\n        writeBlockMapping(state, level, state.dump, compact)\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + state.dump\n        }\n      } else {\n        writeFlowMapping(state, level, state.dump)\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump\n        }\n      }\n    } else if (type === '[object Array]') {\n      if (block && (state.dump.length !== 0)) {\n        if (state.noArrayIndent && !isblockseq && level > 0) {\n          writeBlockSequence(state, level - 1, state.dump, compact)\n        } else {\n          writeBlockSequence(state, level, state.dump, compact)\n        }\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + state.dump\n        }\n      } else {\n        writeFlowSequence(state, level, state.dump)\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump\n        }\n      }\n    } else if (type === '[object String]') {\n      if (state.tag !== '?') {\n        writeScalar(state, state.dump, level, iskey, inblock)\n      }\n    } else if (type === '[object Undefined]') {\n      return false\n    } else {\n      if (state.skipInvalid) return false\n      throw new YAMLException('unacceptable kind of an object to dump ' + type)\n    }\n\n    if (state.tag !== null && state.tag !== '?') {\n      // Need to encode all characters except those allowed by the spec:\n      //\n      // [35] ns-dec-digit    ::=  [#x30-#x39] /* 0-9 */\n      // [36] ns-hex-digit    ::=  ns-dec-digit\n      //                         | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */\n      // [37] ns-ascii-letter ::=  [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */\n      // [38] ns-word-char    ::=  ns-dec-digit | ns-ascii-letter | “-”\n      // [39] ns-uri-char     ::=  “%” ns-hex-digit ns-hex-digit | ns-word-char | “#”\n      //                         | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,”\n      //                         | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]”\n      //\n      // Also need to encode '!' because it has special meaning (end of tag prefix).\n      //\n      let tagStr = encodeURI(\n        state.tag[0] === '!' ? state.tag.slice(1) : state.tag\n      ).replace(/!/g, '%21')\n\n      if (state.tag[0] === '!') {\n        tagStr = '!' + tagStr\n      } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') {\n        tagStr = '!!' + tagStr.slice(18)\n      } else {\n        tagStr = '!<' + tagStr + '>'\n      }\n\n      state.dump = tagStr + ' ' + state.dump\n    }\n  }\n\n  return true\n}\n\nfunction getDuplicateReferences (object, state) {\n  const objects = []\n  const duplicatesIndexes = []\n\n  inspectNode(object, objects, duplicatesIndexes)\n\n  const length = duplicatesIndexes.length\n  for (let index = 0; index < length; index += 1) {\n    state.duplicates.push(objects[duplicatesIndexes[index]])\n  }\n  state.usedDuplicates = new Array(length)\n}\n\nfunction inspectNode (object, objects, duplicatesIndexes) {\n  if (object !== null && typeof object === 'object') {\n    const index = objects.indexOf(object)\n    if (index !== -1) {\n      if (duplicatesIndexes.indexOf(index) === -1) {\n        duplicatesIndexes.push(index)\n      }\n    } else {\n      objects.push(object)\n\n      if (Array.isArray(object)) {\n        for (let i = 0, length = object.length; i < length; i += 1) {\n          inspectNode(object[i], objects, duplicatesIndexes)\n        }\n      } else {\n        const objectKeyList = Object.keys(object)\n\n        for (let i = 0, length = objectKeyList.length; i < length; i += 1) {\n          inspectNode(object[objectKeyList[i]], objects, duplicatesIndexes)\n        }\n      }\n    }\n  }\n}\n\nfunction dump (input, options) {\n  options = options || {}\n\n  const state = new State(options)\n\n  if (!state.noRefs) getDuplicateReferences(input, state)\n\n  let value = input\n\n  if (state.replacer) {\n    value = state.replacer.call({ '': value }, '', value)\n  }\n\n  if (writeNode(state, 0, value, true, true)) return state.dump + '\\n'\n\n  return ''\n}\n\nmodule.exports.dump = dump\n","'use strict'\n\nconst loader = require('./lib/loader')\nconst dumper = require('./lib/dumper')\n\nfunction renamed (from, to) {\n  return function () {\n    throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' +\n      'Use yaml.' + to + ' instead, which is now safe by default.')\n  }\n}\n\nmodule.exports.Type = require('./lib/type')\nmodule.exports.Schema = require('./lib/schema')\nmodule.exports.FAILSAFE_SCHEMA = require('./lib/schema/failsafe')\nmodule.exports.JSON_SCHEMA = require('./lib/schema/json')\nmodule.exports.CORE_SCHEMA = require('./lib/schema/core')\nmodule.exports.DEFAULT_SCHEMA = require('./lib/schema/default')\nmodule.exports.load = loader.load\nmodule.exports.loadAll = loader.loadAll\nmodule.exports.dump = dumper.dump\nmodule.exports.YAMLException = require('./lib/exception')\n\n// Re-export all types in case user wants to create custom schema\nmodule.exports.types = {\n  binary: require('./lib/type/binary'),\n  float: require('./lib/type/float'),\n  map: require('./lib/type/map'),\n  null: require('./lib/type/null'),\n  pairs: require('./lib/type/pairs'),\n  set: require('./lib/type/set'),\n  timestamp: require('./lib/type/timestamp'),\n  bool: require('./lib/type/bool'),\n  int: require('./lib/type/int'),\n  merge: require('./lib/type/merge'),\n  omap: require('./lib/type/omap'),\n  seq: require('./lib/type/seq'),\n  str: require('./lib/type/str')\n}\n\n// Removed functions from JS-YAML 3.0.x\nmodule.exports.safeLoad = renamed('safeLoad', 'load')\nmodule.exports.safeLoadAll = renamed('safeLoadAll', 'loadAll')\nmodule.exports.safeDump = renamed('safeDump', 'dump')\n","import yaml from '../index.js'\n\nconst {\n  Type,\n  Schema,\n  FAILSAFE_SCHEMA,\n  JSON_SCHEMA,\n  CORE_SCHEMA,\n  DEFAULT_SCHEMA,\n  load,\n  loadAll,\n  dump,\n  YAMLException,\n  types,\n  safeLoad,\n  safeLoadAll,\n  safeDump\n} = yaml\n\nexport {\n  Type,\n  Schema,\n  FAILSAFE_SCHEMA,\n  JSON_SCHEMA,\n  CORE_SCHEMA,\n  DEFAULT_SCHEMA,\n  load,\n  loadAll,\n  dump,\n  YAMLException,\n  types,\n  safeLoad,\n  safeLoadAll,\n  safeDump\n}\n\nexport default yaml\n"],"names":["_typeof","o","Symbol","iterator","constructor","prototype","isNothing","subject","isObject","toArray","sequence","Array","isArray","extend","target","source","sourceKeys","Object","keys","index","length","key","repeat","string","count","result","cycle","isNegativeZero","number","Number","NEGATIVE_INFINITY","common","formatError","exception","compact","where","message","reason","mark","name","line","column","snippet","YAMLException","Error","call","this","captureStackTrace","stack","create","toString","require$$0","getLine","buffer","lineStart","lineEnd","position","maxLineLength","head","tail","maxHalfLength","Math","floor","str","slice","replace","pos","padStart","max","makeSnippet","options","maxLength","indent","linesBefore","linesAfter","re","lineStarts","lineEnds","match","foundLineNo","exec","push","lineNoLength","min","i","TYPE_CONSTRUCTOR_OPTIONS","YAML_NODE_KINDS","compileStyleAliases","map","forEach","style","alias","String","Type","tag","indexOf","kind","resolve","construct","data","instanceOf","predicate","represent","representName","defaultStyle","multi","styleAliases","type","require$$1","compileList","schema","currentType","newIndex","previousType","previousIndex","compileMap","scalar","mapping","fallback","collectType","arguments","Schema","definition","implicit","explicit","concat","loadKind","compiledImplicit","compiledExplicit","compiledTypeMap","seq","failsafe","require$$2","require$$3","resolveYamlNull","constructYamlNull","isNull","object","_null","canonical","lowercase","uppercase","camelcase","empty","resolveYamlBoolean","constructYamlBoolean","isBoolean","bool","isHexCode","c","isOctCode","isDecCode","resolveYamlInteger","hasDigits","ch","isFinite","parseYamlInteger","charCodeAt","value","sign","parseInt","constructYamlInteger","isInteger","int","binary","obj","octal","decimal","hexadecimal","toUpperCase","YAML_FLOAT_PATTERN","RegExp","YAML_FLOAT_SPECIAL_PATTERN","resolveYamlFloat","test","parseFloat","constructYamlFloat","toLowerCase","POSITIVE_INFINITY","NaN","SCIENTIFIC_WITHOUT_DOT","representYamlFloat","isNaN","res","isFloat","float","json","require$$4","core","YAML_DATE_REGEXP","YAML_TIMESTAMP_REGEXP","resolveYamlTimestamp","constructYamlTimestamp","fraction","delta","year","month","day","Date","UTC","hour","minute","second","tzHour","tzMinute","date","setTime","getTime","representYamlTimestamp","toISOString","timestamp","resolveYamlMerge","merge","BASE64_MAP","resolveYamlBinary","bitlen","idx","code","charAt","constructYamlBinary","input","bits","tailbits","Uint8Array","representYamlBinary","isBinary","_hasOwnProperty","hasOwnProperty","_toString","resolveYamlOmap","objectKeys","pair","pairHasKey","pairKey","defineProperty","constructYamlOmap","omap","resolveYamlPairs","constructYamlPairs","pairs","resolveYamlSet","constructYamlSet","set","_default","require$$5","require$$6","DEFAULT_SCHEMA","CONTEXT_FLOW_IN","CONTEXT_FLOW_OUT","CONTEXT_BLOCK_IN","CONTEXT_BLOCK_OUT","CHOMPING_CLIP","CHOMPING_STRIP","CHOMPING_KEEP","PATTERN_NON_PRINTABLE","PATTERN_NON_ASCII_LINE_BREAKS","PATTERN_FLOW_INDICATORS","PATTERN_TAG_HANDLE","PATTERN_TAG_URI","_class","isEol","isWhiteSpace","isWsOrEol","isFlowIndicator","fromHexCode","lc","escapedHexLen","fromDecimalCode","simpleEscapeSequence","charFromCodepoint","fromCharCode","setProperty","configurable","enumerable","writable","simpleEscapeCheck","simpleEscapeMap","State","filename","onWarning","legacy","listener","maxDepth","maxTotalMergeKeys","implicitTypes","typeMap","lineIndent","depth","totalMergeKeys","firstTabInLine","documents","anchorMapTransactions","generateError","state","throwError","throwWarning","storeAnchor","transactions","transaction","existed","anchorMap","beginAnchorTransaction","commitAnchorTransaction","pop","parent","names","rollbackAnchorTransaction","entry","snapshotState","anchor","restoreState","snapshot","directiveHandlers","YAML","handleYamlDirective","args","version","major","minor","checkLineBreaks","TAG","handleTagDirective","prefix","handle","tagMap","decodeURIComponent","err","captureSegment","start","end","checkJson","_result","_position","_length","_character","mergeMappings","destination","overridableKeys","quantity","storeMappingPair","keyTag","keyNode","valueNode","startLine","startLineStart","startPos","readLineBreak","skipSeparationSpace","allowComments","checkIndent","lineBreaks","testDocumentSeparator","writeFoldedLines","readPlainScalar","nodeIndent","withinFlowCollection","captureStart","captureEnd","hasPendingContent","_line","_lineStart","_lineIndent","_kind","following","preceding","readSingleQuotedScalar","readDoubleQuotedScalar","tmp","hexLength","hexResult","readFlowCollection","readNext","_pos","_tag","_anchor","terminator","isPair","isExplicitPair","isMapping","composeNode","readBlockScalar","folding","chomping","didReadContent","detectedIndent","textIndent","emptyLines","atMoreIndented","readBlockSequence","detected","readBlockMapping","flowIndent","allowCompact","_keyLine","_keyLineStart","_keyPos","atExplicitKey","readTagProperty","isVerbatim","isNamed","tagHandle","tagName","readAnchorProperty","readAlias","tryReadBlockMappingFromProperty","propertyStart","fallbackState","parentIndent","nodeContext","allowToSeek","allowBlockScalars","allowBlockCollections","indentStatus","atNewLine","hasContent","blockIndent","allowBlockStyles","propertyState","typeIndex","typeQuantity","typeList","readDocument","documentStart","hasDirectives","directiveName","directiveArgs","loadDocuments","nullpos","loadAll","load","loader","CHAR_BOM","CHAR_TAB","CHAR_LINE_FEED","CHAR_CARRIAGE_RETURN","CHAR_SPACE","CHAR_EXCLAMATION","CHAR_DOUBLE_QUOTE","CHAR_SHARP","CHAR_PERCENT","CHAR_AMPERSAND","CHAR_SINGLE_QUOTE","CHAR_ASTERISK","CHAR_COMMA","CHAR_MINUS","CHAR_COLON","CHAR_EQUALS","CHAR_GREATER_THAN","CHAR_QUESTION","CHAR_COMMERCIAL_AT","CHAR_LEFT_SQUARE_BRACKET","CHAR_RIGHT_SQUARE_BRACKET","CHAR_GRAVE_ACCENT","CHAR_LEFT_CURLY_BRACKET","CHAR_VERTICAL_LINE","CHAR_RIGHT_CURLY_BRACKET","ESCAPE_SEQUENCES","DEPRECATED_BOOLEANS_SYNTAX","DEPRECATED_BASE60_SYNTAX","compileStyleMap","encodeHex","character","QUOTING_TYPE_SINGLE","QUOTING_TYPE_DOUBLE","noArrayIndent","skipInvalid","flowLevel","styleMap","sortKeys","lineWidth","noRefs","noCompatMode","condenseFlow","quotingType","forceQuotes","replacer","explicitTypes","duplicates","usedDuplicates","indentString","spaces","ind","next","generateNextLine","level","testImplicitResolving","isWhitespace","isPrintable","isNsCharOrWhitespace","isPlainSafe","prev","inblock","cIsNsCharOrWhitespace","cIsNsChar","isPlainSafeFirst","isPlainSafeLast","codePointAt","first","needIndentIndicator","leadingSpaceRe","STYLE_PLAIN","STYLE_SINGLE","STYLE_LITERAL","STYLE_FOLDED","STYLE_DOUBLE","chooseScalarStyle","singleLineOnly","indentPerLevel","testAmbiguousType","char","prevChar","hasLineBreak","hasFoldableLine","shouldTrackWidth","previousLineBreak","plain","writeScalar","iskey","dump","testAmbiguity","blockHeader","dropEndingNewline","foldString","escapeString","indentIndicator","clip","keep","chomp","width","lineRe","nextLF","lastIndex","foldLine","prevMoreIndented","moreIndented","breakRe","curr","escapeSeq","writeFlowSequence","writeNode","writeBlockSequence","writeFlowMapping","objectKeyList","pairBuffer","objectKey","objectValue","writeBlockMapping","sort","explicitPair","detectType","block","isblockseq","objectOrArray","duplicateIndex","duplicate","tagStr","encodeURI","getDuplicateReferences","objects","duplicatesIndexes","inspectNode","dumper","renamed","from","to","jsYaml","FAILSAFE_SCHEMA","JSON_SCHEMA","CORE_SCHEMA","require$$7","require$$8","types","require$$9","require$$10","require$$11","null","require$$12","require$$13","require$$14","require$$15","require$$16","require$$17","require$$18","require$$19","require$$20","require$$21","safeLoad","safeLoadAll","safeDump","yaml"],"mappings":"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"}!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).jsyaml={})}(this,function(e){"use strict";function t(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var n,r,i,o,a,l,u,c,s,p,f,d,h,m,g,y,v,b,A,k,w,x,C,S,I,T,O,j,M,F,E,N,L,_,D,U,Y,q,K,R,H,P,B,W,$={},G={},Z={};function V(){if(n)return Z;function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(e){return null==e}return n=1,Z.isNothing=t,Z.isObject=function(t){return"object"===e(t)&&null!==t},Z.toArray=function(e){return Array.isArray(e)?e:t(e)?[]:[e]},Z.repeat=function(e,t){for(var n="",r=0;r<t;r+=1)n+=e;return n},Z.isNegativeZero=function(e){return 0===e&&Number.NEGATIVE_INFINITY===1/e},Z.extend=function(e,t){if(t)for(var n=Object.keys(t),r=0,i=n.length;r<i;r+=1){var o=n[r];e[o]=t[o]}return e},Z}function J(){if(i)return r;function e(e,t){var n="",r=e.reason||"(unknown reason)";return e.mark?(e.mark.name&&(n+='in "'+e.mark.name+'" '),n+="("+(e.mark.line+1)+":"+(e.mark.column+1)+")",!t&&e.mark.snippet&&(n+="\n\n"+e.mark.snippet),r+" "+n):r}function t(t,n){Error.call(this),this.name="YAMLException",this.reason=t,this.mark=n,this.message=e(this,!1),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack||""}return i=1,t.prototype=Object.create(Error.prototype),t.prototype.constructor=t,t.prototype.toString=function(t){return this.name+": "+e(this,t)},r=t}function Q(){if(u)return l;u=1;var e=J(),t=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],n=["scalar","sequence","mapping"];return l=function(r,i){var o,a;if(i=i||{},Object.keys(i).forEach(function(n){if(-1===t.indexOf(n))throw new e('Unknown option "'+n+'" is met in definition of "'+r+'" YAML type.')}),this.options=i,this.tag=r,this.kind=i.kind||null,this.resolve=i.resolve||function(){return!0},this.construct=i.construct||function(e){return e},this.instanceOf=i.instanceOf||null,this.predicate=i.predicate||null,this.represent=i.represent||null,this.representName=i.representName||null,this.defaultStyle=i.defaultStyle||null,this.multi=i.multi||!1,this.styleAliases=(o=i.styleAliases||null,a={},null!==o&&Object.keys(o).forEach(function(e){o[e].forEach(function(t){a[String(t)]=e})}),a),-1===n.indexOf(this.kind))throw new e('Unknown kind "'+this.kind+'" is specified for "'+r+'" YAML type.')}}function z(){if(s)return c;s=1;var e=J(),t=Q();function n(e,t){var n=[];return e[t].forEach(function(e){var t=n.length;n.forEach(function(n,r){n.tag===e.tag&&n.kind===e.kind&&n.multi===e.multi&&(t=r)}),n[t]=e}),n}function r(e){return this.extend(e)}return r.prototype.extend=function(i){var o=[],a=[];if(i instanceof t)a.push(i);else if(Array.isArray(i))a=a.concat(i);else{if(!i||!Array.isArray(i.implicit)&&!Array.isArray(i.explicit))throw new e("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");i.implicit&&(o=o.concat(i.implicit)),i.explicit&&(a=a.concat(i.explicit))}o.forEach(function(n){if(!(n instanceof t))throw new e("Specified list of YAML types (or a single Type object) contains a non-Type object.");if(n.loadKind&&"scalar"!==n.loadKind)throw new e("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");if(n.multi)throw new e("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")}),a.forEach(function(n){if(!(n instanceof t))throw new e("Specified list of YAML types (or a single Type object) contains a non-Type object.")});var l=Object.create(r.prototype);return l.implicit=(this.implicit||[]).concat(o),l.explicit=(this.explicit||[]).concat(a),l.compiledImplicit=n(l,"implicit"),l.compiledExplicit=n(l,"explicit"),l.compiledTypeMap=function(){var e={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}};function t(t){t.multi?(e.multi[t.kind].push(t),e.multi.fallback.push(t)):e[t.kind][t.tag]=e.fallback[t.tag]=t}for(var n=0,r=arguments.length;n<r;n+=1)arguments[n].forEach(t);return e}(l.compiledImplicit,l.compiledExplicit),l},c=r}function X(){if(f)return p;f=1;var e=Q();return p=new e("tag:yaml.org,2002:str",{kind:"scalar",construct:function(e){return null!==e?e:""}})}function ee(){if(h)return d;h=1;var e=Q();return d=new e("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(e){return null!==e?e:[]}})}function te(){if(g)return m;g=1;var e=Q();return m=new e("tag:yaml.org,2002:map",{kind:"mapping",construct:function(e){return null!==e?e:{}}})}function ne(){if(v)return y;v=1;var e=z();return y=new e({explicit:[X(),ee(),te()]})}function re(){if(A)return b;A=1;var e=Q();return b=new e("tag:yaml.org,2002:null",{kind:"scalar",resolve:function(e){if(null===e)return!0;var t=e.length;return 1===t&&"~"===e||4===t&&("null"===e||"Null"===e||"NULL"===e)},construct:function(){return null},predicate:function(e){return null===e},represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"},empty:function(){return""}},defaultStyle:"lowercase"})}function ie(){if(w)return k;w=1;var e=Q();return k=new e("tag:yaml.org,2002:bool",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t=e.length;return 4===t&&("true"===e||"True"===e||"TRUE"===e)||5===t&&("false"===e||"False"===e||"FALSE"===e)},construct:function(e){return"true"===e||"True"===e||"TRUE"===e},predicate:function(e){return"[object Boolean]"===Object.prototype.toString.call(e)},represent:{lowercase:function(e){return e?"true":"false"},uppercase:function(e){return e?"TRUE":"FALSE"},camelcase:function(e){return e?"True":"False"}},defaultStyle:"lowercase"})}function oe(){if(C)return x;C=1;var e=V(),t=Q();function n(e){return e>=48&&e<=57||e>=65&&e<=70||e>=97&&e<=102}function r(e){return e>=48&&e<=55}function i(e){return e>=48&&e<=57}function o(e){var t=e,n=1,r=t[0];if("-"!==r&&"+"!==r||("-"===r&&(n=-1),r=(t=t.slice(1))[0]),"0"===t)return 0;if("0"===r){if("b"===t[1])return n*parseInt(t.slice(2),2);if("x"===t[1])return n*parseInt(t.slice(2),16);if("o"===t[1])return n*parseInt(t.slice(2),8)}return n*parseInt(t,10)}return x=new t("tag:yaml.org,2002:int",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t=e.length,a=0,l=!1;if(!t)return!1;var u=e[a];if("-"!==u&&"+"!==u||(u=e[++a]),"0"===u){if(a+1===t)return!0;if("b"===(u=e[++a])){for(a++;a<t;a++){if("0"!==(u=e[a])&&"1"!==u)return!1;l=!0}return l&&isFinite(o(e))}if("x"===u){for(a++;a<t;a++){if(!n(e.charCodeAt(a)))return!1;l=!0}return l&&isFinite(o(e))}if("o"===u){for(a++;a<t;a++){if(!r(e.charCodeAt(a)))return!1;l=!0}return l&&isFinite(o(e))}}for(;a<t;a++){if(!i(e.charCodeAt(a)))return!1;l=!0}return!!l&&isFinite(o(e))},construct:function(e){return o(e)},predicate:function(t){return"[object Number]"===Object.prototype.toString.call(t)&&t%1==0&&!e.isNegativeZero(t)},represent:{binary:function(e){return e>=0?"0b"+e.toString(2):"-0b"+e.toString(2).slice(1)},octal:function(e){return e>=0?"0o"+e.toString(8):"-0o"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?"0x"+e.toString(16).toUpperCase():"-0x"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}})}function ae(){if(I)return S;I=1;var e=V(),t=Q(),n=new RegExp("^(?:[-+]?(?:[0-9]+)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"),r=new RegExp("^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");var i=/^[-+]?[0-9]+e/;return S=new t("tag:yaml.org,2002:float",{kind:"scalar",resolve:function(e){return null!==e&&(!!n.test(e)&&(!!isFinite(parseFloat(e,10))||r.test(e)))},construct:function(e){var t=e.toLowerCase(),n="-"===t[0]?-1:1;return"+-".indexOf(t[0])>=0&&(t=t.slice(1)),".inf"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===t?NaN:n*parseFloat(t,10)},predicate:function(t){return"[object Number]"===Object.prototype.toString.call(t)&&(t%1!=0||e.isNegativeZero(t))},represent:function(t,n){if(isNaN(t))switch(n){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===t)switch(n){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===t)switch(n){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(e.isNegativeZero(t))return"-0.0";var r=t.toString(10);return i.test(r)?r.replace("e",".e"):r},defaultStyle:"lowercase"})}function le(){return O?T:(O=1,T=ne().extend({implicit:[re(),ie(),oe(),ae()]}))}function ue(){return M?j:(M=1,j=le())}function ce(){if(E)return F;E=1;var e=Q(),t=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),n=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");return F=new e("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:function(e){return null!==e&&(null!==t.exec(e)||null!==n.exec(e))},construct:function(e){var r=0,i=null,o=t.exec(e);if(null===o&&(o=n.exec(e)),null===o)throw new Error("Date resolve error");var a=+o[1],l=+o[2]-1,u=+o[3];if(!o[4])return new Date(Date.UTC(a,l,u));var c=+o[4],s=+o[5],p=+o[6];if(o[7]){for(r=o[7].slice(0,3);r.length<3;)r+="0";r=+r}o[9]&&(i=6e4*(60*+o[10]+ +(o[11]||0)),"-"===o[9]&&(i=-i));var f=new Date(Date.UTC(a,l,u,c,s,p,r));return i&&f.setTime(f.getTime()-i),f},instanceOf:Date,represent:function(e){return e.toISOString()}})}function se(){if(L)return N;L=1;var e=Q();return N=new e("tag:yaml.org,2002:merge",{kind:"scalar",resolve:function(e){return"<<"===e||null===e}})}function pe(){if(D)return _;D=1;var e=Q(),t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";return _=new e("tag:yaml.org,2002:binary",{kind:"scalar",resolve:function(e){if(null===e)return!1;for(var n=0,r=e.length,i=t,o=0;o<r;o++){var a=i.indexOf(e.charAt(o));if(!(a>64)){if(a<0)return!1;n+=6}}return n%8==0},construct:function(e){for(var n=e.replace(/[\r\n=]/g,""),r=n.length,i=t,o=0,a=[],l=0;l<r;l++)l%4==0&&l&&(a.push(o>>16&255),a.push(o>>8&255),a.push(255&o)),o=o<<6|i.indexOf(n.charAt(l));var u=r%4*6;return 0===u?(a.push(o>>16&255),a.push(o>>8&255),a.push(255&o)):18===u?(a.push(o>>10&255),a.push(o>>2&255)):12===u&&a.push(o>>4&255),new Uint8Array(a)},predicate:function(e){return"[object Uint8Array]"===Object.prototype.toString.call(e)},represent:function(e){for(var n="",r=0,i=e.length,o=t,a=0;a<i;a++)a%3==0&&a&&(n+=o[r>>18&63],n+=o[r>>12&63],n+=o[r>>6&63],n+=o[63&r]),r=(r<<8)+e[a];var l=i%3;return 0===l?(n+=o[r>>18&63],n+=o[r>>12&63],n+=o[r>>6&63],n+=o[63&r]):2===l?(n+=o[r>>10&63],n+=o[r>>4&63],n+=o[r<<2&63],n+=o[64]):1===l&&(n+=o[r>>2&63],n+=o[r<<4&63],n+=o[64],n+=o[64]),n}})}function fe(){if(Y)return U;Y=1;var e=Q(),t=Object.prototype.hasOwnProperty,n=Object.prototype.toString;return U=new e("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(e){if(null===e)return!0;for(var r={},i=e,o=0,a=i.length;o<a;o+=1){var l=i[o],u=!1;if("[object Object]"!==n.call(l))return!1;var c=void 0;for(c in l)if(t.call(l,c)){if(u)return!1;u=!0}if(!u)return!1;if(t.call(r,c))return!1;Object.defineProperty(r,c,{value:!0})}return!0},construct:function(e){return null!==e?e:[]}})}function de(){if(K)return q;K=1;var e=Q(),t=Object.prototype.toString;return q=new e("tag:yaml.org,2002:pairs",{kind:"sequence",resolve:function(e){if(null===e)return!0;for(var n=e,r=new Array(n.length),i=0,o=n.length;i<o;i+=1){var a=n[i];if("[object Object]"!==t.call(a))return!1;var l=Object.keys(a);if(1!==l.length)return!1;r[i]=[l[0],a[l[0]]]}return!0},construct:function(e){if(null===e)return[];for(var t=e,n=new Array(t.length),r=0,i=t.length;r<i;r+=1){var o=t[r],a=Object.keys(o);n[r]=[a[0],o[a[0]]]}return n}})}function he(){if(H)return R;H=1;var e=Q(),t=Object.prototype.hasOwnProperty;return R=new e("tag:yaml.org,2002:set",{kind:"mapping",resolve:function(e){if(null===e)return!0;var n=e;for(var r in n)if(t.call(n,r)&&null!==n[r])return!1;return!0},construct:function(e){return null!==e?e:{}}})}function me(){return B?P:(B=1,P=ue().extend({implicit:[ce(),se()],explicit:[pe(),fe(),de(),he()]}))}function ge(){if(W)return G;function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}W=1;var t=V(),n=J(),r=function(){if(a)return o;a=1;var e=V();function t(e,t,n,r,i){var o="",a="",l=Math.floor(i/2)-1;return r-t>l&&(t=r-l+(o=" ... ").length),n-r>l&&(n=r+l-(a=" ...").length),{str:o+e.slice(t,n).replace(/\t/g,"→")+a,pos:r-t+o.length}}function n(t,n){return e.repeat(" ",n-t.length)+t}return o=function(r,i){if(i=Object.create(i||null),!r.buffer)return null;i.maxLength||(i.maxLength=79),"number"!=typeof i.indent&&(i.indent=1),"number"!=typeof i.linesBefore&&(i.linesBefore=3),"number"!=typeof i.linesAfter&&(i.linesAfter=2);for(var o,a=/\r?\n|\r|\0/g,l=[0],u=[],c=-1;o=a.exec(r.buffer);)u.push(o.index),l.push(o.index+o[0].length),r.position<=o.index&&c<0&&(c=l.length-2);c<0&&(c=l.length-1);for(var s="",p=Math.min(r.line+i.linesAfter,u.length).toString().length,f=i.maxLength-(i.indent+p+3),d=1;d<=i.linesBefore&&!(c-d<0);d++){var h=t(r.buffer,l[c-d],u[c-d],r.position-(l[c]-l[c-d]),f);s=e.repeat(" ",i.indent)+n((r.line-d+1).toString(),p)+" | "+h.str+"\n"+s}var m=t(r.buffer,l[c],u[c],r.position,f);s+=e.repeat(" ",i.indent)+n((r.line+1).toString(),p)+" | "+m.str+"\n",s+=e.repeat("-",i.indent+p+3+m.pos)+"^\n";for(var g=1;g<=i.linesAfter&&!(c+g>=u.length);g++){var y=t(r.buffer,l[c+g],u[c+g],r.position-(l[c]-l[c+g]),f);s+=e.repeat(" ",i.indent)+n((r.line+g+1).toString(),p)+" | "+y.str+"\n"}return s.replace(/\n$/,"")}}(),i=me(),l=Object.prototype.hasOwnProperty,u=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,c=/[\x85\u2028\u2029]/,s=/[,\[\]{}]/,p=/^(?:!|!!|![0-9A-Za-z-]+!)$/,f=/^(?:!|[^,\[\]{}])(?:%[0-9a-f]{2}|[0-9a-z\-#;/?:@&=+$,_.!~*'()\[\]])*$/i;function d(e){return Object.prototype.toString.call(e)}function h(e){return 10===e||13===e}function m(e){return 9===e||32===e}function g(e){return 9===e||32===e||10===e||13===e}function y(e){return 44===e||91===e||93===e||123===e||125===e}function v(e){if(e>=48&&e<=57)return e-48;var t=32|e;return t>=97&&t<=102?t-97+10:-1}function b(e){return 120===e?2:117===e?4:85===e?8:0}function A(e){return e>=48&&e<=57?e-48:-1}function k(e){switch(e){case 48:return"\0";case 97:return"";case 98:return"\b";case 116:case 9:return"\t";case 110:return"\n";case 118:return"\v";case 102:return"\f";case 114:return"\r";case 101:return"";case 32:return" ";case 34:return'"';case 47:return"/";case 92:return"\\";case 78:return"";case 95:return" ";case 76:return"\u2028";case 80:return"\u2029";default:return""}}function w(e){return e<=65535?String.fromCharCode(e):String.fromCharCode(55296+(e-65536>>10),56320+(e-65536&1023))}function x(e,t,n){"__proto__"===t?Object.defineProperty(e,t,{configurable:!0,enumerable:!0,writable:!0,value:n}):e[t]=n}for(var C=new Array(256),S=new Array(256),I=0;I<256;I++)C[I]=k(I)?1:0,S[I]=k(I);function T(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||i,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.maxDepth="number"==typeof t.maxDepth?t.maxDepth:100,this.maxTotalMergeKeys="number"==typeof t.maxTotalMergeKeys?t.maxTotalMergeKeys:1e4,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.depth=0,this.totalMergeKeys=0,this.firstTabInLine=-1,this.documents=[],this.anchorMapTransactions=[]}function O(e,t){var i={name:e.filename,buffer:e.input.slice(0,-1),position:e.position,line:e.line,column:e.position-e.lineStart};return i.snippet=r(i),new n(t,i)}function j(e,t){throw O(e,t)}function M(e,t){e.onWarning&&e.onWarning.call(null,O(e,t))}function F(e,t,n){var r=e.anchorMapTransactions;if(0!==r.length){var i=r[r.length-1];l.call(i,t)||(i[t]={existed:l.call(e.anchorMap,t),value:e.anchorMap[t]})}e.anchorMap[t]=n}function E(e){return{position:e.position,line:e.line,lineStart:e.lineStart,lineIndent:e.lineIndent,firstTabInLine:e.firstTabInLine,tag:e.tag,anchor:e.anchor,kind:e.kind,result:e.result}}function N(e,t){e.position=t.position,e.line=t.line,e.lineStart=t.lineStart,e.lineIndent=t.lineIndent,e.firstTabInLine=t.firstTabInLine,e.tag=t.tag,e.anchor=t.anchor,e.kind=t.kind,e.result=t.result}var L={YAML:function(e,t,n){null!==e.version&&j(e,"duplication of %YAML directive"),1!==n.length&&j(e,"YAML directive accepts exactly one argument");var r=/^([0-9]+)\.([0-9]+)$/.exec(n[0]);null===r&&j(e,"ill-formed argument of the YAML directive");var i=parseInt(r[1],10),o=parseInt(r[2],10);1!==i&&j(e,"unacceptable YAML version of the document"),e.version=n[0],e.checkLineBreaks=o<2,1!==o&&2!==o&&M(e,"unsupported YAML version of the document")},TAG:function(e,t,n){var r;2!==n.length&&j(e,"TAG directive accepts exactly two arguments");var i=n[0];r=n[1],p.test(i)||j(e,"ill-formed tag handle (first argument) of the TAG directive"),l.call(e.tagMap,i)&&j(e,'there is a previously declared suffix for "'+i+'" tag handle'),f.test(r)||j(e,"ill-formed tag prefix (second argument) of the TAG directive");try{r=decodeURIComponent(r)}catch(t){j(e,"tag prefix is malformed: "+r)}e.tagMap[i]=r}};function _(e,t,n,r){if(t<n){var i=e.input.slice(t,n);if(r)for(var o=0,a=i.length;o<a;o+=1){var l=i.charCodeAt(o);9===l||l>=32&&l<=1114111||j(e,"expected valid JSON character")}else u.test(i)&&j(e,"the stream contains non-printable characters");e.result+=i}}function D(e,n,r,i){t.isObject(r)||j(e,"cannot merge mappings; the provided source object is unacceptable");for(var o=Object.keys(r),a=0,u=o.length;a<u;a+=1){var c=o[a];-1!==e.maxTotalMergeKeys&&++e.totalMergeKeys>e.maxTotalMergeKeys&&j(e,"merge keys exceeded maxTotalMergeKeys ("+e.maxTotalMergeKeys+")"),l.call(n,c)||(x(n,c,r[c]),i[c]=!0)}}function U(t,n,r,i,o,a,u,c,s){if(Array.isArray(o))for(var p=0,f=(o=Array.prototype.slice.call(o)).length;p<f;p+=1)Array.isArray(o[p])&&j(t,"nested arrays are not supported inside keys"),"object"===e(o)&&"[object Object]"===d(o[p])&&(o[p]="[object Object]");if("object"===e(o)&&"[object Object]"===d(o)&&(o="[object Object]"),o=String(o),null===n&&(n={}),"tag:yaml.org,2002:merge"===i)if(Array.isArray(a))for(var h=0,m=a.length;h<m;h+=1)D(t,n,a[h],r);else D(t,n,a,r);else t.json||l.call(r,o)||!l.call(n,o)||(t.line=u||t.line,t.lineStart=c||t.lineStart,t.position=s||t.position,j(t,"duplicated mapping key")),x(n,o,a),delete r[o];return n}function Y(e){var t=e.input.charCodeAt(e.position);10===t?e.position++:13===t?(e.position++,10===e.input.charCodeAt(e.position)&&e.position++):j(e,"a line break is expected"),e.line+=1,e.lineStart=e.position,e.firstTabInLine=-1}function q(e,t,n){for(var r=0,i=e.input.charCodeAt(e.position);0!==i;){for(;m(i);)9===i&&-1===e.firstTabInLine&&(e.firstTabInLine=e.position),i=e.input.charCodeAt(++e.position);if(t&&35===i)do{i=e.input.charCodeAt(++e.position)}while(10!==i&&13!==i&&0!==i);if(!h(i))break;for(Y(e),i=e.input.charCodeAt(e.position),r++,e.lineIndent=0;32===i;)e.lineIndent++,i=e.input.charCodeAt(++e.position)}return-1!==n&&0!==r&&e.lineIndent<n&&M(e,"deficient indentation"),r}function K(e){var t=e.position,n=e.input.charCodeAt(t);return!(45!==n&&46!==n||n!==e.input.charCodeAt(t+1)||n!==e.input.charCodeAt(t+2)||(t+=3,0!==(n=e.input.charCodeAt(t))&&!g(n)))}function R(e,n){1===n?e.result+=" ":n>1&&(e.result+=t.repeat("\n",n-1))}function H(e,t){var n=e.tag,r=e.anchor,i=[],o=!1;if(-1!==e.firstTabInLine)return!1;null!==e.anchor&&F(e,e.anchor,i);for(var a=e.input.charCodeAt(e.position);0!==a&&(-1!==e.firstTabInLine&&(e.position=e.firstTabInLine,j(e,"tab characters must not be used in indentation")),45===a);){if(!g(e.input.charCodeAt(e.position+1)))break;if(o=!0,e.position++,q(e,!0,-1)&&e.lineIndent<=t)i.push(null),a=e.input.charCodeAt(e.position);else{var l=e.line;if(Q(e,t,3,!1,!0),i.push(e.result),q(e,!0,-1),a=e.input.charCodeAt(e.position),(e.line===l||e.lineIndent>t)&&0!==a)j(e,"bad indentation of a sequence entry");else if(e.lineIndent<t)break}}return!!o&&(e.tag=n,e.anchor=r,e.kind="sequence",e.result=i,!0)}function P(e,t,n){var r,i,o,a,l=e.tag,u=e.anchor,c={},s=Object.create(null),p=null,f=null,d=null,h=!1,y=!1;if(-1!==e.firstTabInLine)return!1;null!==e.anchor&&F(e,e.anchor,c);for(var v=e.input.charCodeAt(e.position);0!==v;){h||-1===e.firstTabInLine||(e.position=e.firstTabInLine,j(e,"tab characters must not be used in indentation"));var b=e.input.charCodeAt(e.position+1),A=e.line;if(63!==v&&58!==v||!g(b)){if(i=e.line,o=e.lineStart,a=e.position,!Q(e,n,2,!1,!0))break;if(e.line===A){for(v=e.input.charCodeAt(e.position);m(v);)v=e.input.charCodeAt(++e.position);if(58===v)g(v=e.input.charCodeAt(++e.position))||j(e,"a whitespace character is expected after the key-value separator within a block mapping"),h&&(U(e,c,s,p,f,null,i,o,a),p=f=d=null),y=!0,h=!1,r=!1,p=e.tag,f=e.result;else{if(!y)return e.tag=l,e.anchor=u,!0;j(e,"can not read an implicit mapping pair; a colon is missed")}}else{if(!y)return e.tag=l,e.anchor=u,!0;j(e,"can not read a block mapping entry; a multiline key may not be an implicit key")}}else 63===v?(h&&(U(e,c,s,p,f,null,i,o,a),p=f=d=null),y=!0,h=!0,r=!0):h?(h=!1,r=!0):j(e,"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line"),e.position+=1,v=b;if((e.line===A||e.lineIndent>t)&&(h&&(i=e.line,o=e.lineStart,a=e.position),Q(e,t,4,!0,r)&&(h?f=e.result:d=e.result),h||(U(e,c,s,p,f,d,i,o,a),p=f=d=null),q(e,!0,-1),v=e.input.charCodeAt(e.position)),(e.line===A||e.lineIndent>t)&&0!==v)j(e,"bad indentation of a mapping entry");else if(e.lineIndent<t)break}return h&&U(e,c,s,p,f,null,i,o,a),y&&(e.tag=l,e.anchor=u,e.kind="mapping",e.result=c),y}function B(e){var t,n,r=!1,i=!1,o=e.input.charCodeAt(e.position);if(33!==o)return!1;null!==e.tag&&j(e,"duplication of a tag property"),60===(o=e.input.charCodeAt(++e.position))?(r=!0,o=e.input.charCodeAt(++e.position)):33===o?(i=!0,t="!!",o=e.input.charCodeAt(++e.position)):t="!";var a=e.position;if(r){do{o=e.input.charCodeAt(++e.position)}while(0!==o&&62!==o);e.position<e.length?(n=e.input.slice(a,e.position),o=e.input.charCodeAt(++e.position)):j(e,"unexpected end of the stream within a verbatim tag")}else{for(;0!==o&&!g(o);)33===o&&(i?j(e,"tag suffix cannot contain exclamation marks"):(t=e.input.slice(a-1,e.position+1),p.test(t)||j(e,"named tag handle cannot contain such characters"),i=!0,a=e.position+1)),o=e.input.charCodeAt(++e.position);n=e.input.slice(a,e.position),s.test(n)&&j(e,"tag suffix cannot contain flow indicator characters")}n&&!f.test(n)&&j(e,"tag name cannot contain such characters: "+n);try{n=decodeURIComponent(n)}catch(t){j(e,"tag name is malformed: "+n)}return r?e.tag=n:l.call(e.tagMap,t)?e.tag=e.tagMap[t]+n:"!"===t?e.tag="!"+n:"!!"===t?e.tag="tag:yaml.org,2002:"+n:j(e,'undeclared tag handle "'+t+'"'),!0}function $(e){var t=e.input.charCodeAt(e.position);if(38!==t)return!1;null!==e.anchor&&j(e,"duplication of an anchor property"),t=e.input.charCodeAt(++e.position);for(var n=e.position;0!==t&&!g(t)&&!y(t);)t=e.input.charCodeAt(++e.position);return e.position===n&&j(e,"name of an anchor node must contain at least one character"),e.anchor=e.input.slice(n,e.position),!0}function Z(e,t,n,r){var i=E(e);return function(e){e.anchorMapTransactions.push(Object.create(null))}(e),N(e,t),e.tag=null,e.anchor=null,e.kind=null,e.result=null,P(e,n,r)&&"mapping"===e.kind?(function(e){var t=e.anchorMapTransactions.pop(),n=e.anchorMapTransactions;if(0!==n.length)for(var r=n[n.length-1],i=Object.keys(t),o=0,a=i.length;o<a;o+=1){var u=i[o];l.call(r,u)||(r[u]=t[u])}}(e),!0):(function(e){for(var t=e.anchorMapTransactions.pop(),n=Object.keys(t),r=n.length-1;r>=0;r-=1){var i=t[n[r]];i.existed?e.anchorMap[n[r]]=i.value:delete e.anchorMap[n[r]]}}(e),N(e,i),!1)}function Q(e,n,r,i,o){var a,u,c,s,p,f=1,d=!1,k=!1,x=null;e.depth>=e.maxDepth&&j(e,"nesting exceeded maxDepth ("+e.maxDepth+")"),e.depth+=1,null!==e.listener&&e.listener("open",e),e.tag=null,e.anchor=null,e.kind=null,e.result=null;var I=a=u=4===r||3===r;if(i&&q(e,!0,-1)&&(d=!0,e.lineIndent>n?f=1:e.lineIndent===n?f=0:e.lineIndent<n&&(f=-1)),1===f)for(;;){var T=e.input.charCodeAt(e.position),O=E(e);if(d&&(33===T&&null!==e.tag||38===T&&null!==e.anchor))break;if(!B(e)&&!$(e))break;null===x&&(x=O),q(e,!0,-1)?(d=!0,u=I,e.lineIndent>n?f=1:e.lineIndent===n?f=0:e.lineIndent<n&&(f=-1)):u=!1}if(u&&(u=d||o),1===f||4===r)if(s=1===r||2===r?n:n+1,p=e.position-e.lineStart,1===f)if(u&&(H(e,p)||P(e,p,s))||function(e,t){var n,r,i,o,a,l,u,c,s,p,f,d=!0,h=e.tag,m=e.anchor,y=Object.create(null),v=e.input.charCodeAt(e.position);if(91===v)a=93,c=!1,o=[];else{if(123!==v)return!1;a=125,c=!0,o={}}for(null!==e.anchor&&F(e,e.anchor,o),v=e.input.charCodeAt(++e.position);0!==v;){if(q(e,!0,t),(v=e.input.charCodeAt(e.position))===a)return e.position++,e.tag=h,e.anchor=m,e.kind=c?"mapping":"sequence",e.result=o,!0;d?44===v&&j(e,"expected the node content, but found ','"):j(e,"missed comma between flow collection entries"),f=null,l=u=!1,63===v&&g(e.input.charCodeAt(e.position+1))&&(l=u=!0,e.position++,q(e,!0,t)),n=e.line,r=e.lineStart,i=e.position,Q(e,t,1,!1,!0),p=e.tag,s=e.result,q(e,!0,t),v=e.input.charCodeAt(e.position),!u&&e.line!==n||58!==v||(l=!0,v=e.input.charCodeAt(++e.position),q(e,!0,t),Q(e,t,1,!1,!0),f=e.result),c?U(e,o,y,p,s,f,n,r,i):l?o.push(U(e,null,y,p,s,f,n,r,i)):o.push(s),q(e,!0,t),44===(v=e.input.charCodeAt(e.position))?(d=!0,v=e.input.charCodeAt(++e.position)):d=!1}j(e,"unexpected end of the stream within a flow collection")}(e,s))k=!0;else{var M=e.input.charCodeAt(e.position);null!==x&&I&&!u&&124!==M&&62!==M&&Z(e,x,x.position-x.lineStart,s)||a&&function(e,n){var r,i,o=1,a=!1,l=!1,u=n,c=0,s=!1,p=e.input.charCodeAt(e.position);if(124===p)r=!1;else{if(62!==p)return!1;r=!0}for(e.kind="scalar",e.result="";0!==p;)if(43===(p=e.input.charCodeAt(++e.position))||45===p)1===o?o=43===p?3:2:j(e,"repeat of a chomping mode identifier");else{if(!((i=A(p))>=0))break;0===i?j(e,"bad explicit indentation width of a block scalar; it cannot be less than one"):l?j(e,"repeat of an indentation width identifier"):(u=n+i-1,l=!0)}if(m(p)){do{p=e.input.charCodeAt(++e.position)}while(m(p));if(35===p)do{p=e.input.charCodeAt(++e.position)}while(!h(p)&&0!==p)}for(;0!==p;){for(Y(e),e.lineIndent=0,p=e.input.charCodeAt(e.position);(!l||e.lineIndent<u)&&32===p;)e.lineIndent++,p=e.input.charCodeAt(++e.position);if(!l&&e.lineIndent>u&&(u=e.lineIndent),h(p))c++;else{if(l||0!==u||j(e,"missing indentation for block scalar"),e.lineIndent<u){3===o?e.result+=t.repeat("\n",a?1+c:c):1===o&&a&&(e.result+="\n");break}r?m(p)?(s=!0,e.result+=t.repeat("\n",a?1+c:c)):s?(s=!1,e.result+=t.repeat("\n",c+1)):0===c?a&&(e.result+=" "):e.result+=t.repeat("\n",c):e.result+=t.repeat("\n",a?1+c:c),a=!0,l=!0,c=0;for(var f=e.position;!h(p)&&0!==p;)p=e.input.charCodeAt(++e.position);_(e,f,e.position,!1)}}return!0}(e,s)||function(e,t){var n,r,i=e.input.charCodeAt(e.position);if(39!==i)return!1;for(e.kind="scalar",e.result="",e.position++,n=r=e.position;0!==(i=e.input.charCodeAt(e.position));)if(39===i){if(_(e,n,e.position,!0),39!==(i=e.input.charCodeAt(++e.position)))return!0;n=e.position,e.position++,r=e.position}else h(i)?(_(e,n,r,!0),R(e,q(e,!1,t)),n=r=e.position):e.position===e.lineStart&&K(e)?j(e,"unexpected end of the document within a single quoted scalar"):(e.position++,m(i)||(r=e.position));j(e,"unexpected end of the stream within a single quoted scalar")}(e,s)||function(e,t){var n,r,i,o=e.input.charCodeAt(e.position);if(34!==o)return!1;for(e.kind="scalar",e.result="",e.position++,n=r=e.position;0!==(o=e.input.charCodeAt(e.position));){if(34===o)return _(e,n,e.position,!0),e.position++,!0;if(92===o){if(_(e,n,e.position,!0),h(o=e.input.charCodeAt(++e.position)))q(e,!1,t);else if(o<256&&C[o])e.result+=S[o],e.position++;else if((i=b(o))>0){for(var a=i,l=0;a>0;a--)(i=v(o=e.input.charCodeAt(++e.position)))>=0?l=(l<<4)+i:j(e,"expected hexadecimal character");e.result+=w(l),e.position++}else j(e,"unknown escape sequence");n=r=e.position}else h(o)?(_(e,n,r,!0),R(e,q(e,!1,t)),n=r=e.position):e.position===e.lineStart&&K(e)?j(e,"unexpected end of the document within a double quoted scalar"):(e.position++,m(o)||(r=e.position))}j(e,"unexpected end of the stream within a double quoted scalar")}(e,s)?k=!0:!function(e){var t=e.input.charCodeAt(e.position);if(42!==t)return!1;t=e.input.charCodeAt(++e.position);for(var n=e.position;0!==t&&!g(t)&&!y(t);)t=e.input.charCodeAt(++e.position);e.position===n&&j(e,"name of an alias node must contain at least one character");var r=e.input.slice(n,e.position);return l.call(e.anchorMap,r)||j(e,'unidentified alias "'+r+'"'),e.result=e.anchorMap[r],q(e,!0,-1),!0}(e)?function(e,t,n){var r,i,o,a,l,u,c=e.kind,s=e.result,p=e.input.charCodeAt(e.position);if(g(p)||y(p)||35===p||38===p||42===p||33===p||124===p||62===p||39===p||34===p||37===p||64===p||96===p)return!1;if(63===p||45===p){var f=e.input.charCodeAt(e.position+1);if(g(f)||n&&y(f))return!1}for(e.kind="scalar",e.result="",r=i=e.position,o=!1;0!==p;){if(58===p){var d=e.input.charCodeAt(e.position+1);if(g(d)||n&&y(d))break}else if(35===p){if(g(e.input.charCodeAt(e.position-1)))break}else{if(e.position===e.lineStart&&K(e)||n&&y(p))break;if(h(p)){if(a=e.line,l=e.lineStart,u=e.lineIndent,q(e,!1,-1),e.lineIndent>=t){o=!0,p=e.input.charCodeAt(e.position);continue}e.position=i,e.line=a,e.lineStart=l,e.lineIndent=u;break}}o&&(_(e,r,i,!1),R(e,e.line-a),r=i=e.position,o=!1),m(p)||(i=e.position+1),p=e.input.charCodeAt(++e.position)}return _(e,r,i,!1),!!e.result||(e.kind=c,e.result=s,!1)}(e,s,1===r)&&(k=!0,null===e.tag&&(e.tag="?")):(k=!0,null===e.tag&&null===e.anchor||j(e,"alias node should not have any properties")),null!==e.anchor&&F(e,e.anchor,e.result)}else 0===f&&(k=u&&H(e,p));if(null===e.tag)null!==e.anchor&&F(e,e.anchor,e.result);else if("?"===e.tag){null!==e.result&&"scalar"!==e.kind&&j(e,'unacceptable node kind for !<?> tag; it should be "scalar", not "'+e.kind+'"');for(var N=0,L=e.implicitTypes.length;N<L;N+=1)if((c=e.implicitTypes[N]).resolve(e.result)){e.result=c.construct(e.result),e.tag=c.tag,null!==e.anchor&&F(e,e.anchor,e.result);break}}else if("!"!==e.tag){if(l.call(e.typeMap[e.kind||"fallback"],e.tag))c=e.typeMap[e.kind||"fallback"][e.tag];else{c=null;for(var D=e.typeMap.multi[e.kind||"fallback"],W=0,G=D.length;W<G;W+=1)if(e.tag.slice(0,D[W].tag.length)===D[W].tag){c=D[W];break}}c||j(e,"unknown tag !<"+e.tag+">"),null!==e.result&&c.kind!==e.kind&&j(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+c.kind+'", not "'+e.kind+'"'),c.resolve(e.result,e.tag)?(e.result=c.construct(e.result,e.tag),null!==e.anchor&&F(e,e.anchor,e.result)):j(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")}return null!==e.listener&&e.listener("close",e),e.depth-=1,null!==e.tag||null!==e.anchor||k}function z(e){var t,n=e.position,r=!1;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap=Object.create(null),e.anchorMap=Object.create(null);0!==(t=e.input.charCodeAt(e.position))&&(q(e,!0,-1),t=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==t));){r=!0,t=e.input.charCodeAt(++e.position);for(var i=e.position;0!==t&&!g(t);)t=e.input.charCodeAt(++e.position);var o=e.input.slice(i,e.position),a=[];for(o.length<1&&j(e,"directive name must not be less than one character in length");0!==t;){for(;m(t);)t=e.input.charCodeAt(++e.position);if(35===t){do{t=e.input.charCodeAt(++e.position)}while(0!==t&&!h(t));break}if(h(t))break;for(i=e.position;0!==t&&!g(t);)t=e.input.charCodeAt(++e.position);a.push(e.input.slice(i,e.position))}0!==t&&Y(e),l.call(L,o)?L[o](e,o,a):M(e,'unknown document directive "'+o+'"')}q(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,q(e,!0,-1)):r&&j(e,"directives end mark is expected"),Q(e,e.lineIndent-1,4,!1,!0),q(e,!0,-1),e.checkLineBreaks&&c.test(e.input.slice(n,e.position))&&M(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&K(e)?46===e.input.charCodeAt(e.position)&&(e.position+=3,q(e,!0,-1)):e.position<e.length-1&&j(e,"end of the stream or a document separator is expected")}function X(e,t){t=t||{},0!==(e=String(e)).length&&(10!==e.charCodeAt(e.length-1)&&13!==e.charCodeAt(e.length-1)&&(e+="\n"),65279===e.charCodeAt(0)&&(e=e.slice(1)));var n=new T(e,t),r=e.indexOf("\0");for(-1!==r&&(n.position=r,j(n,"null byte is not allowed in input")),n.input+="\0";32===n.input.charCodeAt(n.position);)n.lineIndent+=1,n.position+=1;for(;n.position<n.length-1;)z(n);return n.documents}return G.loadAll=function(t,n,r){null!==n&&"object"===e(n)&&void 0===r&&(r=n,n=null);var i=X(t,r);if("function"!=typeof n)return i;for(var o=0,a=i.length;o<a;o+=1)n(i[o])},G.load=function(e,t){var r=X(e,t);if(0!==r.length){if(1===r.length)return r[0];throw new n("expected a single document in the stream, but found more")}},G}var ye,ve,be={};function Ae(){if(ye)return be;function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}ye=1;var t=V(),n=J(),r=me(),i=Object.prototype.toString,o=Object.prototype.hasOwnProperty,a=65279,l={0:"\\0",7:"\\a",8:"\\b",9:"\\t",10:"\\n",11:"\\v",12:"\\f",13:"\\r",27:"\\e",34:'\\"',92:"\\\\",133:"\\N",160:"\\_",8232:"\\L",8233:"\\P"},u=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"],c=/^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;function s(e){var r,i,o=e.toString(16).toUpperCase();if(e<=255)r="x",i=2;else if(e<=65535)r="u",i=4;else{if(!(e<=4294967295))throw new n("code point within a string may not be greater than 0xFFFFFFFF");r="U",i=8}return"\\"+r+t.repeat("0",i-o.length)+o}function p(e){this.schema=e.schema||r,this.indent=Math.max(1,e.indent||2),this.noArrayIndent=e.noArrayIndent||!1,this.skipInvalid=e.skipInvalid||!1,this.flowLevel=t.isNothing(e.flowLevel)?-1:e.flowLevel,this.styleMap=function(e,t){if(null===t)return{};for(var n={},r=Object.keys(t),i=0,a=r.length;i<a;i+=1){var l=r[i],u=String(t[l]);"!!"===l.slice(0,2)&&(l="tag:yaml.org,2002:"+l.slice(2));var c=e.compiledTypeMap.fallback[l];c&&o.call(c.styleAliases,u)&&(u=c.styleAliases[u]),n[l]=u}return n}(this.schema,e.styles||null),this.sortKeys=e.sortKeys||!1,this.lineWidth=e.lineWidth||80,this.noRefs=e.noRefs||!1,this.noCompatMode=e.noCompatMode||!1,this.condenseFlow=e.condenseFlow||!1,this.quotingType='"'===e.quotingType?2:1,this.forceQuotes=e.forceQuotes||!1,this.replacer="function"==typeof e.replacer?e.replacer:null,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result="",this.duplicates=[],this.usedDuplicates=null}function f(e,n){for(var r=t.repeat(" ",n),i=0,o="",a=e.length;i<a;){var l=void 0,u=e.indexOf("\n",i);-1===u?(l=e.slice(i),i=a):(l=e.slice(i,u+1),i=u+1),l.length&&"\n"!==l&&(o+=r),o+=l}return o}function d(e,n){return"\n"+t.repeat(" ",e.indent*n)}function h(e){return 32===e||9===e}function m(e){return e>=32&&e<=126||e>=161&&e<=55295&&8232!==e&&8233!==e||e>=57344&&e<=65533&&e!==a||e>=65536&&e<=1114111}function g(e){return m(e)&&e!==a&&13!==e&&10!==e}function y(e,t,n){var r=g(e),i=r&&!h(e);return(n?r:r&&44!==e&&91!==e&&93!==e&&123!==e&&125!==e)&&35!==e&&!(58===t&&!i)||g(t)&&!h(t)&&35===e||58===t&&i}function v(e,t){var n,r=e.charCodeAt(t);return r>=55296&&r<=56319&&t+1<e.length&&(n=e.charCodeAt(t+1))>=56320&&n<=57343?1024*(r-55296)+n-56320+65536:r}function b(e){return/^\n* /.test(e)}function A(e,t,n,r,i,o,l,u){var c,s,p=0,f=null,d=!1,g=!1,A=-1!==r,k=-1,w=m(s=v(e,0))&&s!==a&&!h(s)&&45!==s&&63!==s&&58!==s&&44!==s&&91!==s&&93!==s&&123!==s&&125!==s&&35!==s&&38!==s&&42!==s&&33!==s&&124!==s&&61!==s&&62!==s&&39!==s&&34!==s&&37!==s&&64!==s&&96!==s&&function(e){return!h(e)&&58!==e}(v(e,e.length-1));if(t||l)for(c=0;c<e.length;p>=65536?c+=2:c++){if(!m(p=v(e,c)))return 5;w=w&&y(p,f,u),f=p}else{for(c=0;c<e.length;p>=65536?c+=2:c++){if(10===(p=v(e,c)))d=!0,A&&(g=g||c-k-1>r&&" "!==e[k+1],k=c);else if(!m(p))return 5;w=w&&y(p,f,u),f=p}g=g||A&&c-k-1>r&&" "!==e[k+1]}return d||g?n>9&&b(e)?5:l?2===o?5:2:g?4:3:!w||l||i(e)?2===o?5:2:1}function k(e,t,r,i,o){e.dump=function(){if(0===t.length)return 2===e.quotingType?'""':"''";if(!e.noCompatMode&&(-1!==u.indexOf(t)||c.test(t)))return 2===e.quotingType?'"'+t+'"':"'"+t+"'";var a=e.indent*Math.max(1,r),p=-1===e.lineWidth?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-a),d=i||e.flowLevel>-1&&r>=e.flowLevel;switch(A(t,d,e.indent,p,function(t){return function(e,t){for(var n=0,r=e.implicitTypes.length;n<r;n+=1)if(e.implicitTypes[n].resolve(t))return!0;return!1}(e,t)},e.quotingType,e.forceQuotes&&!i,o)){case 1:return t;case 2:return"'"+t.replace(/'/g,"''")+"'";case 3:return"|"+w(t,e.indent)+x(f(t,a));case 4:return">"+w(t,e.indent)+x(f(function(e,t){var n,r,i=/(\n+)([^\n]*)/g,o=(l=e.indexOf("\n"),l=-1!==l?l:e.length,i.lastIndex=l,C(e.slice(0,l),t)),a="\n"===e[0]||" "===e[0];var l;for(;r=i.exec(e);){var u=r[1],c=r[2];n=" "===c[0],o+=u+(a||n||""===c?"":"\n")+C(c,t),a=n}return o}(t,p),a));case 5:return'"'+function(e){for(var t="",n=0,r=0;r<e.length;n>=65536?r+=2:r++){n=v(e,r);var i=l[n];!i&&m(n)?(t+=e[r],n>=65536&&(t+=e[r+1])):t+=i||s(n)}return t}(t)+'"';default:throw new n("impossible error: invalid scalar style")}}()}function w(e,t){var n=b(e)?String(t):"",r="\n"===e[e.length-1];return n+(r&&("\n"===e[e.length-2]||"\n"===e)?"+":r?"":"-")+"\n"}function x(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function C(e,t){if(""===e||" "===e[0])return e;for(var n,r,i=/ [^ ]/g,o=0,a=0,l=0,u="";n=i.exec(e);)(l=n.index)-o>t&&(r=a>o?a:l,u+="\n"+e.slice(o,r),o=r+1),a=l;return u+="\n",e.length-o>t&&a>o?u+=e.slice(o,a)+"\n"+e.slice(a+1):u+=e.slice(o),u.slice(1)}function S(e,t,n,r){for(var i="",o=e.tag,a=0,l=n.length;a<l;a+=1){var u=n[a];e.replacer&&(u=e.replacer.call(n,String(a),u)),(T(e,t+1,u,!0,!0,!1,!0)||void 0===u&&T(e,t+1,null,!0,!0,!1,!0))&&(r&&""===i||(i+=d(e,t)),e.dump&&10===e.dump.charCodeAt(0)?i+="-":i+="- ",i+=e.dump)}e.tag=o,e.dump=i||"[]"}function I(t,r,a){for(var l=a?t.explicitTypes:t.implicitTypes,u=0,c=l.length;u<c;u+=1){var s=l[u];if((s.instanceOf||s.predicate)&&(!s.instanceOf||"object"===e(r)&&r instanceof s.instanceOf)&&(!s.predicate||s.predicate(r))){if(a?s.multi&&s.representName?t.tag=s.representName(r):t.tag=s.tag:t.tag="?",s.represent){var p=t.styleMap[s.tag]||s.defaultStyle,f=void 0;if("[object Function]"===i.call(s.represent))f=s.represent(r,p);else{if(!o.call(s.represent,p))throw new n("!<"+s.tag+'> tag resolver accepts not "'+p+'" style');f=s.represent[p](r,p)}t.dump=f}return!0}}return!1}function T(e,t,r,o,a,l,u){e.tag=null,e.dump=r,I(e,r,!1)||I(e,r,!0);var c=i.call(e.dump),s=o;o&&(o=e.flowLevel<0||e.flowLevel>t);var p,f,h="[object Object]"===c||"[object Array]"===c;if(h&&(f=-1!==(p=e.duplicates.indexOf(r))),(null!==e.tag&&"?"!==e.tag||f||2!==e.indent&&t>0)&&(a=!1),f&&e.usedDuplicates[p])e.dump="*ref_"+p;else{if(h&&f&&!e.usedDuplicates[p]&&(e.usedDuplicates[p]=!0),"[object Object]"===c)o&&0!==Object.keys(e.dump).length?(!function(e,t,r,i){var o="",a=e.tag,l=Object.keys(r);if(!0===e.sortKeys)l.sort();else if("function"==typeof e.sortKeys)l.sort(e.sortKeys);else if(e.sortKeys)throw new n("sortKeys must be a boolean or a function");for(var u=0,c=l.length;u<c;u+=1){var s="";i&&""===o||(s+=d(e,t));var p=l[u],f=r[p];if(e.replacer&&(f=e.replacer.call(r,p,f)),T(e,t+1,p,!0,!0,!0)){var h=null!==e.tag&&"?"!==e.tag||e.dump&&e.dump.length>1024;h&&(e.dump&&10===e.dump.charCodeAt(0)?s+="?":s+="? "),s+=e.dump,h&&(s+=d(e,t)),T(e,t+1,f,!0,h)&&(e.dump&&10===e.dump.charCodeAt(0)?s+=":":s+=": ",o+=s+=e.dump)}}e.tag=a,e.dump=o||"{}"}(e,t,e.dump,a),f&&(e.dump="&ref_"+p+e.dump)):(!function(e,t,n){for(var r="",i=e.tag,o=Object.keys(n),a=0,l=o.length;a<l;a+=1){var u="";""!==r&&(u+=", "),e.condenseFlow&&(u+='"');var c=o[a],s=n[c];e.replacer&&(s=e.replacer.call(n,c,s)),T(e,t,c,!1,!1)&&(e.dump.length>1024&&(u+="? "),u+=e.dump+(e.condenseFlow?'"':"")+":"+(e.condenseFlow?"":" "),T(e,t,s,!1,!1)&&(r+=u+=e.dump))}e.tag=i,e.dump="{"+r+"}"}(e,t,e.dump),f&&(e.dump="&ref_"+p+" "+e.dump));else if("[object Array]"===c)o&&0!==e.dump.length?(e.noArrayIndent&&!u&&t>0?S(e,t-1,e.dump,a):S(e,t,e.dump,a),f&&(e.dump="&ref_"+p+e.dump)):(!function(e,t,n){for(var r="",i=e.tag,o=0,a=n.length;o<a;o+=1){var l=n[o];e.replacer&&(l=e.replacer.call(n,String(o),l)),(T(e,t,l,!1,!1)||void 0===l&&T(e,t,null,!1,!1))&&(""!==r&&(r+=","+(e.condenseFlow?"":" ")),r+=e.dump)}e.tag=i,e.dump="["+r+"]"}(e,t,e.dump),f&&(e.dump="&ref_"+p+" "+e.dump));else{if("[object String]"!==c){if("[object Undefined]"===c)return!1;if(e.skipInvalid)return!1;throw new n("unacceptable kind of an object to dump "+c)}"?"!==e.tag&&k(e,e.dump,t,l,s)}if(null!==e.tag&&"?"!==e.tag){var m=encodeURI("!"===e.tag[0]?e.tag.slice(1):e.tag).replace(/!/g,"%21");m="!"===e.tag[0]?"!"+m:"tag:yaml.org,2002:"===m.slice(0,18)?"!!"+m.slice(18):"!<"+m+">",e.dump=m+" "+e.dump}}return!0}function O(e,t){var n=[],r=[];j(e,n,r);for(var i=r.length,o=0;o<i;o+=1)t.duplicates.push(n[r[o]]);t.usedDuplicates=new Array(i)}function j(t,n,r){if(null!==t&&"object"===e(t)){var i=n.indexOf(t);if(-1!==i)-1===r.indexOf(i)&&r.push(i);else if(n.push(t),Array.isArray(t))for(var o=0,a=t.length;o<a;o+=1)j(t[o],n,r);else for(var l=Object.keys(t),u=0,c=l.length;u<c;u+=1)j(t[l[u]],n,r)}}return be.dump=function(e,t){var n=new p(t=t||{});n.noRefs||O(e,n);var r=e;return n.replacer&&(r=n.replacer.call({"":r},"",r)),T(n,0,r,!0,!0)?n.dump+"\n":""},be}var ke=t(function(){if(ve)return $;ve=1;var e=ge(),t=Ae();function n(e,t){return function(){throw new Error("Function yaml."+e+" is removed in js-yaml 4. Use yaml."+t+" instead, which is now safe by default.")}}return $.Type=Q(),$.Schema=z(),$.FAILSAFE_SCHEMA=ne(),$.JSON_SCHEMA=le(),$.CORE_SCHEMA=ue(),$.DEFAULT_SCHEMA=me(),$.load=e.load,$.loadAll=e.loadAll,$.dump=t.dump,$.YAMLException=J(),$.types={binary:pe(),float:ae(),map:te(),null:re(),pairs:de(),set:he(),timestamp:ce(),bool:ie(),int:oe(),merge:se(),omap:fe(),seq:ee(),str:X()},$.safeLoad=n("safeLoad","load"),$.safeLoadAll=n("safeLoadAll","loadAll"),$.safeDump=n("safeDump","dump"),$}()),we=ke.Type,xe=ke.Schema,Ce=ke.FAILSAFE_SCHEMA,Se=ke.JSON_SCHEMA,Ie=ke.CORE_SCHEMA,Te=ke.DEFAULT_SCHEMA,Oe=ke.load,je=ke.loadAll,Me=ke.dump,Fe=ke.YAMLException,Ee=ke.types,Ne=ke.safeLoad,Le=ke.safeLoadAll,_e=ke.safeDump;e.CORE_SCHEMA=Ie,e.DEFAULT_SCHEMA=Te,e.FAILSAFE_SCHEMA=Ce,e.JSON_SCHEMA=Se,e.Schema=xe,e.Type=we,e.YAMLException=Fe,e.default=ke,e.dump=Me,e.load=Oe,e.loadAll=je,e.safeDump=_e,e.safeLoad=Ne,e.safeLoadAll=Le,e.types=Ee,Object.defineProperty(e,"__esModule",{value:!0})});
//# sourceMappingURL=js-yaml.min.js.map
{"version":3,"file":"js-yaml.min.js","sources":["../lib/common.js","../lib/exception.js","../lib/type.js","../lib/schema.js","../lib/type/str.js","../lib/type/seq.js","../lib/type/map.js","../lib/schema/failsafe.js","../lib/type/null.js","../lib/type/bool.js","../lib/type/int.js","../lib/type/float.js","../lib/schema/json.js","../lib/schema/core.js","../lib/type/timestamp.js","../lib/type/merge.js","../lib/type/binary.js","../lib/type/omap.js","../lib/type/pairs.js","../lib/type/set.js","../lib/schema/default.js","../lib/loader.js","../lib/snippet.js","../lib/dumper.js","../index.js","../lib/index_vite_proxy.tmp.mjs"],"sourcesContent":["'use strict'\n\nfunction isNothing (subject) {\n  return (typeof subject === 'undefined') || (subject === null)\n}\n\nfunction isObject (subject) {\n  return (typeof subject === 'object') && (subject !== null)\n}\n\nfunction toArray (sequence) {\n  if (Array.isArray(sequence)) return sequence\n  else if (isNothing(sequence)) return []\n\n  return [sequence]\n}\n\nfunction extend (target, source) {\n  if (source) {\n    const sourceKeys = Object.keys(source)\n\n    for (let index = 0, length = sourceKeys.length; index < length; index += 1) {\n      const key = sourceKeys[index]\n      target[key] = source[key]\n    }\n  }\n\n  return target\n}\n\nfunction repeat (string, count) {\n  let result = ''\n\n  for (let cycle = 0; cycle < count; cycle += 1) {\n    result += string\n  }\n\n  return result\n}\n\nfunction isNegativeZero (number) {\n  return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number)\n}\n\nmodule.exports.isNothing = isNothing\nmodule.exports.isObject = isObject\nmodule.exports.toArray = toArray\nmodule.exports.repeat = repeat\nmodule.exports.isNegativeZero = isNegativeZero\nmodule.exports.extend = extend\n","// YAML error class. http://stackoverflow.com/questions/8458984\n//\n'use strict'\n\nfunction formatError (exception, compact) {\n  let where = ''\n  const message = exception.reason || '(unknown reason)'\n\n  if (!exception.mark) return message\n\n  if (exception.mark.name) {\n    where += 'in \"' + exception.mark.name + '\" '\n  }\n\n  where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')'\n\n  if (!compact && exception.mark.snippet) {\n    where += '\\n\\n' + exception.mark.snippet\n  }\n\n  return message + ' ' + where\n}\n\nfunction YAMLException (reason, mark) {\n  // Super constructor\n  Error.call(this)\n\n  this.name = 'YAMLException'\n  this.reason = reason\n  this.mark = mark\n  this.message = formatError(this, false)\n\n  // Include stack trace in error object\n  if (Error.captureStackTrace) {\n    // Chrome and NodeJS\n    Error.captureStackTrace(this, this.constructor)\n  } else {\n    // FF, IE 10+ and Safari 6+. Fallback for others\n    this.stack = (new Error()).stack || ''\n  }\n}\n\n// Inherit from Error\nYAMLException.prototype = Object.create(Error.prototype)\nYAMLException.prototype.constructor = YAMLException\n\nYAMLException.prototype.toString = function toString (compact) {\n  return this.name + ': ' + formatError(this, compact)\n}\n\nmodule.exports = YAMLException\n","'use strict'\n\nconst YAMLException = require('./exception')\n\nconst TYPE_CONSTRUCTOR_OPTIONS = [\n  'kind',\n  'multi',\n  'resolve',\n  'construct',\n  'instanceOf',\n  'predicate',\n  'represent',\n  'representName',\n  'defaultStyle',\n  'styleAliases'\n]\n\nconst YAML_NODE_KINDS = [\n  'scalar',\n  'sequence',\n  'mapping'\n]\n\nfunction compileStyleAliases (map) {\n  const result = {}\n\n  if (map !== null) {\n    Object.keys(map).forEach(function (style) {\n      map[style].forEach(function (alias) {\n        result[String(alias)] = style\n      })\n    })\n  }\n\n  return result\n}\n\nfunction Type (tag, options) {\n  options = options || {}\n\n  Object.keys(options).forEach(function (name) {\n    if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {\n      throw new YAMLException('Unknown option \"' + name + '\" is met in definition of \"' + tag + '\" YAML type.')\n    }\n  })\n\n  // TODO: Add tag format check.\n  this.options = options // keep original options in case user wants to extend this type later\n  this.tag = tag\n  this.kind = options['kind'] || null\n  this.resolve = options['resolve'] || function () { return true }\n  this.construct = options['construct'] || function (data) { return data }\n  this.instanceOf = options['instanceOf'] || null\n  this.predicate = options['predicate'] || null\n  this.represent = options['represent'] || null\n  this.representName = options['representName'] || null\n  this.defaultStyle = options['defaultStyle'] || null\n  this.multi = options['multi'] || false\n  this.styleAliases = compileStyleAliases(options['styleAliases'] || null)\n\n  if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {\n    throw new YAMLException('Unknown kind \"' + this.kind + '\" is specified for \"' + tag + '\" YAML type.')\n  }\n}\n\nmodule.exports = Type\n","'use strict'\n\nconst YAMLException = require('./exception')\nconst Type = require('./type')\n\nfunction compileList (schema, name) {\n  const result = []\n\n  schema[name].forEach(function (currentType) {\n    let newIndex = result.length\n\n    result.forEach(function (previousType, previousIndex) {\n      if (previousType.tag === currentType.tag &&\n          previousType.kind === currentType.kind &&\n          previousType.multi === currentType.multi) {\n        newIndex = previousIndex\n      }\n    })\n\n    result[newIndex] = currentType\n  })\n\n  return result\n}\n\nfunction compileMap (/* lists... */) {\n  const result = {\n    scalar: {},\n    sequence: {},\n    mapping: {},\n    fallback: {},\n    multi: {\n      scalar: [],\n      sequence: [],\n      mapping: [],\n      fallback: []\n    }\n  }\n  function collectType (type) {\n    if (type.multi) {\n      result.multi[type.kind].push(type)\n      result.multi['fallback'].push(type)\n    } else {\n      result[type.kind][type.tag] = result['fallback'][type.tag] = type\n    }\n  }\n\n  for (let index = 0, length = arguments.length; index < length; index += 1) {\n    arguments[index].forEach(collectType)\n  }\n  return result\n}\n\nfunction Schema (definition) {\n  return this.extend(definition)\n}\n\nSchema.prototype.extend = function extend (definition) {\n  let implicit = []\n  let explicit = []\n\n  if (definition instanceof Type) {\n    // Schema.extend(type)\n    explicit.push(definition)\n  } else if (Array.isArray(definition)) {\n    // Schema.extend([ type1, type2, ... ])\n    explicit = explicit.concat(definition)\n  } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {\n    // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] })\n    if (definition.implicit) implicit = implicit.concat(definition.implicit)\n    if (definition.explicit) explicit = explicit.concat(definition.explicit)\n  } else {\n    throw new YAMLException('Schema.extend argument should be a Type, [ Type ], ' +\n      'or a schema definition ({ implicit: [...], explicit: [...] })')\n  }\n\n  implicit.forEach(function (type) {\n    if (!(type instanceof Type)) {\n      throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')\n    }\n\n    if (type.loadKind && type.loadKind !== 'scalar') {\n      throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.')\n    }\n\n    if (type.multi) {\n      throw new YAMLException('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.')\n    }\n  })\n\n  explicit.forEach(function (type) {\n    if (!(type instanceof Type)) {\n      throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')\n    }\n  })\n\n  const result = Object.create(Schema.prototype)\n\n  result.implicit = (this.implicit || []).concat(implicit)\n  result.explicit = (this.explicit || []).concat(explicit)\n\n  result.compiledImplicit = compileList(result, 'implicit')\n  result.compiledExplicit = compileList(result, 'explicit')\n  result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit)\n\n  return result\n}\n\nmodule.exports = Schema\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:str', {\n  kind: 'scalar',\n  construct: function (data) { return data !== null ? data : '' }\n})\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:seq', {\n  kind: 'sequence',\n  construct: function (data) { return data !== null ? data : [] }\n})\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:map', {\n  kind: 'mapping',\n  construct: function (data) { return data !== null ? data : {} }\n})\n","// Standard YAML's Failsafe schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2802346\n\n'use strict'\n\nconst Schema = require('../schema')\n\nmodule.exports = new Schema({\n  explicit: [\n    require('../type/str'),\n    require('../type/seq'),\n    require('../type/map')\n  ]\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlNull (data) {\n  if (data === null) return true\n\n  const max = data.length\n\n  return (max === 1 && data === '~') ||\n         (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'))\n}\n\nfunction constructYamlNull () {\n  return null\n}\n\nfunction isNull (object) {\n  return object === null\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:null', {\n  kind: 'scalar',\n  resolve: resolveYamlNull,\n  construct: constructYamlNull,\n  predicate: isNull,\n  represent: {\n    canonical: function () { return '~' },\n    lowercase: function () { return 'null' },\n    uppercase: function () { return 'NULL' },\n    camelcase: function () { return 'Null' },\n    empty: function () { return '' }\n  },\n  defaultStyle: 'lowercase'\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlBoolean (data) {\n  if (data === null) return false\n\n  const max = data.length\n\n  return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||\n         (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'))\n}\n\nfunction constructYamlBoolean (data) {\n  return data === 'true' ||\n         data === 'True' ||\n         data === 'TRUE'\n}\n\nfunction isBoolean (object) {\n  return Object.prototype.toString.call(object) === '[object Boolean]'\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:bool', {\n  kind: 'scalar',\n  resolve: resolveYamlBoolean,\n  construct: constructYamlBoolean,\n  predicate: isBoolean,\n  represent: {\n    lowercase: function (object) { return object ? 'true' : 'false' },\n    uppercase: function (object) { return object ? 'TRUE' : 'FALSE' },\n    camelcase: function (object) { return object ? 'True' : 'False' }\n  },\n  defaultStyle: 'lowercase'\n})\n","'use strict'\n\nconst common = require('../common')\nconst Type = require('../type')\n\nfunction isHexCode (c) {\n  return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) ||\n         ((c >= 0x41/* A */) && (c <= 0x46/* F */)) ||\n         ((c >= 0x61/* a */) && (c <= 0x66/* f */))\n}\n\nfunction isOctCode (c) {\n  return ((c >= 0x30/* 0 */) && (c <= 0x37/* 7 */))\n}\n\nfunction isDecCode (c) {\n  return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */))\n}\n\nfunction resolveYamlInteger (data) {\n  if (data === null) return false\n\n  const max = data.length\n  let index = 0\n  let hasDigits = false\n\n  if (!max) return false\n\n  let ch = data[index]\n\n  // sign\n  if (ch === '-' || ch === '+') {\n    ch = data[++index]\n  }\n\n  if (ch === '0') {\n    // 0\n    if (index + 1 === max) return true\n    ch = data[++index]\n\n    // base 2, base 8, base 16\n\n    if (ch === 'b') {\n      // base 2\n      index++\n\n      for (; index < max; index++) {\n        ch = data[index]\n        if (ch !== '0' && ch !== '1') return false\n        hasDigits = true\n      }\n      return hasDigits && isFinite(parseYamlInteger(data))\n    }\n\n    if (ch === 'x') {\n      // base 16\n      index++\n\n      for (; index < max; index++) {\n        if (!isHexCode(data.charCodeAt(index))) return false\n        hasDigits = true\n      }\n      return hasDigits && isFinite(parseYamlInteger(data))\n    }\n\n    if (ch === 'o') {\n      // base 8\n      index++\n\n      for (; index < max; index++) {\n        if (!isOctCode(data.charCodeAt(index))) return false\n        hasDigits = true\n      }\n      return hasDigits && isFinite(parseYamlInteger(data))\n    }\n  }\n\n  // base 10 (except 0)\n\n  for (; index < max; index++) {\n    if (!isDecCode(data.charCodeAt(index))) {\n      return false\n    }\n    hasDigits = true\n  }\n\n  if (!hasDigits) return false\n\n  return isFinite(parseYamlInteger(data))\n}\n\nfunction parseYamlInteger (data) {\n  let value = data\n  let sign = 1\n\n  let ch = value[0]\n\n  if (ch === '-' || ch === '+') {\n    if (ch === '-') sign = -1\n    value = value.slice(1)\n    ch = value[0]\n  }\n\n  if (value === '0') return 0\n\n  if (ch === '0') {\n    if (value[1] === 'b') return sign * parseInt(value.slice(2), 2)\n    if (value[1] === 'x') return sign * parseInt(value.slice(2), 16)\n    if (value[1] === 'o') return sign * parseInt(value.slice(2), 8)\n  }\n\n  return sign * parseInt(value, 10)\n}\n\nfunction constructYamlInteger (data) {\n  return parseYamlInteger(data)\n}\n\nfunction isInteger (object) {\n  return (Object.prototype.toString.call(object)) === '[object Number]' &&\n         (object % 1 === 0 && !common.isNegativeZero(object))\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:int', {\n  kind: 'scalar',\n  resolve: resolveYamlInteger,\n  construct: constructYamlInteger,\n  predicate: isInteger,\n  represent: {\n    binary: function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1) },\n    octal: function (obj) { return obj >= 0 ? '0o' + obj.toString(8) : '-0o' + obj.toString(8).slice(1) },\n    decimal: function (obj) { return obj.toString(10) },\n    hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() : '-0x' + obj.toString(16).toUpperCase().slice(1) }\n  },\n  defaultStyle: 'decimal',\n  styleAliases: {\n    binary: [2, 'bin'],\n    octal: [8, 'oct'],\n    decimal: [10, 'dec'],\n    hexadecimal: [16, 'hex']\n  }\n})\n","'use strict'\n\nconst common = require('../common')\nconst Type = require('../type')\n\nconst YAML_FLOAT_PATTERN = new RegExp(\n  // 2.5e4, 2.5 and integers\n  '^(?:[-+]?(?:[0-9]+)(?:\\\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?' +\n  // .2e4, .2\n  // special case, seems not from spec\n  '|\\\\.[0-9]+(?:[eE][-+]?[0-9]+)?' +\n  // .inf\n  '|[-+]?\\\\.(?:inf|Inf|INF)' +\n  // .nan\n  '|\\\\.(?:nan|NaN|NAN))$')\n\nconst YAML_FLOAT_SPECIAL_PATTERN = new RegExp(\n  '^(?:' +\n  // .inf\n  '[-+]?\\\\.(?:inf|Inf|INF)' +\n  // .nan\n  '|\\\\.(?:nan|NaN|NAN))$')\n\nfunction resolveYamlFloat (data) {\n  if (data === null) return false\n\n  if (!YAML_FLOAT_PATTERN.test(data)) {\n    return false\n  }\n\n  if (isFinite(parseFloat(data, 10))) {\n    return true\n  }\n\n  return YAML_FLOAT_SPECIAL_PATTERN.test(data)\n}\n\nfunction constructYamlFloat (data) {\n  let value = data.toLowerCase()\n  const sign = value[0] === '-' ? -1 : 1\n\n  if ('+-'.indexOf(value[0]) >= 0) {\n    value = value.slice(1)\n  }\n\n  if (value === '.inf') {\n    return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY\n  } else if (value === '.nan') {\n    return NaN\n  }\n  return sign * parseFloat(value, 10)\n}\n\nconst SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/\n\nfunction representYamlFloat (object, style) {\n  if (isNaN(object)) {\n    switch (style) {\n      case 'lowercase': return '.nan'\n      case 'uppercase': return '.NAN'\n      case 'camelcase': return '.NaN'\n    }\n  } else if (Number.POSITIVE_INFINITY === object) {\n    switch (style) {\n      case 'lowercase': return '.inf'\n      case 'uppercase': return '.INF'\n      case 'camelcase': return '.Inf'\n    }\n  } else if (Number.NEGATIVE_INFINITY === object) {\n    switch (style) {\n      case 'lowercase': return '-.inf'\n      case 'uppercase': return '-.INF'\n      case 'camelcase': return '-.Inf'\n    }\n  } else if (common.isNegativeZero(object)) {\n    return '-0.0'\n  }\n\n  const res = object.toString(10)\n\n  // JS stringifier can build scientific format without dots: 5e-100,\n  // while YAML requres dot: 5.e-100. Fix it with simple hack\n\n  return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res\n}\n\nfunction isFloat (object) {\n  return (Object.prototype.toString.call(object) === '[object Number]') &&\n         (object % 1 !== 0 || common.isNegativeZero(object))\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:float', {\n  kind: 'scalar',\n  resolve: resolveYamlFloat,\n  construct: constructYamlFloat,\n  predicate: isFloat,\n  represent: representYamlFloat,\n  defaultStyle: 'lowercase'\n})\n","// Standard YAML's JSON schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2803231\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, this schema is not such strict as defined in the YAML specification.\n// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.\n\n'use strict'\n\nmodule.exports = require('./failsafe').extend({\n  implicit: [\n    require('../type/null'),\n    require('../type/bool'),\n    require('../type/int'),\n    require('../type/float')\n  ]\n})\n","// Standard YAML's Core schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2804923\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, Core schema has no distinctions from JSON schema is JS-YAML.\n\n'use strict'\n\nmodule.exports = require('./json')\n","'use strict'\n\nconst Type = require('../type')\n\nconst YAML_DATE_REGEXP = new RegExp(\n  '^([0-9][0-9][0-9][0-9])' + // [1] year\n  '-([0-9][0-9])' + // [2] month\n  '-([0-9][0-9])$')                   // [3] day\n\nconst YAML_TIMESTAMP_REGEXP = new RegExp(\n  '^([0-9][0-9][0-9][0-9])' + // [1] year\n  '-([0-9][0-9]?)' + // [2] month\n  '-([0-9][0-9]?)' + // [3] day\n  '(?:[Tt]|[ \\\\t]+)' + // ...\n  '([0-9][0-9]?)' + // [4] hour\n  ':([0-9][0-9])' + // [5] minute\n  ':([0-9][0-9])' + // [6] second\n  '(?:\\\\.([0-9]*))?' + // [7] fraction\n  '(?:[ \\\\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tzHour\n  '(?::([0-9][0-9]))?))?$')           // [11] tzMinute\n\nfunction resolveYamlTimestamp (data) {\n  if (data === null) return false\n  if (YAML_DATE_REGEXP.exec(data) !== null) return true\n  if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true\n  return false\n}\n\nfunction constructYamlTimestamp (data) {\n  let fraction = 0\n  let delta = null\n\n  let match = YAML_DATE_REGEXP.exec(data)\n  if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data)\n\n  if (match === null) throw new Error('Date resolve error')\n\n  // match: [1] year [2] month [3] day\n\n  const year = +(match[1])\n  const month = +(match[2]) - 1 // JS month starts with 0\n  const day = +(match[3])\n\n  if (!match[4]) { // no hour\n    return new Date(Date.UTC(year, month, day))\n  }\n\n  // match: [4] hour [5] minute [6] second [7] fraction\n\n  const hour = +(match[4])\n  const minute = +(match[5])\n  const second = +(match[6])\n\n  if (match[7]) {\n    fraction = match[7].slice(0, 3)\n    while (fraction.length < 3) { // milli-seconds\n      fraction += '0'\n    }\n    fraction = +fraction\n  }\n\n  // match: [8] tz [9] tz_sign [10] tzHour [11] tzMinute\n\n  if (match[9]) {\n    const tzHour = +(match[10])\n    const tzMinute = +(match[11] || 0)\n    delta = (tzHour * 60 + tzMinute) * 60000 // delta in mili-seconds\n    if (match[9] === '-') delta = -delta\n  }\n\n  const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction))\n\n  if (delta) date.setTime(date.getTime() - delta)\n\n  return date\n}\n\nfunction representYamlTimestamp (object /*, style */) {\n  return object.toISOString()\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:timestamp', {\n  kind: 'scalar',\n  resolve: resolveYamlTimestamp,\n  construct: constructYamlTimestamp,\n  instanceOf: Date,\n  represent: representYamlTimestamp\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlMerge (data) {\n  return data === '<<' || data === null\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:merge', {\n  kind: 'scalar',\n  resolve: resolveYamlMerge\n})\n","'use strict'\n\nconst Type = require('../type')\n\n// [ 64, 65, 66 ] -> [ padding, CR, LF ]\nconst BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\\n\\r'\n\nfunction resolveYamlBinary (data) {\n  if (data === null) return false\n\n  let bitlen = 0\n  const max = data.length\n  const map = BASE64_MAP\n\n  // Convert one by one.\n  for (let idx = 0; idx < max; idx++) {\n    const code = map.indexOf(data.charAt(idx))\n\n    // Skip CR/LF\n    if (code > 64) continue\n\n    // Fail on illegal characters\n    if (code < 0) return false\n\n    bitlen += 6\n  }\n\n  // If there are any bits left, source was corrupted\n  return (bitlen % 8) === 0\n}\n\nfunction constructYamlBinary (data) {\n  const input = data.replace(/[\\r\\n=]/g, '') // remove CR/LF & padding to simplify scan\n  const max = input.length\n  const map = BASE64_MAP\n  let bits = 0\n  const result = []\n\n  // Collect by 6*4 bits (3 bytes)\n\n  for (let idx = 0; idx < max; idx++) {\n    if ((idx % 4 === 0) && idx) {\n      result.push((bits >> 16) & 0xFF)\n      result.push((bits >> 8) & 0xFF)\n      result.push(bits & 0xFF)\n    }\n\n    bits = (bits << 6) | map.indexOf(input.charAt(idx))\n  }\n\n  // Dump tail\n\n  const tailbits = (max % 4) * 6\n\n  if (tailbits === 0) {\n    result.push((bits >> 16) & 0xFF)\n    result.push((bits >> 8) & 0xFF)\n    result.push(bits & 0xFF)\n  } else if (tailbits === 18) {\n    result.push((bits >> 10) & 0xFF)\n    result.push((bits >> 2) & 0xFF)\n  } else if (tailbits === 12) {\n    result.push((bits >> 4) & 0xFF)\n  }\n\n  return new Uint8Array(result)\n}\n\nfunction representYamlBinary (object /*, style */) {\n  let result = ''\n  let bits = 0\n  const max = object.length\n  const map = BASE64_MAP\n\n  // Convert every three bytes to 4 ASCII characters.\n\n  for (let idx = 0; idx < max; idx++) {\n    if ((idx % 3 === 0) && idx) {\n      result += map[(bits >> 18) & 0x3F]\n      result += map[(bits >> 12) & 0x3F]\n      result += map[(bits >> 6) & 0x3F]\n      result += map[bits & 0x3F]\n    }\n\n    bits = (bits << 8) + object[idx]\n  }\n\n  // Dump tail\n\n  const tail = max % 3\n\n  if (tail === 0) {\n    result += map[(bits >> 18) & 0x3F]\n    result += map[(bits >> 12) & 0x3F]\n    result += map[(bits >> 6) & 0x3F]\n    result += map[bits & 0x3F]\n  } else if (tail === 2) {\n    result += map[(bits >> 10) & 0x3F]\n    result += map[(bits >> 4) & 0x3F]\n    result += map[(bits << 2) & 0x3F]\n    result += map[64]\n  } else if (tail === 1) {\n    result += map[(bits >> 2) & 0x3F]\n    result += map[(bits << 4) & 0x3F]\n    result += map[64]\n    result += map[64]\n  }\n\n  return result\n}\n\nfunction isBinary (obj) {\n  return Object.prototype.toString.call(obj) === '[object Uint8Array]'\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:binary', {\n  kind: 'scalar',\n  resolve: resolveYamlBinary,\n  construct: constructYamlBinary,\n  predicate: isBinary,\n  represent: representYamlBinary\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\nconst _toString = Object.prototype.toString\n\nfunction resolveYamlOmap (data) {\n  if (data === null) return true\n\n  const objectKeys = {}\n  const object = data\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    const pair = object[index]\n    let pairHasKey = false\n\n    if (_toString.call(pair) !== '[object Object]') return false\n\n    let pairKey\n    for (pairKey in pair) {\n      if (_hasOwnProperty.call(pair, pairKey)) {\n        if (!pairHasKey) pairHasKey = true\n        else return false\n      }\n    }\n\n    if (!pairHasKey) return false\n\n    if (_hasOwnProperty.call(objectKeys, pairKey)) return false\n    Object.defineProperty(objectKeys, pairKey, { value: true })\n  }\n\n  return true\n}\n\nfunction constructYamlOmap (data) {\n  return data !== null ? data : []\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:omap', {\n  kind: 'sequence',\n  resolve: resolveYamlOmap,\n  construct: constructYamlOmap\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _toString = Object.prototype.toString\n\nfunction resolveYamlPairs (data) {\n  if (data === null) return true\n\n  const object = data\n\n  const result = new Array(object.length)\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    const pair = object[index]\n\n    if (_toString.call(pair) !== '[object Object]') return false\n\n    const keys = Object.keys(pair)\n\n    if (keys.length !== 1) return false\n\n    result[index] = [keys[0], pair[keys[0]]]\n  }\n\n  return true\n}\n\nfunction constructYamlPairs (data) {\n  if (data === null) return []\n\n  const object = data\n  const result = new Array(object.length)\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    const pair = object[index]\n\n    const keys = Object.keys(pair)\n\n    result[index] = [keys[0], pair[keys[0]]]\n  }\n\n  return result\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:pairs', {\n  kind: 'sequence',\n  resolve: resolveYamlPairs,\n  construct: constructYamlPairs\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nfunction resolveYamlSet (data) {\n  if (data === null) return true\n\n  const object = data\n\n  for (const key in object) {\n    if (_hasOwnProperty.call(object, key)) {\n      if (object[key] !== null) return false\n    }\n  }\n\n  return true\n}\n\nfunction constructYamlSet (data) {\n  return data !== null ? data : {}\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:set', {\n  kind: 'mapping',\n  resolve: resolveYamlSet,\n  construct: constructYamlSet\n})\n","// JS-YAML's default schema for `safeLoad` function.\n// It is not described in the YAML specification.\n//\n// This schema is based on standard YAML's Core schema and includes most of\n// extra types described at YAML tag repository. (http://yaml.org/type/)\n\n'use strict'\n\nmodule.exports = require('./core').extend({\n  implicit: [\n    require('../type/timestamp'),\n    require('../type/merge')\n  ],\n  explicit: [\n    require('../type/binary'),\n    require('../type/omap'),\n    require('../type/pairs'),\n    require('../type/set')\n  ]\n})\n","'use strict'\n\nconst common = require('./common')\nconst YAMLException = require('./exception')\nconst makeSnippet = require('./snippet')\nconst DEFAULT_SCHEMA = require('./schema/default')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nconst CONTEXT_FLOW_IN = 1\nconst CONTEXT_FLOW_OUT = 2\nconst CONTEXT_BLOCK_IN = 3\nconst CONTEXT_BLOCK_OUT = 4\n\nconst CHOMPING_CLIP = 1\nconst CHOMPING_STRIP = 2\nconst CHOMPING_KEEP = 3\n\n// eslint-disable-next-line no-control-regex\nconst PATTERN_NON_PRINTABLE = /[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x84\\x86-\\x9F\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/\nconst PATTERN_NON_ASCII_LINE_BREAKS = /[\\x85\\u2028\\u2029]/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_FLOW_INDICATORS = /[,\\[\\]{}]/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_TAG_URI = /^(?:!|[^,\\[\\]{}])(?:%[0-9a-f]{2}|[0-9a-z\\-#;/?:@&=+$,_.!~*'()\\[\\]])*$/i\n\nfunction _class (obj) { return Object.prototype.toString.call(obj) }\n\nfunction isEol (c) {\n  return (c === 0x0A/* LF */) || (c === 0x0D/* CR */)\n}\n\nfunction isWhiteSpace (c) {\n  return (c === 0x09/* Tab */) || (c === 0x20/* Space */)\n}\n\nfunction isWsOrEol (c) {\n  return (c === 0x09/* Tab */) ||\n         (c === 0x20/* Space */) ||\n         (c === 0x0A/* LF */) ||\n         (c === 0x0D/* CR */)\n}\n\nfunction isFlowIndicator (c) {\n  return c === 0x2C/* , */ ||\n         c === 0x5B/* [ */ ||\n         c === 0x5D/* ] */ ||\n         c === 0x7B/* { */ ||\n         c === 0x7D/* } */\n}\n\nfunction fromHexCode (c) {\n  if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {\n    return c - 0x30\n  }\n\n  const lc = c | 0x20\n\n  if ((lc >= 0x61/* a */) && (lc <= 0x66/* f */)) {\n    return lc - 0x61 + 10\n  }\n\n  return -1\n}\n\nfunction escapedHexLen (c) {\n  if (c === 0x78/* x */) { return 2 }\n  if (c === 0x75/* u */) { return 4 }\n  if (c === 0x55/* U */) { return 8 }\n  return 0\n}\n\nfunction fromDecimalCode (c) {\n  if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {\n    return c - 0x30\n  }\n\n  return -1\n}\n\nfunction simpleEscapeSequence (c) {\n  switch (c) {\n    case 0x30/* 0 */: return '\\x00'\n    case 0x61/* a */: return '\\x07'\n    case 0x62/* b */: return '\\x08'\n    case 0x74/* t */: return '\\x09'\n    case 0x09/* Tab */: return '\\x09'\n    case 0x6E/* n */: return '\\x0A'\n    case 0x76/* v */: return '\\x0B'\n    case 0x66/* f */: return '\\x0C'\n    case 0x72/* r */: return '\\x0D'\n    case 0x65/* e */: return '\\x1B'\n    case 0x20/* Space */: return ' '\n    case 0x22/* \" */: return '\\x22'\n    case 0x2F/* / */: return '/'\n    case 0x5C/* \\ */: return '\\x5C'\n    case 0x4E/* N */: return '\\x85'\n    case 0x5F/* _ */: return '\\xA0'\n    case 0x4C/* L */: return '\\u2028'\n    case 0x50/* P */: return '\\u2029'\n    default: return ''\n  }\n}\n\nfunction charFromCodepoint (c) {\n  if (c <= 0xFFFF) {\n    return String.fromCharCode(c)\n  }\n  // Encode UTF-16 surrogate pair\n  // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF\n  return String.fromCharCode(\n    ((c - 0x010000) >> 10) + 0xD800,\n    ((c - 0x010000) & 0x03FF) + 0xDC00\n  )\n}\n\n// set a property of a literal object, while protecting against prototype pollution,\n// see https://github.com/nodeca/js-yaml/issues/164 for more details\nfunction setProperty (object, key, value) {\n  // used for this specific key only because Object.defineProperty is slow\n  if (key === '__proto__') {\n    Object.defineProperty(object, key, {\n      configurable: true,\n      enumerable: true,\n      writable: true,\n      value: value\n    })\n  } else {\n    object[key] = value\n  }\n}\n\nconst simpleEscapeCheck = new Array(256) // integer, for fast access\nconst simpleEscapeMap = new Array(256)\nfor (let i = 0; i < 256; i++) {\n  simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0\n  simpleEscapeMap[i] = simpleEscapeSequence(i)\n}\n\nfunction State (input, options) {\n  this.input = input\n\n  this.filename = options['filename'] || null\n  this.schema = options['schema'] || DEFAULT_SCHEMA\n  this.onWarning = options['onWarning'] || null\n  // (Hidden) Remove? makes the loader to expect YAML 1.1 documents\n  // if such documents have no explicit %YAML directive\n  this.legacy = options['legacy'] || false\n\n  this.json = options['json'] || false\n  this.listener = options['listener'] || null\n  this.maxDepth = typeof options['maxDepth'] === 'number' ? options['maxDepth'] : 100\n  this.maxTotalMergeKeys = typeof options['maxTotalMergeKeys'] === 'number' ? options['maxTotalMergeKeys'] : 10000\n\n  this.implicitTypes = this.schema.compiledImplicit\n  this.typeMap = this.schema.compiledTypeMap\n\n  this.length = input.length\n  this.position = 0\n  this.line = 0\n  this.lineStart = 0\n  this.lineIndent = 0\n  this.depth = 0\n  this.totalMergeKeys = 0\n\n  // position of first leading tab in the current line,\n  // used to make sure there are no tabs in the indentation\n  this.firstTabInLine = -1\n\n  this.documents = []\n  this.anchorMapTransactions = []\n\n  /*\n  this.version;\n  this.checkLineBreaks;\n  this.tagMap;\n  this.anchorMap;\n  this.tag;\n  this.anchor;\n  this.kind;\n  this.result; */\n}\n\nfunction generateError (state, message) {\n  const mark = {\n    name: state.filename,\n    buffer: state.input.slice(0, -1), // omit trailing \\0\n    position: state.position,\n    line: state.line,\n    column: state.position - state.lineStart\n  }\n\n  mark.snippet = makeSnippet(mark)\n\n  return new YAMLException(message, mark)\n}\n\nfunction throwError (state, message) {\n  throw generateError(state, message)\n}\n\nfunction throwWarning (state, message) {\n  if (state.onWarning) {\n    state.onWarning.call(null, generateError(state, message))\n  }\n}\n\nfunction storeAnchor (state, name, value) {\n  const transactions = state.anchorMapTransactions\n\n  if (transactions.length !== 0) {\n    const transaction = transactions[transactions.length - 1]\n\n    if (!_hasOwnProperty.call(transaction, name)) {\n      transaction[name] = {\n        existed: _hasOwnProperty.call(state.anchorMap, name),\n        value: state.anchorMap[name]\n      }\n    }\n  }\n\n  state.anchorMap[name] = value\n}\n\nfunction beginAnchorTransaction (state) {\n  state.anchorMapTransactions.push(Object.create(null))\n}\n\nfunction commitAnchorTransaction (state) {\n  const transaction = state.anchorMapTransactions.pop()\n  const transactions = state.anchorMapTransactions\n\n  if (transactions.length === 0) return\n\n  const parent = transactions[transactions.length - 1]\n  const names = Object.keys(transaction)\n\n  for (let index = 0, length = names.length; index < length; index += 1) {\n    const name = names[index]\n\n    if (!_hasOwnProperty.call(parent, name)) {\n      parent[name] = transaction[name]\n    }\n  }\n}\n\nfunction rollbackAnchorTransaction (state) {\n  const transaction = state.anchorMapTransactions.pop()\n  const names = Object.keys(transaction)\n\n  for (let index = names.length - 1; index >= 0; index -= 1) {\n    const entry = transaction[names[index]]\n\n    if (entry.existed) {\n      state.anchorMap[names[index]] = entry.value\n    } else {\n      delete state.anchorMap[names[index]]\n    }\n  }\n}\n\nfunction snapshotState (state) {\n  return {\n    position: state.position,\n    line: state.line,\n    lineStart: state.lineStart,\n    lineIndent: state.lineIndent,\n    firstTabInLine: state.firstTabInLine,\n    tag: state.tag,\n    anchor: state.anchor,\n    kind: state.kind,\n    result: state.result\n  }\n}\n\nfunction restoreState (state, snapshot) {\n  state.position = snapshot.position\n  state.line = snapshot.line\n  state.lineStart = snapshot.lineStart\n  state.lineIndent = snapshot.lineIndent\n  state.firstTabInLine = snapshot.firstTabInLine\n  state.tag = snapshot.tag\n  state.anchor = snapshot.anchor\n  state.kind = snapshot.kind\n  state.result = snapshot.result\n}\n\nconst directiveHandlers = {\n\n  YAML: function handleYamlDirective (state, name, args) {\n    if (state.version !== null) {\n      throwError(state, 'duplication of %YAML directive')\n    }\n\n    if (args.length !== 1) {\n      throwError(state, 'YAML directive accepts exactly one argument')\n    }\n\n    const match = /^([0-9]+)\\.([0-9]+)$/.exec(args[0])\n\n    if (match === null) {\n      throwError(state, 'ill-formed argument of the YAML directive')\n    }\n\n    const major = parseInt(match[1], 10)\n    const minor = parseInt(match[2], 10)\n\n    if (major !== 1) {\n      throwError(state, 'unacceptable YAML version of the document')\n    }\n\n    state.version = args[0]\n    state.checkLineBreaks = (minor < 2)\n\n    if (minor !== 1 && minor !== 2) {\n      throwWarning(state, 'unsupported YAML version of the document')\n    }\n  },\n\n  TAG: function handleTagDirective (state, name, args) {\n    let prefix\n\n    if (args.length !== 2) {\n      throwError(state, 'TAG directive accepts exactly two arguments')\n    }\n\n    const handle = args[0]\n    prefix = args[1]\n\n    if (!PATTERN_TAG_HANDLE.test(handle)) {\n      throwError(state, 'ill-formed tag handle (first argument) of the TAG directive')\n    }\n\n    if (_hasOwnProperty.call(state.tagMap, handle)) {\n      throwError(state, 'there is a previously declared suffix for \"' + handle + '\" tag handle')\n    }\n\n    if (!PATTERN_TAG_URI.test(prefix)) {\n      throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive')\n    }\n\n    try {\n      prefix = decodeURIComponent(prefix)\n    } catch (err) {\n      throwError(state, 'tag prefix is malformed: ' + prefix)\n    }\n\n    state.tagMap[handle] = prefix\n  }\n}\n\nfunction captureSegment (state, start, end, checkJson) {\n  if (start < end) {\n    const _result = state.input.slice(start, end)\n\n    if (checkJson) {\n      for (let _position = 0, _length = _result.length; _position < _length; _position += 1) {\n        const _character = _result.charCodeAt(_position)\n        if (!(_character === 0x09 ||\n              (_character >= 0x20 && _character <= 0x10FFFF))) {\n          throwError(state, 'expected valid JSON character')\n        }\n      }\n    } else if (PATTERN_NON_PRINTABLE.test(_result)) {\n      throwError(state, 'the stream contains non-printable characters')\n    }\n\n    state.result += _result\n  }\n}\n\nfunction mergeMappings (state, destination, source, overridableKeys) {\n  if (!common.isObject(source)) {\n    throwError(state, 'cannot merge mappings; the provided source object is unacceptable')\n  }\n\n  const sourceKeys = Object.keys(source)\n\n  for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {\n    const key = sourceKeys[index]\n\n    if (state.maxTotalMergeKeys !== -1 && ++state.totalMergeKeys > state.maxTotalMergeKeys) {\n      throwError(state, 'merge keys exceeded maxTotalMergeKeys (' + state.maxTotalMergeKeys + ')')\n    }\n\n    if (!_hasOwnProperty.call(destination, key)) {\n      setProperty(destination, key, source[key])\n      overridableKeys[key] = true\n    }\n  }\n}\n\nfunction storeMappingPair (state, _result, overridableKeys, keyTag, keyNode, valueNode,\n  startLine, startLineStart, startPos) {\n  // The output is a plain object here, so keys can only be strings.\n  // We need to convert keyNode to a string, but doing so can hang the process\n  // (deeply nested arrays that explode exponentially using aliases).\n  if (Array.isArray(keyNode)) {\n    keyNode = Array.prototype.slice.call(keyNode)\n\n    for (let index = 0, quantity = keyNode.length; index < quantity; index += 1) {\n      if (Array.isArray(keyNode[index])) {\n        throwError(state, 'nested arrays are not supported inside keys')\n      }\n\n      if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {\n        keyNode[index] = '[object Object]'\n      }\n    }\n  }\n\n  // Avoid code execution in load() via toString property\n  // (still use its own toString for arrays, timestamps,\n  // and whatever user schema extensions happen to have @@toStringTag)\n  if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {\n    keyNode = '[object Object]'\n  }\n\n  keyNode = String(keyNode)\n\n  if (_result === null) {\n    _result = {}\n  }\n\n  if (keyTag === 'tag:yaml.org,2002:merge') {\n    if (Array.isArray(valueNode)) {\n      for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {\n        mergeMappings(state, _result, valueNode[index], overridableKeys)\n      }\n    } else {\n      mergeMappings(state, _result, valueNode, overridableKeys)\n    }\n  } else {\n    if (!state.json &&\n        !_hasOwnProperty.call(overridableKeys, keyNode) &&\n        _hasOwnProperty.call(_result, keyNode)) {\n      state.line = startLine || state.line\n      state.lineStart = startLineStart || state.lineStart\n      state.position = startPos || state.position\n      throwError(state, 'duplicated mapping key')\n    }\n\n    setProperty(_result, keyNode, valueNode)\n    delete overridableKeys[keyNode]\n  }\n\n  return _result\n}\n\nfunction readLineBreak (state) {\n  const ch = state.input.charCodeAt(state.position)\n\n  if (ch === 0x0A/* LF */) {\n    state.position++\n  } else if (ch === 0x0D/* CR */) {\n    state.position++\n    if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {\n      state.position++\n    }\n  } else {\n    throwError(state, 'a line break is expected')\n  }\n\n  state.line += 1\n  state.lineStart = state.position\n  state.firstTabInLine = -1\n}\n\nfunction skipSeparationSpace (state, allowComments, checkIndent) {\n  let lineBreaks = 0\n  let ch = state.input.charCodeAt(state.position)\n\n  while (ch !== 0) {\n    while (isWhiteSpace(ch)) {\n      if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) {\n        state.firstTabInLine = state.position\n      }\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    if (allowComments && ch === 0x23/* # */) {\n      do {\n        ch = state.input.charCodeAt(++state.position)\n      } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0)\n    }\n\n    if (isEol(ch)) {\n      readLineBreak(state)\n\n      ch = state.input.charCodeAt(state.position)\n      lineBreaks++\n      state.lineIndent = 0\n\n      while (ch === 0x20/* Space */) {\n        state.lineIndent++\n        ch = state.input.charCodeAt(++state.position)\n      }\n    } else {\n      break\n    }\n  }\n\n  if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {\n    throwWarning(state, 'deficient indentation')\n  }\n\n  return lineBreaks\n}\n\nfunction testDocumentSeparator (state) {\n  let _position = state.position\n  let ch = state.input.charCodeAt(_position)\n\n  // Condition state.position === state.lineStart is tested\n  // in parent on each call, for efficiency. No needs to test here again.\n  if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&\n      ch === state.input.charCodeAt(_position + 1) &&\n      ch === state.input.charCodeAt(_position + 2)) {\n    _position += 3\n\n    ch = state.input.charCodeAt(_position)\n\n    if (ch === 0 || isWsOrEol(ch)) {\n      return true\n    }\n  }\n\n  return false\n}\n\nfunction writeFoldedLines (state, count) {\n  if (count === 1) {\n    state.result += ' '\n  } else if (count > 1) {\n    state.result += common.repeat('\\n', count - 1)\n  }\n}\n\nfunction readPlainScalar (state, nodeIndent, withinFlowCollection) {\n  let captureStart\n  let captureEnd\n  let hasPendingContent\n  let _line\n  let _lineStart\n  let _lineIndent\n  const _kind = state.kind\n  const _result = state.result\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (isWsOrEol(ch) ||\n      isFlowIndicator(ch) ||\n      ch === 0x23/* # */ ||\n      ch === 0x26/* & */ ||\n      ch === 0x2A/* * */ ||\n      ch === 0x21/* ! */ ||\n      ch === 0x7C/* | */ ||\n      ch === 0x3E/* > */ ||\n      ch === 0x27/* ' */ ||\n      ch === 0x22/* \" */ ||\n      ch === 0x25/* % */ ||\n      ch === 0x40/* @ */ ||\n      ch === 0x60/* ` */) {\n    return false\n  }\n\n  if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {\n    const following = state.input.charCodeAt(state.position + 1)\n\n    if (isWsOrEol(following) ||\n        (withinFlowCollection && isFlowIndicator(following))) {\n      return false\n    }\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n  captureStart = captureEnd = state.position\n  hasPendingContent = false\n\n  while (ch !== 0) {\n    if (ch === 0x3A/* : */) {\n      const following = state.input.charCodeAt(state.position + 1)\n\n      if (isWsOrEol(following) ||\n          (withinFlowCollection && isFlowIndicator(following))) {\n        break\n      }\n    } else if (ch === 0x23/* # */) {\n      const preceding = state.input.charCodeAt(state.position - 1)\n\n      if (isWsOrEol(preceding)) {\n        break\n      }\n    } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||\n               (withinFlowCollection && isFlowIndicator(ch))) {\n      break\n    } else if (isEol(ch)) {\n      _line = state.line\n      _lineStart = state.lineStart\n      _lineIndent = state.lineIndent\n      skipSeparationSpace(state, false, -1)\n\n      if (state.lineIndent >= nodeIndent) {\n        hasPendingContent = true\n        ch = state.input.charCodeAt(state.position)\n        continue\n      } else {\n        state.position = captureEnd\n        state.line = _line\n        state.lineStart = _lineStart\n        state.lineIndent = _lineIndent\n        break\n      }\n    }\n\n    if (hasPendingContent) {\n      captureSegment(state, captureStart, captureEnd, false)\n      writeFoldedLines(state, state.line - _line)\n      captureStart = captureEnd = state.position\n      hasPendingContent = false\n    }\n\n    if (!isWhiteSpace(ch)) {\n      captureEnd = state.position + 1\n    }\n\n    ch = state.input.charCodeAt(++state.position)\n  }\n\n  captureSegment(state, captureStart, captureEnd, false)\n\n  if (state.result) {\n    return true\n  }\n\n  state.kind = _kind\n  state.result = _result\n  return false\n}\n\nfunction readSingleQuotedScalar (state, nodeIndent) {\n  let captureStart\n  let captureEnd\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x27/* ' */) {\n    return false\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n  state.position++\n  captureStart = captureEnd = state.position\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    if (ch === 0x27/* ' */) {\n      captureSegment(state, captureStart, state.position, true)\n      ch = state.input.charCodeAt(++state.position)\n\n      if (ch === 0x27/* ' */) {\n        captureStart = state.position\n        state.position++\n        captureEnd = state.position\n      } else {\n        return true\n      }\n    } else if (isEol(ch)) {\n      captureSegment(state, captureStart, captureEnd, true)\n      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))\n      captureStart = captureEnd = state.position\n    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n      throwError(state, 'unexpected end of the document within a single quoted scalar')\n    } else {\n      state.position++\n      if (!isWhiteSpace(ch)) {\n        captureEnd = state.position\n      }\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a single quoted scalar')\n}\n\nfunction readDoubleQuotedScalar (state, nodeIndent) {\n  let captureStart\n  let captureEnd\n  let tmp\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x22/* \" */) {\n    return false\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n  state.position++\n  captureStart = captureEnd = state.position\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    if (ch === 0x22/* \" */) {\n      captureSegment(state, captureStart, state.position, true)\n      state.position++\n      return true\n    } else if (ch === 0x5C/* \\ */) {\n      captureSegment(state, captureStart, state.position, true)\n      ch = state.input.charCodeAt(++state.position)\n\n      if (isEol(ch)) {\n        skipSeparationSpace(state, false, nodeIndent)\n\n        // TODO: rework to inline fn with no type cast?\n      } else if (ch < 256 && simpleEscapeCheck[ch]) {\n        state.result += simpleEscapeMap[ch]\n        state.position++\n      } else if ((tmp = escapedHexLen(ch)) > 0) {\n        let hexLength = tmp\n        let hexResult = 0\n\n        for (; hexLength > 0; hexLength--) {\n          ch = state.input.charCodeAt(++state.position)\n\n          if ((tmp = fromHexCode(ch)) >= 0) {\n            hexResult = (hexResult << 4) + tmp\n          } else {\n            throwError(state, 'expected hexadecimal character')\n          }\n        }\n\n        state.result += charFromCodepoint(hexResult)\n\n        state.position++\n      } else {\n        throwError(state, 'unknown escape sequence')\n      }\n\n      captureStart = captureEnd = state.position\n    } else if (isEol(ch)) {\n      captureSegment(state, captureStart, captureEnd, true)\n      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))\n      captureStart = captureEnd = state.position\n    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n      throwError(state, 'unexpected end of the document within a double quoted scalar')\n    } else {\n      state.position++\n      if (!isWhiteSpace(ch)) {\n        captureEnd = state.position\n      }\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a double quoted scalar')\n}\n\nfunction readFlowCollection (state, nodeIndent) {\n  let readNext = true\n  let _line\n  let _lineStart\n  let _pos\n  const _tag = state.tag\n  let _result\n  const _anchor = state.anchor\n  let terminator\n  let isPair\n  let isExplicitPair\n  let isMapping\n  const overridableKeys = Object.create(null)\n  let keyNode\n  let keyTag\n  let valueNode\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch === 0x5B/* [ */) {\n    terminator = 0x5D/* ] */\n    isMapping = false\n    _result = []\n  } else if (ch === 0x7B/* { */) {\n    terminator = 0x7D/* } */\n    isMapping = true\n    _result = {}\n  } else {\n    return false\n  }\n\n  if (state.anchor !== null) {\n    storeAnchor(state, state.anchor, _result)\n  }\n\n  ch = state.input.charCodeAt(++state.position)\n\n  while (ch !== 0) {\n    skipSeparationSpace(state, true, nodeIndent)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if (ch === terminator) {\n      state.position++\n      state.tag = _tag\n      state.anchor = _anchor\n      state.kind = isMapping ? 'mapping' : 'sequence'\n      state.result = _result\n      return true\n    } else if (!readNext) {\n      throwError(state, 'missed comma between flow collection entries')\n    } else if (ch === 0x2C/* , */) {\n      // \"flow collection entries can never be completely empty\", as per YAML 1.2, section 7.4\n      throwError(state, \"expected the node content, but found ','\")\n    }\n\n    keyTag = keyNode = valueNode = null\n    isPair = isExplicitPair = false\n\n    if (ch === 0x3F/* ? */) {\n      const following = state.input.charCodeAt(state.position + 1)\n\n      if (isWsOrEol(following)) {\n        isPair = isExplicitPair = true\n        state.position++\n        skipSeparationSpace(state, true, nodeIndent)\n      }\n    }\n\n    _line = state.line // Save the current line.\n    _lineStart = state.lineStart\n    _pos = state.position\n    composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)\n    keyTag = state.tag\n    keyNode = state.result\n    skipSeparationSpace(state, true, nodeIndent)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {\n      isPair = true\n      ch = state.input.charCodeAt(++state.position)\n      skipSeparationSpace(state, true, nodeIndent)\n      composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)\n      valueNode = state.result\n    }\n\n    if (isMapping) {\n      storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)\n    } else if (isPair) {\n      _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos))\n    } else {\n      _result.push(keyNode)\n    }\n\n    skipSeparationSpace(state, true, nodeIndent)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if (ch === 0x2C/* , */) {\n      readNext = true\n      ch = state.input.charCodeAt(++state.position)\n    } else {\n      readNext = false\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a flow collection')\n}\n\nfunction readBlockScalar (state, nodeIndent) {\n  let folding\n  let chomping = CHOMPING_CLIP\n  let didReadContent = false\n  let detectedIndent = false\n  let textIndent = nodeIndent\n  let emptyLines = 0\n  let atMoreIndented = false\n  let tmp\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch === 0x7C/* | */) {\n    folding = false\n  } else if (ch === 0x3E/* > */) {\n    folding = true\n  } else {\n    return false\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n\n  while (ch !== 0) {\n    ch = state.input.charCodeAt(++state.position)\n\n    if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {\n      if (CHOMPING_CLIP === chomping) {\n        chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP\n      } else {\n        throwError(state, 'repeat of a chomping mode identifier')\n      }\n    } else if ((tmp = fromDecimalCode(ch)) >= 0) {\n      if (tmp === 0) {\n        throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one')\n      } else if (!detectedIndent) {\n        textIndent = nodeIndent + tmp - 1\n        detectedIndent = true\n      } else {\n        throwError(state, 'repeat of an indentation width identifier')\n      }\n    } else {\n      break\n    }\n  }\n\n  if (isWhiteSpace(ch)) {\n    do { ch = state.input.charCodeAt(++state.position) }\n    while (isWhiteSpace(ch))\n\n    if (ch === 0x23/* # */) {\n      do { ch = state.input.charCodeAt(++state.position) }\n      while (!isEol(ch) && (ch !== 0))\n    }\n  }\n\n  while (ch !== 0) {\n    readLineBreak(state)\n    state.lineIndent = 0\n\n    ch = state.input.charCodeAt(state.position)\n\n    // eslint-disable-next-line no-unmodified-loop-condition\n    while ((!detectedIndent || state.lineIndent < textIndent) &&\n           (ch === 0x20/* Space */)) {\n      state.lineIndent++\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    if (!detectedIndent && state.lineIndent > textIndent) {\n      textIndent = state.lineIndent\n    }\n\n    if (isEol(ch)) {\n      emptyLines++\n      continue\n    }\n\n    if (!detectedIndent && textIndent === 0) {\n      throwError(state, 'missing indentation for block scalar')\n    }\n\n    // End of the scalar.\n    if (state.lineIndent < textIndent) {\n      // Perform the chomping.\n      if (chomping === CHOMPING_KEEP) {\n        state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n      } else if (chomping === CHOMPING_CLIP) {\n        if (didReadContent) { // i.e. only if the scalar is not empty.\n          state.result += '\\n'\n        }\n      }\n\n      // Break this `while` cycle and go to the funciton's epilogue.\n      break\n    }\n\n    // Folded style: use fancy rules to handle line breaks.\n    if (folding) {\n      // Lines starting with white space characters (more-indented lines) are not folded.\n      if (isWhiteSpace(ch)) {\n        atMoreIndented = true\n        // except for the first content line (cf. Example 8.1)\n        state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n\n      // End of more-indented block.\n      } else if (atMoreIndented) {\n        atMoreIndented = false\n        state.result += common.repeat('\\n', emptyLines + 1)\n\n      // Just one line break - perceive as the same line.\n      } else if (emptyLines === 0) {\n        if (didReadContent) { // i.e. only if we have already read some scalar content.\n          state.result += ' '\n        }\n\n      // Several line breaks - perceive as different lines.\n      } else {\n        state.result += common.repeat('\\n', emptyLines)\n      }\n\n    // Literal style: just add exact number of line breaks between content lines.\n    } else {\n      // Keep all line breaks except the header line break.\n      state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n    }\n\n    didReadContent = true\n    detectedIndent = true\n    emptyLines = 0\n    const captureStart = state.position\n\n    while (!isEol(ch) && (ch !== 0)) {\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    captureSegment(state, captureStart, state.position, false)\n  }\n\n  return true\n}\n\nfunction readBlockSequence (state, nodeIndent) {\n  const _tag = state.tag\n  const _anchor = state.anchor\n  const _result = []\n  let detected = false\n\n  // there is a leading tab before this token, so it can't be a block sequence/mapping;\n  // it can still be flow sequence/mapping or a scalar\n  if (state.firstTabInLine !== -1) return false\n\n  if (state.anchor !== null) {\n    storeAnchor(state, state.anchor, _result)\n  }\n\n  let ch = state.input.charCodeAt(state.position)\n\n  while (ch !== 0) {\n    if (state.firstTabInLine !== -1) {\n      state.position = state.firstTabInLine\n      throwError(state, 'tab characters must not be used in indentation')\n    }\n\n    if (ch !== 0x2D/* - */) {\n      break\n    }\n\n    const following = state.input.charCodeAt(state.position + 1)\n\n    if (!isWsOrEol(following)) {\n      break\n    }\n\n    detected = true\n    state.position++\n\n    if (skipSeparationSpace(state, true, -1)) {\n      if (state.lineIndent <= nodeIndent) {\n        _result.push(null)\n        ch = state.input.charCodeAt(state.position)\n        continue\n      }\n    }\n\n    const _line = state.line\n    composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true)\n    _result.push(state.result)\n    skipSeparationSpace(state, true, -1)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n      throwError(state, 'bad indentation of a sequence entry')\n    } else if (state.lineIndent < nodeIndent) {\n      break\n    }\n  }\n\n  if (detected) {\n    state.tag = _tag\n    state.anchor = _anchor\n    state.kind = 'sequence'\n    state.result = _result\n    return true\n  }\n  return false\n}\n\nfunction readBlockMapping (state, nodeIndent, flowIndent) {\n  let allowCompact\n  let _keyLine\n  let _keyLineStart\n  let _keyPos\n  const _tag = state.tag\n  const _anchor = state.anchor\n  const _result = {}\n  const overridableKeys = Object.create(null)\n  let keyTag = null\n  let keyNode = null\n  let valueNode = null\n  let atExplicitKey = false\n  let detected = false\n\n  // there is a leading tab before this token, so it can't be a block sequence/mapping;\n  // it can still be flow sequence/mapping or a scalar\n  if (state.firstTabInLine !== -1) return false\n\n  if (state.anchor !== null) {\n    storeAnchor(state, state.anchor, _result)\n  }\n\n  let ch = state.input.charCodeAt(state.position)\n\n  while (ch !== 0) {\n    if (!atExplicitKey && state.firstTabInLine !== -1) {\n      state.position = state.firstTabInLine\n      throwError(state, 'tab characters must not be used in indentation')\n    }\n\n    const following = state.input.charCodeAt(state.position + 1)\n    const _line = state.line // Save the current line.\n\n    //\n    // Explicit notation case. There are two separate blocks:\n    // first for the key (denoted by \"?\") and second for the value (denoted by \":\")\n    //\n    if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && isWsOrEol(following)) {\n      if (ch === 0x3F/* ? */) {\n        if (atExplicitKey) {\n          storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n          keyTag = keyNode = valueNode = null\n        }\n\n        detected = true\n        atExplicitKey = true\n        allowCompact = true\n      } else if (atExplicitKey) {\n        // i.e. 0x3A/* : */ === character after the explicit key.\n        atExplicitKey = false\n        allowCompact = true\n      } else {\n        throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line')\n      }\n\n      state.position += 1\n      ch = following\n\n    //\n    // Implicit notation case. Flow-style node as the key first, then \":\", and the value.\n    //\n    } else {\n      _keyLine = state.line\n      _keyLineStart = state.lineStart\n      _keyPos = state.position\n\n      if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {\n        // Neither implicit nor explicit notation.\n        // Reading is done. Go to the epilogue.\n        break\n      }\n\n      if (state.line === _line) {\n        ch = state.input.charCodeAt(state.position)\n\n        while (isWhiteSpace(ch)) {\n          ch = state.input.charCodeAt(++state.position)\n        }\n\n        if (ch === 0x3A/* : */) {\n          ch = state.input.charCodeAt(++state.position)\n\n          if (!isWsOrEol(ch)) {\n            throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping')\n          }\n\n          if (atExplicitKey) {\n            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n            keyTag = keyNode = valueNode = null\n          }\n\n          detected = true\n          atExplicitKey = false\n          allowCompact = false\n          keyTag = state.tag\n          keyNode = state.result\n        } else if (detected) {\n          throwError(state, 'can not read an implicit mapping pair; a colon is missed')\n        } else {\n          state.tag = _tag\n          state.anchor = _anchor\n          return true // Keep the result of `composeNode`.\n        }\n      } else if (detected) {\n        throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key')\n      } else {\n        state.tag = _tag\n        state.anchor = _anchor\n        return true // Keep the result of `composeNode`.\n      }\n    }\n\n    //\n    // Common reading code for both explicit and implicit notations.\n    //\n    if (state.line === _line || state.lineIndent > nodeIndent) {\n      if (atExplicitKey) {\n        _keyLine = state.line\n        _keyLineStart = state.lineStart\n        _keyPos = state.position\n      }\n\n      if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {\n        if (atExplicitKey) {\n          keyNode = state.result\n        } else {\n          valueNode = state.result\n        }\n      }\n\n      if (!atExplicitKey) {\n        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos)\n        keyTag = keyNode = valueNode = null\n      }\n\n      skipSeparationSpace(state, true, -1)\n      ch = state.input.charCodeAt(state.position)\n    }\n\n    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n      throwError(state, 'bad indentation of a mapping entry')\n    } else if (state.lineIndent < nodeIndent) {\n      break\n    }\n  }\n\n  //\n  // Epilogue.\n  //\n\n  // Special case: last mapping's node contains only the key in explicit notation.\n  if (atExplicitKey) {\n    storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n  }\n\n  // Expose the resulting mapping.\n  if (detected) {\n    state.tag = _tag\n    state.anchor = _anchor\n    state.kind = 'mapping'\n    state.result = _result\n  }\n\n  return detected\n}\n\nfunction readTagProperty (state) {\n  let isVerbatim = false\n  let isNamed = false\n  let tagHandle\n  let tagName\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x21/* ! */) return false\n\n  if (state.tag !== null) {\n    throwError(state, 'duplication of a tag property')\n  }\n\n  ch = state.input.charCodeAt(++state.position)\n\n  if (ch === 0x3C/* < */) {\n    isVerbatim = true\n    ch = state.input.charCodeAt(++state.position)\n  } else if (ch === 0x21/* ! */) {\n    isNamed = true\n    tagHandle = '!!'\n    ch = state.input.charCodeAt(++state.position)\n  } else {\n    tagHandle = '!'\n  }\n\n  let _position = state.position\n\n  if (isVerbatim) {\n    do { ch = state.input.charCodeAt(++state.position) }\n    while (ch !== 0 && ch !== 0x3E/* > */)\n\n    if (state.position < state.length) {\n      tagName = state.input.slice(_position, state.position)\n      ch = state.input.charCodeAt(++state.position)\n    } else {\n      throwError(state, 'unexpected end of the stream within a verbatim tag')\n    }\n  } else {\n    while (ch !== 0 && !isWsOrEol(ch)) {\n      if (ch === 0x21/* ! */) {\n        if (!isNamed) {\n          tagHandle = state.input.slice(_position - 1, state.position + 1)\n\n          if (!PATTERN_TAG_HANDLE.test(tagHandle)) {\n            throwError(state, 'named tag handle cannot contain such characters')\n          }\n\n          isNamed = true\n          _position = state.position + 1\n        } else {\n          throwError(state, 'tag suffix cannot contain exclamation marks')\n        }\n      }\n\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    tagName = state.input.slice(_position, state.position)\n\n    if (PATTERN_FLOW_INDICATORS.test(tagName)) {\n      throwError(state, 'tag suffix cannot contain flow indicator characters')\n    }\n  }\n\n  if (tagName && !PATTERN_TAG_URI.test(tagName)) {\n    throwError(state, 'tag name cannot contain such characters: ' + tagName)\n  }\n\n  try {\n    tagName = decodeURIComponent(tagName)\n  } catch (err) {\n    throwError(state, 'tag name is malformed: ' + tagName)\n  }\n\n  if (isVerbatim) {\n    state.tag = tagName\n  } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {\n    state.tag = state.tagMap[tagHandle] + tagName\n  } else if (tagHandle === '!') {\n    state.tag = '!' + tagName\n  } else if (tagHandle === '!!') {\n    state.tag = 'tag:yaml.org,2002:' + tagName\n  } else {\n    throwError(state, 'undeclared tag handle \"' + tagHandle + '\"')\n  }\n\n  return true\n}\n\nfunction readAnchorProperty (state) {\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x26/* & */) return false\n\n  if (state.anchor !== null) {\n    throwError(state, 'duplication of an anchor property')\n  }\n\n  ch = state.input.charCodeAt(++state.position)\n  const _position = state.position\n\n  while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {\n    ch = state.input.charCodeAt(++state.position)\n  }\n\n  if (state.position === _position) {\n    throwError(state, 'name of an anchor node must contain at least one character')\n  }\n\n  state.anchor = state.input.slice(_position, state.position)\n  return true\n}\n\nfunction readAlias (state) {\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x2A/* * */) return false\n\n  ch = state.input.charCodeAt(++state.position)\n  const _position = state.position\n\n  while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {\n    ch = state.input.charCodeAt(++state.position)\n  }\n\n  if (state.position === _position) {\n    throwError(state, 'name of an alias node must contain at least one character')\n  }\n\n  const alias = state.input.slice(_position, state.position)\n\n  if (!_hasOwnProperty.call(state.anchorMap, alias)) {\n    throwError(state, 'unidentified alias \"' + alias + '\"')\n  }\n\n  state.result = state.anchorMap[alias]\n  skipSeparationSpace(state, true, -1)\n  return true\n}\n\nfunction tryReadBlockMappingFromProperty (state, propertyStart, nodeIndent, flowIndent) {\n  const fallbackState = snapshotState(state)\n\n  beginAnchorTransaction(state)\n  restoreState(state, propertyStart)\n\n  // Re-read the leading properties as part of the first implicit key, not as\n  // properties of the current node.\n  state.tag = null\n  state.anchor = null\n  state.kind = null\n  state.result = null\n\n  if (readBlockMapping(state, nodeIndent, flowIndent) && state.kind === 'mapping') {\n    commitAnchorTransaction(state)\n    return true\n  }\n\n  rollbackAnchorTransaction(state)\n  restoreState(state, fallbackState)\n  return false\n}\n\nfunction composeNode (state, parentIndent, nodeContext, allowToSeek, allowCompact) {\n  let allowBlockScalars\n  let allowBlockCollections\n  let indentStatus = 1 // 1: this>parent, 0: this=parent, -1: this<parent\n  let atNewLine = false\n  let hasContent = false\n  let propertyStart = null\n  let type\n  let flowIndent\n  let blockIndent\n\n  if (state.depth >= state.maxDepth) {\n    throwError(state, 'nesting exceeded maxDepth (' + state.maxDepth + ')')\n  }\n\n  state.depth += 1\n\n  if (state.listener !== null) {\n    state.listener('open', state)\n  }\n\n  state.tag = null\n  state.anchor = null\n  state.kind = null\n  state.result = null\n\n  const allowBlockStyles = allowBlockScalars = allowBlockCollections =\n    CONTEXT_BLOCK_OUT === nodeContext ||\n    CONTEXT_BLOCK_IN === nodeContext\n\n  if (allowToSeek) {\n    if (skipSeparationSpace(state, true, -1)) {\n      atNewLine = true\n\n      if (state.lineIndent > parentIndent) {\n        indentStatus = 1\n      } else if (state.lineIndent === parentIndent) {\n        indentStatus = 0\n      } else if (state.lineIndent < parentIndent) {\n        indentStatus = -1\n      }\n    }\n  }\n\n  if (indentStatus === 1) {\n    while (true) {\n      const ch = state.input.charCodeAt(state.position)\n      const propertyState = snapshotState(state)\n\n      // A duplicate property token after a line break can be the first key of\n      // a nested block mapping, e.g. `!!map\\n  !!str key: value`.\n      if (atNewLine &&\n          ((ch === 0x21/* ! */ && state.tag !== null) ||\n           (ch === 0x26/* & */ && state.anchor !== null))) {\n        break\n      }\n\n      if (!readTagProperty(state) && !readAnchorProperty(state)) {\n        break\n      }\n\n      if (propertyStart === null) {\n        propertyStart = propertyState\n      }\n\n      if (skipSeparationSpace(state, true, -1)) {\n        atNewLine = true\n        allowBlockCollections = allowBlockStyles\n\n        if (state.lineIndent > parentIndent) {\n          indentStatus = 1\n        } else if (state.lineIndent === parentIndent) {\n          indentStatus = 0\n        } else if (state.lineIndent < parentIndent) {\n          indentStatus = -1\n        }\n      } else {\n        allowBlockCollections = false\n      }\n    }\n  }\n\n  if (allowBlockCollections) {\n    allowBlockCollections = atNewLine || allowCompact\n  }\n\n  if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {\n    if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {\n      flowIndent = parentIndent\n    } else {\n      flowIndent = parentIndent + 1\n    }\n\n    blockIndent = state.position - state.lineStart\n\n    if (indentStatus === 1) {\n      if ((allowBlockCollections &&\n          (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent))) ||\n          readFlowCollection(state, flowIndent)) {\n        hasContent = true\n      } else {\n        const ch = state.input.charCodeAt(state.position)\n\n        if (propertyStart !== null && allowBlockStyles && !allowBlockCollections &&\n            ch !== 0x7C/* | */ && ch !== 0x3E/* > */ &&\n            tryReadBlockMappingFromProperty(\n              state,\n              propertyStart,\n              propertyStart.position - propertyStart.lineStart,\n              flowIndent\n            )) {\n          hasContent = true\n        } else if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||\n            readSingleQuotedScalar(state, flowIndent) ||\n            readDoubleQuotedScalar(state, flowIndent)) {\n          hasContent = true\n        } else if (readAlias(state)) {\n          hasContent = true\n\n          if (state.tag !== null || state.anchor !== null) {\n            throwError(state, 'alias node should not have any properties')\n          }\n        } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {\n          hasContent = true\n\n          if (state.tag === null) {\n            state.tag = '?'\n          }\n        }\n\n        if (state.anchor !== null) {\n          storeAnchor(state, state.anchor, state.result)\n        }\n      }\n    } else if (indentStatus === 0) {\n      // Special case: block sequences are allowed to have same indentation level as the parent.\n      // http://www.yaml.org/spec/1.2/spec.html#id2799784\n      hasContent = allowBlockCollections && readBlockSequence(state, blockIndent)\n    }\n  }\n\n  if (state.tag === null) {\n    if (state.anchor !== null) {\n      storeAnchor(state, state.anchor, state.result)\n    }\n  } else if (state.tag === '?') {\n    // Implicit resolving is not allowed for non-scalar types, and '?'\n    // non-specific tag is only automatically assigned to plain scalars.\n    //\n    // We only need to check kind conformity in case user explicitly assigns '?'\n    // tag, for example like this: \"!<?> [0]\"\n    //\n    if (state.result !== null && state.kind !== 'scalar') {\n      throwError(state, 'unacceptable node kind for !<?> tag; it should be \"scalar\", not \"' + state.kind + '\"')\n    }\n\n    for (let typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {\n      type = state.implicitTypes[typeIndex]\n\n      if (type.resolve(state.result)) { // `state.result` updated in resolver if matched\n        state.result = type.construct(state.result)\n        state.tag = type.tag\n        if (state.anchor !== null) {\n          storeAnchor(state, state.anchor, state.result)\n        }\n        break\n      }\n    }\n  } else if (state.tag !== '!') {\n    if (_hasOwnProperty.call(state.typeMap[state.kind || 'fallback'], state.tag)) {\n      type = state.typeMap[state.kind || 'fallback'][state.tag]\n    } else {\n      // looking for multi type\n      type = null\n      const typeList = state.typeMap.multi[state.kind || 'fallback']\n\n      for (let typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {\n        if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {\n          type = typeList[typeIndex]\n          break\n        }\n      }\n    }\n\n    if (!type) {\n      throwError(state, 'unknown tag !<' + state.tag + '>')\n    }\n\n    if (state.result !== null && type.kind !== state.kind) {\n      throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be \"' + type.kind + '\", not \"' + state.kind + '\"')\n    }\n\n    if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched\n      throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag')\n    } else {\n      state.result = type.construct(state.result, state.tag)\n      if (state.anchor !== null) {\n        storeAnchor(state, state.anchor, state.result)\n      }\n    }\n  }\n\n  if (state.listener !== null) {\n    state.listener('close', state)\n  }\n\n  state.depth -= 1\n  return state.tag !== null || state.anchor !== null || hasContent\n}\n\nfunction readDocument (state) {\n  const documentStart = state.position\n  let hasDirectives = false\n  let ch\n\n  state.version = null\n  state.checkLineBreaks = state.legacy\n  state.tagMap = Object.create(null)\n  state.anchorMap = Object.create(null)\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    skipSeparationSpace(state, true, -1)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if (state.lineIndent > 0 || ch !== 0x25/* % */) {\n      break\n    }\n\n    hasDirectives = true\n    ch = state.input.charCodeAt(++state.position)\n    let _position = state.position\n\n    while (ch !== 0 && !isWsOrEol(ch)) {\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    const directiveName = state.input.slice(_position, state.position)\n    const directiveArgs = []\n\n    if (directiveName.length < 1) {\n      throwError(state, 'directive name must not be less than one character in length')\n    }\n\n    while (ch !== 0) {\n      while (isWhiteSpace(ch)) {\n        ch = state.input.charCodeAt(++state.position)\n      }\n\n      if (ch === 0x23/* # */) {\n        do { ch = state.input.charCodeAt(++state.position) }\n        while (ch !== 0 && !isEol(ch))\n        break\n      }\n\n      if (isEol(ch)) break\n\n      _position = state.position\n\n      while (ch !== 0 && !isWsOrEol(ch)) {\n        ch = state.input.charCodeAt(++state.position)\n      }\n\n      directiveArgs.push(state.input.slice(_position, state.position))\n    }\n\n    if (ch !== 0) readLineBreak(state)\n\n    if (_hasOwnProperty.call(directiveHandlers, directiveName)) {\n      directiveHandlers[directiveName](state, directiveName, directiveArgs)\n    } else {\n      throwWarning(state, 'unknown document directive \"' + directiveName + '\"')\n    }\n  }\n\n  skipSeparationSpace(state, true, -1)\n\n  if (state.lineIndent === 0 &&\n      state.input.charCodeAt(state.position) === 0x2D/* - */ &&\n      state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&\n      state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {\n    state.position += 3\n    skipSeparationSpace(state, true, -1)\n  } else if (hasDirectives) {\n    throwError(state, 'directives end mark is expected')\n  }\n\n  composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true)\n  skipSeparationSpace(state, true, -1)\n\n  if (state.checkLineBreaks &&\n      PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {\n    throwWarning(state, 'non-ASCII line breaks are interpreted as content')\n  }\n\n  state.documents.push(state.result)\n\n  if (state.position === state.lineStart && testDocumentSeparator(state)) {\n    if (state.input.charCodeAt(state.position) === 0x2E/* . */) {\n      state.position += 3\n      skipSeparationSpace(state, true, -1)\n    }\n    return\n  }\n\n  if (state.position < (state.length - 1)) {\n    throwError(state, 'end of the stream or a document separator is expected')\n  }\n}\n\nfunction loadDocuments (input, options) {\n  input = String(input)\n  options = options || {}\n\n  if (input.length !== 0) {\n    // Add tailing `\\n` if not exists\n    if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&\n        input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {\n      input += '\\n'\n    }\n\n    // Strip BOM\n    if (input.charCodeAt(0) === 0xFEFF) {\n      input = input.slice(1)\n    }\n  }\n\n  const state = new State(input, options)\n\n  const nullpos = input.indexOf('\\0')\n\n  if (nullpos !== -1) {\n    state.position = nullpos\n    throwError(state, 'null byte is not allowed in input')\n  }\n\n  // Use 0 as string terminator. That significantly simplifies bounds check.\n  state.input += '\\0'\n\n  while (state.input.charCodeAt(state.position) === 0x20/* Space */) {\n    state.lineIndent += 1\n    state.position += 1\n  }\n\n  while (state.position < (state.length - 1)) {\n    readDocument(state)\n  }\n\n  return state.documents\n}\n\nfunction loadAll (input, iterator, options) {\n  if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {\n    options = iterator\n    iterator = null\n  }\n\n  const documents = loadDocuments(input, options)\n\n  if (typeof iterator !== 'function') {\n    return documents\n  }\n\n  for (let index = 0, length = documents.length; index < length; index += 1) {\n    iterator(documents[index])\n  }\n}\n\nfunction load (input, options) {\n  const documents = loadDocuments(input, options)\n\n  if (documents.length === 0) {\n    return undefined\n  } else if (documents.length === 1) {\n    return documents[0]\n  }\n  throw new YAMLException('expected a single document in the stream, but found more')\n}\n\nmodule.exports.loadAll = loadAll\nmodule.exports.load = load\n","'use strict'\n\nconst common = require('./common')\n\n// get snippet for a single line, respecting maxLength\nfunction getLine (buffer, lineStart, lineEnd, position, maxLineLength) {\n  let head = ''\n  let tail = ''\n  const maxHalfLength = Math.floor(maxLineLength / 2) - 1\n\n  if (position - lineStart > maxHalfLength) {\n    head = ' ... '\n    lineStart = position - maxHalfLength + head.length\n  }\n\n  if (lineEnd - position > maxHalfLength) {\n    tail = ' ...'\n    lineEnd = position + maxHalfLength - tail.length\n  }\n\n  return {\n    str: head + buffer.slice(lineStart, lineEnd).replace(/\\t/g, '→') + tail,\n    pos: position - lineStart + head.length // relative position\n  }\n}\n\nfunction padStart (string, max) {\n  return common.repeat(' ', max - string.length) + string\n}\n\nfunction makeSnippet (mark, options) {\n  options = Object.create(options || null)\n\n  if (!mark.buffer) return null\n\n  if (!options.maxLength) options.maxLength = 79\n  if (typeof options.indent !== 'number') options.indent = 1\n  if (typeof options.linesBefore !== 'number') options.linesBefore = 3\n  if (typeof options.linesAfter !== 'number') options.linesAfter = 2\n\n  const re = /\\r?\\n|\\r|\\0/g\n  const lineStarts = [0]\n  const lineEnds = []\n  let match\n  let foundLineNo = -1\n\n  while ((match = re.exec(mark.buffer))) {\n    lineEnds.push(match.index)\n    lineStarts.push(match.index + match[0].length)\n\n    if (mark.position <= match.index && foundLineNo < 0) {\n      foundLineNo = lineStarts.length - 2\n    }\n  }\n\n  if (foundLineNo < 0) foundLineNo = lineStarts.length - 1\n\n  let result = ''\n  const lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length\n  const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3)\n\n  for (let i = 1; i <= options.linesBefore; i++) {\n    if (foundLineNo - i < 0) break\n    const line = getLine(\n      mark.buffer,\n      lineStarts[foundLineNo - i],\n      lineEnds[foundLineNo - i],\n      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),\n      maxLineLength\n    )\n    result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) +\n      ' | ' + line.str + '\\n' + result\n  }\n\n  const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength)\n  result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) +\n    ' | ' + line.str + '\\n'\n  result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\\n'\n\n  for (let i = 1; i <= options.linesAfter; i++) {\n    if (foundLineNo + i >= lineEnds.length) break\n    const line = getLine(\n      mark.buffer,\n      lineStarts[foundLineNo + i],\n      lineEnds[foundLineNo + i],\n      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),\n      maxLineLength\n    )\n    result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) +\n      ' | ' + line.str + '\\n'\n  }\n\n  return result.replace(/\\n$/, '')\n}\n\nmodule.exports = makeSnippet\n","'use strict'\n\nconst common = require('./common')\nconst YAMLException = require('./exception')\nconst DEFAULT_SCHEMA = require('./schema/default')\n\nconst _toString = Object.prototype.toString\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nconst CHAR_BOM = 0xFEFF\nconst CHAR_TAB = 0x09 /* Tab */\nconst CHAR_LINE_FEED = 0x0A /* LF */\nconst CHAR_CARRIAGE_RETURN = 0x0D /* CR */\nconst CHAR_SPACE = 0x20 /* Space */\nconst CHAR_EXCLAMATION = 0x21 /* ! */\nconst CHAR_DOUBLE_QUOTE = 0x22 /* \" */\nconst CHAR_SHARP = 0x23 /* # */\nconst CHAR_PERCENT = 0x25 /* % */\nconst CHAR_AMPERSAND = 0x26 /* & */\nconst CHAR_SINGLE_QUOTE = 0x27 /* ' */\nconst CHAR_ASTERISK = 0x2A /* * */\nconst CHAR_COMMA = 0x2C /* , */\nconst CHAR_MINUS = 0x2D /* - */\nconst CHAR_COLON = 0x3A /* : */\nconst CHAR_EQUALS = 0x3D /* = */\nconst CHAR_GREATER_THAN = 0x3E /* > */\nconst CHAR_QUESTION = 0x3F /* ? */\nconst CHAR_COMMERCIAL_AT = 0x40 /* @ */\nconst CHAR_LEFT_SQUARE_BRACKET = 0x5B /* [ */\nconst CHAR_RIGHT_SQUARE_BRACKET = 0x5D /* ] */\nconst CHAR_GRAVE_ACCENT = 0x60 /* ` */\nconst CHAR_LEFT_CURLY_BRACKET = 0x7B /* { */\nconst CHAR_VERTICAL_LINE = 0x7C /* | */\nconst CHAR_RIGHT_CURLY_BRACKET = 0x7D /* } */\n\nconst ESCAPE_SEQUENCES = {}\n\nESCAPE_SEQUENCES[0x00] = '\\\\0'\nESCAPE_SEQUENCES[0x07] = '\\\\a'\nESCAPE_SEQUENCES[0x08] = '\\\\b'\nESCAPE_SEQUENCES[0x09] = '\\\\t'\nESCAPE_SEQUENCES[0x0A] = '\\\\n'\nESCAPE_SEQUENCES[0x0B] = '\\\\v'\nESCAPE_SEQUENCES[0x0C] = '\\\\f'\nESCAPE_SEQUENCES[0x0D] = '\\\\r'\nESCAPE_SEQUENCES[0x1B] = '\\\\e'\nESCAPE_SEQUENCES[0x22] = '\\\\\"'\nESCAPE_SEQUENCES[0x5C] = '\\\\\\\\'\nESCAPE_SEQUENCES[0x85] = '\\\\N'\nESCAPE_SEQUENCES[0xA0] = '\\\\_'\nESCAPE_SEQUENCES[0x2028] = '\\\\L'\nESCAPE_SEQUENCES[0x2029] = '\\\\P'\n\nconst DEPRECATED_BOOLEANS_SYNTAX = [\n  'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',\n  'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'\n]\n\nconst DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\\.[0-9_]*)?$/\n\nfunction compileStyleMap (schema, map) {\n  if (map === null) return {}\n\n  const result = {}\n  const keys = Object.keys(map)\n\n  for (let index = 0, length = keys.length; index < length; index += 1) {\n    let tag = keys[index]\n    let style = String(map[tag])\n\n    if (tag.slice(0, 2) === '!!') {\n      tag = 'tag:yaml.org,2002:' + tag.slice(2)\n    }\n    const type = schema.compiledTypeMap['fallback'][tag]\n\n    if (type && _hasOwnProperty.call(type.styleAliases, style)) {\n      style = type.styleAliases[style]\n    }\n\n    result[tag] = style\n  }\n\n  return result\n}\n\nfunction encodeHex (character) {\n  let handle\n  let length\n\n  const string = character.toString(16).toUpperCase()\n\n  if (character <= 0xFF) {\n    handle = 'x'\n    length = 2\n  } else if (character <= 0xFFFF) {\n    handle = 'u'\n    length = 4\n  } else if (character <= 0xFFFFFFFF) {\n    handle = 'U'\n    length = 8\n  } else {\n    throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF')\n  }\n\n  return '\\\\' + handle + common.repeat('0', length - string.length) + string\n}\n\nconst QUOTING_TYPE_SINGLE = 1\nconst QUOTING_TYPE_DOUBLE = 2\n\nfunction State (options) {\n  this.schema = options['schema'] || DEFAULT_SCHEMA\n  this.indent = Math.max(1, (options['indent'] || 2))\n  this.noArrayIndent = options['noArrayIndent'] || false\n  this.skipInvalid = options['skipInvalid'] || false\n  this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel'])\n  this.styleMap = compileStyleMap(this.schema, options['styles'] || null)\n  this.sortKeys = options['sortKeys'] || false\n  this.lineWidth = options['lineWidth'] || 80\n  this.noRefs = options['noRefs'] || false\n  this.noCompatMode = options['noCompatMode'] || false\n  this.condenseFlow = options['condenseFlow'] || false\n  this.quotingType = options['quotingType'] === '\"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE\n  this.forceQuotes = options['forceQuotes'] || false\n  this.replacer = typeof options['replacer'] === 'function' ? options['replacer'] : null\n\n  this.implicitTypes = this.schema.compiledImplicit\n  this.explicitTypes = this.schema.compiledExplicit\n\n  this.tag = null\n  this.result = ''\n\n  this.duplicates = []\n  this.usedDuplicates = null\n}\n\n// Indents every line in a string. Empty lines (\\n only) are not indented.\nfunction indentString (string, spaces) {\n  const ind = common.repeat(' ', spaces)\n  let position = 0\n  let result = ''\n  const length = string.length\n\n  while (position < length) {\n    let line\n    const next = string.indexOf('\\n', position)\n    if (next === -1) {\n      line = string.slice(position)\n      position = length\n    } else {\n      line = string.slice(position, next + 1)\n      position = next + 1\n    }\n\n    if (line.length && line !== '\\n') result += ind\n\n    result += line\n  }\n\n  return result\n}\n\nfunction generateNextLine (state, level) {\n  return '\\n' + common.repeat(' ', state.indent * level)\n}\n\nfunction testImplicitResolving (state, str) {\n  for (let index = 0, length = state.implicitTypes.length; index < length; index += 1) {\n    const type = state.implicitTypes[index]\n\n    if (type.resolve(str)) {\n      return true\n    }\n  }\n\n  return false\n}\n\n// [33] s-white ::= s-space | s-tab\nfunction isWhitespace (c) {\n  return c === CHAR_SPACE || c === CHAR_TAB\n}\n\n// Returns true if the character can be printed without escaping.\n// From YAML 1.2: \"any allowed characters known to be non-printable\n// should also be escaped. [However,] This isn’t mandatory\"\n// Derived from nb-char - \\t - #x85 - #xA0 - #x2028 - #x2029.\nfunction isPrintable (c) {\n  return (c >= 0x00020 && c <= 0x00007E) ||\n    ((c >= 0x000A1 && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029) ||\n    ((c >= 0x0E000 && c <= 0x00FFFD) && c !== CHAR_BOM) ||\n    (c >= 0x10000 && c <= 0x10FFFF)\n}\n\n// [34] ns-char ::= nb-char - s-white\n// [27] nb-char ::= c-printable - b-char - c-byte-order-mark\n// [26] b-char  ::= b-line-feed | b-carriage-return\n// Including s-white (for some reason, examples doesn't match specs in this aspect)\n// ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark\nfunction isNsCharOrWhitespace (c) {\n  return isPrintable(c) &&\n    c !== CHAR_BOM &&\n    // - b-char\n    c !== CHAR_CARRIAGE_RETURN &&\n    c !== CHAR_LINE_FEED\n}\n\n// [127]  ns-plain-safe(c) ::= c = flow-out  ⇒ ns-plain-safe-out\n//                             c = flow-in   ⇒ ns-plain-safe-in\n//                             c = block-key ⇒ ns-plain-safe-out\n//                             c = flow-key  ⇒ ns-plain-safe-in\n// [128] ns-plain-safe-out ::= ns-char\n// [129]  ns-plain-safe-in ::= ns-char - c-flow-indicator\n// [130]  ns-plain-char(c) ::=  ( ns-plain-safe(c) - “:” - “#” )\n//                            | ( /* An ns-char preceding */ “#” )\n//                            | ( “:” /* Followed by an ns-plain-safe(c) */ )\nfunction isPlainSafe (c, prev, inblock) {\n  const cIsNsCharOrWhitespace = isNsCharOrWhitespace(c)\n  const cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c)\n  return (\n    (\n      // ns-plain-safe\n      inblock // c = flow-in\n        ? cIsNsCharOrWhitespace\n        : cIsNsCharOrWhitespace &&\n          // - c-flow-indicator\n          c !== CHAR_COMMA &&\n          c !== CHAR_LEFT_SQUARE_BRACKET &&\n          c !== CHAR_RIGHT_SQUARE_BRACKET &&\n          c !== CHAR_LEFT_CURLY_BRACKET &&\n          c !== CHAR_RIGHT_CURLY_BRACKET\n    ) &&\n    // ns-plain-char\n    c !== CHAR_SHARP && // false on '#'\n    !(prev === CHAR_COLON && !cIsNsChar)\n  ) || // false on ': '\n  (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP) || // change to true on '[^ ]#'\n  (prev === CHAR_COLON && cIsNsChar) // change to true on ':[^ ]'\n}\n\n// Simplified test for values allowed as the first character in plain style.\nfunction isPlainSafeFirst (c) {\n  // Uses a subset of ns-char - c-indicator\n  // where ns-char = nb-char - s-white.\n  // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part\n  return isPrintable(c) &&\n    c !== CHAR_BOM &&\n    !isWhitespace(c) && // - s-white\n    // - (c-indicator ::=\n    // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”\n    c !== CHAR_MINUS &&\n    c !== CHAR_QUESTION &&\n    c !== CHAR_COLON &&\n    c !== CHAR_COMMA &&\n    c !== CHAR_LEFT_SQUARE_BRACKET &&\n    c !== CHAR_RIGHT_SQUARE_BRACKET &&\n    c !== CHAR_LEFT_CURLY_BRACKET &&\n    c !== CHAR_RIGHT_CURLY_BRACKET &&\n    // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “\"”\n    c !== CHAR_SHARP &&\n    c !== CHAR_AMPERSAND &&\n    c !== CHAR_ASTERISK &&\n    c !== CHAR_EXCLAMATION &&\n    c !== CHAR_VERTICAL_LINE &&\n    c !== CHAR_EQUALS &&\n    c !== CHAR_GREATER_THAN &&\n    c !== CHAR_SINGLE_QUOTE &&\n    c !== CHAR_DOUBLE_QUOTE &&\n    // | “%” | “@” | “`”)\n    c !== CHAR_PERCENT &&\n    c !== CHAR_COMMERCIAL_AT &&\n    c !== CHAR_GRAVE_ACCENT\n}\n\n// Simplified test for values allowed as the last character in plain style.\nfunction isPlainSafeLast (c) {\n  // just not whitespace or colon, it will be checked to be plain character later\n  return !isWhitespace(c) && c !== CHAR_COLON\n}\n\n// Same as 'string'.codePointAt(pos), but works in older browsers.\nfunction codePointAt (string, pos) {\n  const first = string.charCodeAt(pos)\n  let second\n\n  if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) {\n    second = string.charCodeAt(pos + 1)\n    if (second >= 0xDC00 && second <= 0xDFFF) {\n      // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae\n      return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000\n    }\n  }\n  return first\n}\n\n// Determines whether block indentation indicator is required.\nfunction needIndentIndicator (string) {\n  const leadingSpaceRe = /^\\n* /\n  return leadingSpaceRe.test(string)\n}\n\nconst STYLE_PLAIN = 1\nconst STYLE_SINGLE = 2\nconst STYLE_LITERAL = 3\nconst STYLE_FOLDED = 4\nconst STYLE_DOUBLE = 5\n\n// Determines which scalar styles are possible and returns the preferred style.\n// lineWidth = -1 => no limit.\n// Pre-conditions: str.length > 0.\n// Post-conditions:\n//    STYLE_PLAIN or STYLE_SINGLE => no \\n are in the string.\n//    STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).\n//    STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).\nfunction chooseScalarStyle (string, singleLineOnly, indentPerLevel, lineWidth,\n  testAmbiguousType, quotingType, forceQuotes, inblock) {\n  let i\n  let char = 0\n  let prevChar = null\n  let hasLineBreak = false\n  let hasFoldableLine = false // only checked if shouldTrackWidth\n  const shouldTrackWidth = lineWidth !== -1\n  let previousLineBreak = -1 // count the first line correctly\n  let plain = isPlainSafeFirst(codePointAt(string, 0)) &&\n    isPlainSafeLast(codePointAt(string, string.length - 1))\n\n  if (singleLineOnly || forceQuotes) {\n    // Case: no block styles.\n    // Check for disallowed characters to rule out plain and single.\n    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n      char = codePointAt(string, i)\n      if (!isPrintable(char)) {\n        return STYLE_DOUBLE\n      }\n      plain = plain && isPlainSafe(char, prevChar, inblock)\n      prevChar = char\n    }\n  } else {\n    // Case: block styles permitted.\n    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n      char = codePointAt(string, i)\n      if (char === CHAR_LINE_FEED) {\n        hasLineBreak = true\n        // Check if any line can be folded.\n        if (shouldTrackWidth) {\n          hasFoldableLine = hasFoldableLine ||\n            // Foldable line = too long, and not more-indented.\n            (i - previousLineBreak - 1 > lineWidth &&\n             string[previousLineBreak + 1] !== ' ')\n          previousLineBreak = i\n        }\n      } else if (!isPrintable(char)) {\n        return STYLE_DOUBLE\n      }\n      plain = plain && isPlainSafe(char, prevChar, inblock)\n      prevChar = char\n    }\n    // in case the end is missing a \\n\n    hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&\n      (i - previousLineBreak - 1 > lineWidth &&\n       string[previousLineBreak + 1] !== ' '))\n  }\n  // Although every style can represent \\n without escaping, prefer block styles\n  // for multiline, since they're more readable and they don't add empty lines.\n  // Also prefer folding a super-long line.\n  if (!hasLineBreak && !hasFoldableLine) {\n    // Strings interpretable as another type have to be quoted;\n    // e.g. the string 'true' vs. the boolean true.\n    if (plain && !forceQuotes && !testAmbiguousType(string)) {\n      return STYLE_PLAIN\n    }\n    return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE\n  }\n  // Edge case: block indentation indicator can only have one digit.\n  if (indentPerLevel > 9 && needIndentIndicator(string)) {\n    return STYLE_DOUBLE\n  }\n  // At this point we know block styles are valid.\n  // Prefer literal style unless we want to fold.\n  if (!forceQuotes) {\n    return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL\n  }\n  return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE\n}\n\n// Note: line breaking/folding is implemented for only the folded style.\n// NB. We drop the last trailing newline (if any) of a returned block scalar\n//  since the dumper adds its own newline. This always works:\n//    • No ending newline => unaffected; already using strip \"-\" chomping.\n//    • Ending newline    => removed then restored.\n//  Importantly, this keeps the \"+\" chomp indicator from gaining an extra line.\nfunction writeScalar (state, string, level, iskey, inblock) {\n  state.dump = (function () {\n    if (string.length === 0) {\n      return state.quotingType === QUOTING_TYPE_DOUBLE ? '\"\"' : \"''\"\n    }\n    if (!state.noCompatMode) {\n      if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {\n        return state.quotingType === QUOTING_TYPE_DOUBLE ? ('\"' + string + '\"') : (\"'\" + string + \"'\")\n      }\n    }\n\n    const indent = state.indent * Math.max(1, level) // no 0-indent scalars\n    // As indentation gets deeper, let the width decrease monotonically\n    // to the lower bound min(state.lineWidth, 40).\n    // Note that this implies\n    //  state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.\n    //  state.lineWidth > 40 + state.indent: width decreases until the lower bound.\n    // This behaves better than a constant minimum width which disallows narrower options,\n    // or an indent threshold which causes the width to suddenly increase.\n    const lineWidth = (state.lineWidth === -1)\n      ? -1\n      : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent)\n\n    // Without knowing if keys are implicit/explicit, assume implicit for safety.\n    const singleLineOnly = iskey ||\n      // No block styles in flow mode.\n      (state.flowLevel > -1 && level >= state.flowLevel)\n    function testAmbiguity (string) {\n      return testImplicitResolving(state, string)\n    }\n\n    switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth,\n      testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {\n      case STYLE_PLAIN:\n        return string\n      case STYLE_SINGLE:\n        return \"'\" + string.replace(/'/g, \"''\") + \"'\"\n      case STYLE_LITERAL:\n        return '|' + blockHeader(string, state.indent) +\n          dropEndingNewline(indentString(string, indent))\n      case STYLE_FOLDED:\n        return '>' + blockHeader(string, state.indent) +\n          dropEndingNewline(indentString(foldString(string, lineWidth), indent))\n      case STYLE_DOUBLE:\n        return '\"' + escapeString(string, lineWidth) + '\"'\n      default:\n        throw new YAMLException('impossible error: invalid scalar style')\n    }\n  }())\n}\n\n// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.\nfunction blockHeader (string, indentPerLevel) {\n  const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : ''\n\n  // note the special case: the string '\\n' counts as a \"trailing\" empty line.\n  const clip = string[string.length - 1] === '\\n'\n  const keep = clip && (string[string.length - 2] === '\\n' || string === '\\n')\n  const chomp = keep ? '+' : (clip ? '' : '-')\n\n  return indentIndicator + chomp + '\\n'\n}\n\n// (See the note for writeScalar.)\nfunction dropEndingNewline (string) {\n  return string[string.length - 1] === '\\n' ? string.slice(0, -1) : string\n}\n\n// Note: a long line without a suitable break point will exceed the width limit.\n// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.\nfunction foldString (string, width) {\n  // In folded style, $k$ consecutive newlines output as $k+1$ newlines—\n  // unless they're before or after a more-indented line, or at the very\n  // beginning or end, in which case $k$ maps to $k$.\n  // Therefore, parse each chunk as newline(s) followed by a content line.\n  const lineRe = /(\\n+)([^\\n]*)/g\n\n  // first line (possibly an empty line)\n  let result = (function () {\n    let nextLF = string.indexOf('\\n')\n    nextLF = nextLF !== -1 ? nextLF : string.length\n    lineRe.lastIndex = nextLF\n    return foldLine(string.slice(0, nextLF), width)\n  }())\n  // If we haven't reached the first content line yet, don't add an extra \\n.\n  let prevMoreIndented = string[0] === '\\n' || string[0] === ' '\n  let moreIndented\n\n  // rest of the lines\n  let match\n  while ((match = lineRe.exec(string))) {\n    const prefix = match[1]\n    const line = match[2]\n\n    moreIndented = (line[0] === ' ')\n    result += prefix +\n      ((!prevMoreIndented && !moreIndented && line !== '') ? '\\n' : '') +\n      foldLine(line, width)\n    prevMoreIndented = moreIndented\n  }\n\n  return result\n}\n\n// Greedy line breaking.\n// Picks the longest line under the limit each time,\n// otherwise settles for the shortest line over the limit.\n// NB. More-indented lines *cannot* be folded, as that would add an extra \\n.\nfunction foldLine (line, width) {\n  if (line === '' || line[0] === ' ') return line\n\n  // Since a more-indented line adds a \\n, breaks can't be followed by a space.\n  const breakRe = / [^ ]/g // note: the match index will always be <= length-2.\n  let match\n  // start is an inclusive index. end, curr, and next are exclusive.\n  let start = 0\n  let end\n  let curr = 0\n  let next = 0\n  let result = ''\n\n  // Invariants: 0 <= start <= length-1.\n  //   0 <= curr <= next <= max(0, length-2). curr - start <= width.\n  // Inside the loop:\n  //   A match implies length >= 2, so curr and next are <= length-2.\n  while ((match = breakRe.exec(line))) {\n    next = match.index\n    // maintain invariant: curr - start <= width\n    if (next - start > width) {\n      end = (curr > start) ? curr : next // derive end <= length-2\n      result += '\\n' + line.slice(start, end)\n      // skip the space that was output as \\n\n      start = end + 1                    // derive start <= length-1\n    }\n    curr = next\n  }\n\n  // By the invariants, start <= length-1, so there is something left over.\n  // It is either the whole string or a part starting from non-whitespace.\n  result += '\\n'\n  // Insert a break if the remainder is too long and there is a break available.\n  if (line.length - start > width && curr > start) {\n    result += line.slice(start, curr) + '\\n' + line.slice(curr + 1)\n  } else {\n    result += line.slice(start)\n  }\n\n  return result.slice(1) // drop extra \\n joiner\n}\n\n// Escapes a double-quoted string.\nfunction escapeString (string) {\n  let result = ''\n  let char = 0\n\n  for (let i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n    char = codePointAt(string, i)\n    const escapeSeq = ESCAPE_SEQUENCES[char]\n\n    if (!escapeSeq && isPrintable(char)) {\n      result += string[i]\n      if (char >= 0x10000) result += string[i + 1]\n    } else {\n      result += escapeSeq || encodeHex(char)\n    }\n  }\n\n  return result\n}\n\nfunction writeFlowSequence (state, level, object) {\n  let _result = ''\n  const _tag = state.tag\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    let value = object[index]\n\n    if (state.replacer) {\n      value = state.replacer.call(object, String(index), value)\n    }\n\n    // Write only valid elements, put null instead of invalid elements.\n    if (writeNode(state, level, value, false, false) ||\n        (typeof value === 'undefined' &&\n         writeNode(state, level, null, false, false))) {\n      if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : '')\n      _result += state.dump\n    }\n  }\n\n  state.tag = _tag\n  state.dump = '[' + _result + ']'\n}\n\nfunction writeBlockSequence (state, level, object, compact) {\n  let _result = ''\n  const _tag = state.tag\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    let value = object[index]\n\n    if (state.replacer) {\n      value = state.replacer.call(object, String(index), value)\n    }\n\n    // Write only valid elements, put null instead of invalid elements.\n    if (writeNode(state, level + 1, value, true, true, false, true) ||\n        (typeof value === 'undefined' &&\n         writeNode(state, level + 1, null, true, true, false, true))) {\n      if (!compact || _result !== '') {\n        _result += generateNextLine(state, level)\n      }\n\n      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n        _result += '-'\n      } else {\n        _result += '- '\n      }\n\n      _result += state.dump\n    }\n  }\n\n  state.tag = _tag\n  state.dump = _result || '[]' // Empty sequence if no valid values.\n}\n\nfunction writeFlowMapping (state, level, object) {\n  let _result = ''\n  const _tag = state.tag\n  const objectKeyList = Object.keys(object)\n\n  for (let index = 0, length = objectKeyList.length; index < length; index += 1) {\n    let pairBuffer = ''\n    if (_result !== '') pairBuffer += ', '\n\n    if (state.condenseFlow) pairBuffer += '\"'\n\n    const objectKey = objectKeyList[index]\n    let objectValue = object[objectKey]\n\n    if (state.replacer) {\n      objectValue = state.replacer.call(object, objectKey, objectValue)\n    }\n\n    if (!writeNode(state, level, objectKey, false, false)) {\n      continue // Skip this pair because of invalid key;\n    }\n\n    if (state.dump.length > 1024) pairBuffer += '? '\n\n    pairBuffer += state.dump + (state.condenseFlow ? '\"' : '') + ':' + (state.condenseFlow ? '' : ' ')\n\n    if (!writeNode(state, level, objectValue, false, false)) {\n      continue // Skip this pair because of invalid value.\n    }\n\n    pairBuffer += state.dump\n\n    // Both key and value are valid.\n    _result += pairBuffer\n  }\n\n  state.tag = _tag\n  state.dump = '{' + _result + '}'\n}\n\nfunction writeBlockMapping (state, level, object, compact) {\n  let _result = ''\n  const _tag = state.tag\n  const objectKeyList = Object.keys(object)\n\n  // Allow sorting keys so that the output file is deterministic\n  if (state.sortKeys === true) {\n    // Default sorting\n    objectKeyList.sort()\n  } else if (typeof state.sortKeys === 'function') {\n    // Custom sort function\n    objectKeyList.sort(state.sortKeys)\n  } else if (state.sortKeys) {\n    // Something is wrong\n    throw new YAMLException('sortKeys must be a boolean or a function')\n  }\n\n  for (let index = 0, length = objectKeyList.length; index < length; index += 1) {\n    let pairBuffer = ''\n\n    if (!compact || _result !== '') {\n      pairBuffer += generateNextLine(state, level)\n    }\n\n    const objectKey = objectKeyList[index]\n    let objectValue = object[objectKey]\n\n    if (state.replacer) {\n      objectValue = state.replacer.call(object, objectKey, objectValue)\n    }\n\n    if (!writeNode(state, level + 1, objectKey, true, true, true)) {\n      continue // Skip this pair because of invalid key.\n    }\n\n    const explicitPair = (state.tag !== null && state.tag !== '?') ||\n                   (state.dump && state.dump.length > 1024)\n\n    if (explicitPair) {\n      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n        pairBuffer += '?'\n      } else {\n        pairBuffer += '? '\n      }\n    }\n\n    pairBuffer += state.dump\n\n    if (explicitPair) {\n      pairBuffer += generateNextLine(state, level)\n    }\n\n    if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {\n      continue // Skip this pair because of invalid value.\n    }\n\n    if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n      pairBuffer += ':'\n    } else {\n      pairBuffer += ': '\n    }\n\n    pairBuffer += state.dump\n\n    // Both key and value are valid.\n    _result += pairBuffer\n  }\n\n  state.tag = _tag\n  state.dump = _result || '{}' // Empty mapping if no valid pairs.\n}\n\nfunction detectType (state, object, explicit) {\n  const typeList = explicit ? state.explicitTypes : state.implicitTypes\n\n  for (let index = 0, length = typeList.length; index < length; index += 1) {\n    const type = typeList[index]\n\n    if ((type.instanceOf || type.predicate) &&\n        (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&\n        (!type.predicate || type.predicate(object))) {\n      if (explicit) {\n        if (type.multi && type.representName) {\n          state.tag = type.representName(object)\n        } else {\n          state.tag = type.tag\n        }\n      } else {\n        state.tag = '?'\n      }\n\n      if (type.represent) {\n        const style = state.styleMap[type.tag] || type.defaultStyle\n\n        let _result\n        if (_toString.call(type.represent) === '[object Function]') {\n          _result = type.represent(object, style)\n        } else if (_hasOwnProperty.call(type.represent, style)) {\n          _result = type.represent[style](object, style)\n        } else {\n          throw new YAMLException('!<' + type.tag + '> tag resolver accepts not \"' + style + '\" style')\n        }\n\n        state.dump = _result\n      }\n\n      return true\n    }\n  }\n\n  return false\n}\n\n// Serializes `object` and writes it to global `result`.\n// Returns true on success, or false on invalid object.\n//\nfunction writeNode (state, level, object, block, compact, iskey, isblockseq) {\n  state.tag = null\n  state.dump = object\n\n  if (!detectType(state, object, false)) {\n    detectType(state, object, true)\n  }\n\n  const type = _toString.call(state.dump)\n  const inblock = block\n\n  if (block) {\n    block = (state.flowLevel < 0 || state.flowLevel > level)\n  }\n\n  const objectOrArray = type === '[object Object]' || type === '[object Array]'\n  let duplicateIndex\n  let duplicate\n\n  if (objectOrArray) {\n    duplicateIndex = state.duplicates.indexOf(object)\n    duplicate = duplicateIndex !== -1\n  }\n\n  if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {\n    compact = false\n  }\n\n  if (duplicate && state.usedDuplicates[duplicateIndex]) {\n    state.dump = '*ref_' + duplicateIndex\n  } else {\n    if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {\n      state.usedDuplicates[duplicateIndex] = true\n    }\n    if (type === '[object Object]') {\n      if (block && (Object.keys(state.dump).length !== 0)) {\n        writeBlockMapping(state, level, state.dump, compact)\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + state.dump\n        }\n      } else {\n        writeFlowMapping(state, level, state.dump)\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump\n        }\n      }\n    } else if (type === '[object Array]') {\n      if (block && (state.dump.length !== 0)) {\n        if (state.noArrayIndent && !isblockseq && level > 0) {\n          writeBlockSequence(state, level - 1, state.dump, compact)\n        } else {\n          writeBlockSequence(state, level, state.dump, compact)\n        }\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + state.dump\n        }\n      } else {\n        writeFlowSequence(state, level, state.dump)\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump\n        }\n      }\n    } else if (type === '[object String]') {\n      if (state.tag !== '?') {\n        writeScalar(state, state.dump, level, iskey, inblock)\n      }\n    } else if (type === '[object Undefined]') {\n      return false\n    } else {\n      if (state.skipInvalid) return false\n      throw new YAMLException('unacceptable kind of an object to dump ' + type)\n    }\n\n    if (state.tag !== null && state.tag !== '?') {\n      // Need to encode all characters except those allowed by the spec:\n      //\n      // [35] ns-dec-digit    ::=  [#x30-#x39] /* 0-9 */\n      // [36] ns-hex-digit    ::=  ns-dec-digit\n      //                         | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */\n      // [37] ns-ascii-letter ::=  [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */\n      // [38] ns-word-char    ::=  ns-dec-digit | ns-ascii-letter | “-”\n      // [39] ns-uri-char     ::=  “%” ns-hex-digit ns-hex-digit | ns-word-char | “#”\n      //                         | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,”\n      //                         | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]”\n      //\n      // Also need to encode '!' because it has special meaning (end of tag prefix).\n      //\n      let tagStr = encodeURI(\n        state.tag[0] === '!' ? state.tag.slice(1) : state.tag\n      ).replace(/!/g, '%21')\n\n      if (state.tag[0] === '!') {\n        tagStr = '!' + tagStr\n      } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') {\n        tagStr = '!!' + tagStr.slice(18)\n      } else {\n        tagStr = '!<' + tagStr + '>'\n      }\n\n      state.dump = tagStr + ' ' + state.dump\n    }\n  }\n\n  return true\n}\n\nfunction getDuplicateReferences (object, state) {\n  const objects = []\n  const duplicatesIndexes = []\n\n  inspectNode(object, objects, duplicatesIndexes)\n\n  const length = duplicatesIndexes.length\n  for (let index = 0; index < length; index += 1) {\n    state.duplicates.push(objects[duplicatesIndexes[index]])\n  }\n  state.usedDuplicates = new Array(length)\n}\n\nfunction inspectNode (object, objects, duplicatesIndexes) {\n  if (object !== null && typeof object === 'object') {\n    const index = objects.indexOf(object)\n    if (index !== -1) {\n      if (duplicatesIndexes.indexOf(index) === -1) {\n        duplicatesIndexes.push(index)\n      }\n    } else {\n      objects.push(object)\n\n      if (Array.isArray(object)) {\n        for (let i = 0, length = object.length; i < length; i += 1) {\n          inspectNode(object[i], objects, duplicatesIndexes)\n        }\n      } else {\n        const objectKeyList = Object.keys(object)\n\n        for (let i = 0, length = objectKeyList.length; i < length; i += 1) {\n          inspectNode(object[objectKeyList[i]], objects, duplicatesIndexes)\n        }\n      }\n    }\n  }\n}\n\nfunction dump (input, options) {\n  options = options || {}\n\n  const state = new State(options)\n\n  if (!state.noRefs) getDuplicateReferences(input, state)\n\n  let value = input\n\n  if (state.replacer) {\n    value = state.replacer.call({ '': value }, '', value)\n  }\n\n  if (writeNode(state, 0, value, true, true)) return state.dump + '\\n'\n\n  return ''\n}\n\nmodule.exports.dump = dump\n","'use strict'\n\nconst loader = require('./lib/loader')\nconst dumper = require('./lib/dumper')\n\nfunction renamed (from, to) {\n  return function () {\n    throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' +\n      'Use yaml.' + to + ' instead, which is now safe by default.')\n  }\n}\n\nmodule.exports.Type = require('./lib/type')\nmodule.exports.Schema = require('./lib/schema')\nmodule.exports.FAILSAFE_SCHEMA = require('./lib/schema/failsafe')\nmodule.exports.JSON_SCHEMA = require('./lib/schema/json')\nmodule.exports.CORE_SCHEMA = require('./lib/schema/core')\nmodule.exports.DEFAULT_SCHEMA = require('./lib/schema/default')\nmodule.exports.load = loader.load\nmodule.exports.loadAll = loader.loadAll\nmodule.exports.dump = dumper.dump\nmodule.exports.YAMLException = require('./lib/exception')\n\n// Re-export all types in case user wants to create custom schema\nmodule.exports.types = {\n  binary: require('./lib/type/binary'),\n  float: require('./lib/type/float'),\n  map: require('./lib/type/map'),\n  null: require('./lib/type/null'),\n  pairs: require('./lib/type/pairs'),\n  set: require('./lib/type/set'),\n  timestamp: require('./lib/type/timestamp'),\n  bool: require('./lib/type/bool'),\n  int: require('./lib/type/int'),\n  merge: require('./lib/type/merge'),\n  omap: require('./lib/type/omap'),\n  seq: require('./lib/type/seq'),\n  str: require('./lib/type/str')\n}\n\n// Removed functions from JS-YAML 3.0.x\nmodule.exports.safeLoad = renamed('safeLoad', 'load')\nmodule.exports.safeLoadAll = renamed('safeLoadAll', 'loadAll')\nmodule.exports.safeDump = renamed('safeDump', 'dump')\n","import yaml from '../index.js'\n\nconst {\n  Type,\n  Schema,\n  FAILSAFE_SCHEMA,\n  JSON_SCHEMA,\n  CORE_SCHEMA,\n  DEFAULT_SCHEMA,\n  load,\n  loadAll,\n  dump,\n  YAMLException,\n  types,\n  safeLoad,\n  safeLoadAll,\n  safeDump\n} = yaml\n\nexport {\n  Type,\n  Schema,\n  FAILSAFE_SCHEMA,\n  JSON_SCHEMA,\n  CORE_SCHEMA,\n  DEFAULT_SCHEMA,\n  load,\n  loadAll,\n  dump,\n  YAMLException,\n  types,\n  safeLoad,\n  safeLoadAll,\n  safeDump\n}\n\nexport default yaml\n"],"names":["_typeof","o","Symbol","iterator","constructor","prototype","isNothing","subject","common","isObject","toArray","sequence","Array","isArray","repeat","string","count","result","cycle","isNegativeZero","number","Number","NEGATIVE_INFINITY","extend","target","source","sourceKeys","Object","keys","index","length","key","formatError","exception","compact","where","message","reason","mark","name","line","column","snippet","YAMLException","Error","call","this","captureStackTrace","stack","create","toString","require$$0","TYPE_CONSTRUCTOR_OPTIONS","YAML_NODE_KINDS","type","tag","options","map","forEach","indexOf","kind","resolve","construct","data","instanceOf","predicate","represent","representName","defaultStyle","multi","styleAliases","style","alias","String","Type","require$$1","compileList","schema","currentType","newIndex","previousType","previousIndex","Schema","definition","implicit","explicit","push","concat","loadKind","compiledImplicit","compiledExplicit","compiledTypeMap","scalar","mapping","fallback","collectType","arguments","compileMap","str","seq","failsafe","require$$2","require$$3","_null","max","object","canonical","lowercase","uppercase","camelcase","empty","bool","isHexCode","c","isOctCode","isDecCode","parseYamlInteger","value","sign","ch","slice","parseInt","int","hasDigits","isFinite","charCodeAt","binary","obj","octal","decimal","hexadecimal","toUpperCase","YAML_FLOAT_PATTERN","RegExp","YAML_FLOAT_SPECIAL_PATTERN","SCIENTIFIC_WITHOUT_DOT","float","test","parseFloat","toLowerCase","POSITIVE_INFINITY","NaN","isNaN","res","replace","json","require$$4","core","YAML_DATE_REGEXP","YAML_TIMESTAMP_REGEXP","timestamp","exec","fraction","delta","match","year","month","day","Date","UTC","hour","minute","second","date","setTime","getTime","toISOString","merge","BASE64_MAP","bitlen","idx","code","charAt","input","bits","tailbits","Uint8Array","tail","_hasOwnProperty","hasOwnProperty","_toString","omap","objectKeys","pair","pairHasKey","pairKey","defineProperty","pairs","set","_default","require$$5","require$$6","makeSnippet","getLine","buffer","lineStart","lineEnd","position","maxLineLength","head","maxHalfLength","Math","floor","pos","padStart","maxLength","indent","linesBefore","linesAfter","re","lineStarts","lineEnds","foundLineNo","lineNoLength","min","i","DEFAULT_SCHEMA","PATTERN_NON_PRINTABLE","PATTERN_NON_ASCII_LINE_BREAKS","PATTERN_FLOW_INDICATORS","PATTERN_TAG_HANDLE","PATTERN_TAG_URI","_class","isEol","isWhiteSpace","isWsOrEol","isFlowIndicator","fromHexCode","lc","escapedHexLen","fromDecimalCode","simpleEscapeSequence","charFromCodepoint","fromCharCode","setProperty","configurable","enumerable","writable","simpleEscapeCheck","simpleEscapeMap","State","filename","onWarning","legacy","listener","maxDepth","maxTotalMergeKeys","implicitTypes","typeMap","lineIndent","depth","totalMergeKeys","firstTabInLine","documents","anchorMapTransactions","generateError","state","throwError","throwWarning","storeAnchor","transactions","transaction","existed","anchorMap","snapshotState","anchor","restoreState","snapshot","directiveHandlers","YAML","args","version","major","minor","checkLineBreaks","TAG","prefix","handle","tagMap","decodeURIComponent","err","captureSegment","start","end","checkJson","_result","_position","_length","_character","mergeMappings","destination","overridableKeys","quantity","storeMappingPair","keyTag","keyNode","valueNode","startLine","startLineStart","startPos","readLineBreak","skipSeparationSpace","allowComments","checkIndent","lineBreaks","testDocumentSeparator","writeFoldedLines","readBlockSequence","nodeIndent","_tag","_anchor","detected","_line","composeNode","readBlockMapping","flowIndent","allowCompact","_keyLine","_keyLineStart","_keyPos","atExplicitKey","following","readTagProperty","tagHandle","tagName","isVerbatim","isNamed","readAnchorProperty","tryReadBlockMappingFromProperty","propertyStart","fallbackState","beginAnchorTransaction","pop","parent","names","commitAnchorTransaction","entry","rollbackAnchorTransaction","parentIndent","nodeContext","allowToSeek","allowBlockScalars","allowBlockCollections","blockIndent","indentStatus","atNewLine","hasContent","allowBlockStyles","propertyState","_lineStart","_pos","terminator","isPair","isExplicitPair","isMapping","readNext","readFlowCollection","folding","tmp","chomping","didReadContent","detectedIndent","textIndent","emptyLines","atMoreIndented","captureStart","readBlockScalar","captureEnd","readSingleQuotedScalar","hexLength","hexResult","readDoubleQuotedScalar","readAlias","withinFlowCollection","hasPendingContent","_lineIndent","_kind","readPlainScalar","typeIndex","typeQuantity","typeList","readDocument","documentStart","hasDirectives","directiveName","directiveArgs","loadDocuments","nullpos","loader","loadAll","load","CHAR_BOM","ESCAPE_SEQUENCES","DEPRECATED_BOOLEANS_SYNTAX","DEPRECATED_BASE60_SYNTAX","encodeHex","character","noArrayIndent","skipInvalid","flowLevel","styleMap","compileStyleMap","sortKeys","lineWidth","noRefs","noCompatMode","condenseFlow","quotingType","forceQuotes","replacer","explicitTypes","duplicates","usedDuplicates","indentString","spaces","ind","next","generateNextLine","level","isWhitespace","isPrintable","isNsCharOrWhitespace","isPlainSafe","prev","inblock","cIsNsCharOrWhitespace","cIsNsChar","codePointAt","first","needIndentIndicator","chooseScalarStyle","singleLineOnly","indentPerLevel","testAmbiguousType","char","prevChar","hasLineBreak","hasFoldableLine","shouldTrackWidth","previousLineBreak","plain","isPlainSafeLast","writeScalar","iskey","dump","testImplicitResolving","blockHeader","dropEndingNewline","width","moreIndented","lineRe","nextLF","lastIndex","foldLine","prevMoreIndented","foldString","escapeSeq","escapeString","indentIndicator","clip","breakRe","curr","writeBlockSequence","writeNode","detectType","block","isblockseq","duplicateIndex","duplicate","objectOrArray","objectKeyList","sort","pairBuffer","objectKey","objectValue","explicitPair","writeBlockMapping","writeFlowMapping","writeFlowSequence","tagStr","encodeURI","getDuplicateReferences","objects","duplicatesIndexes","inspectNode","dumper","renamed","from","to","jsYaml","FAILSAFE_SCHEMA","JSON_SCHEMA","CORE_SCHEMA","require$$7","require$$8","types","require$$9","require$$10","require$$11","null","require$$12","require$$13","require$$14","require$$15","require$$16","require$$17","require$$18","require$$19","require$$20","require$$21","safeLoad","safeLoadAll","safeDump","yaml"],"mappings":"udAAY,SAAAA,EAAAC,GAAA,OAAAD,EAAA,mBAAAE,QAAA,iBAAAA,OAAAC,SAAA,SAAAF,GAAA,cAAAA,GAAA,SAAAA,GAAA,OAAAA,GAAA,mBAAAC,QAAAD,EAAAG,cAAAF,QAAAD,IAAAC,OAAAG,UAAA,gBAAAJ,CAAA,GAAAA,EAAA,CAEZ,SAASK,EAAWC,GAClB,OAAQ,MAAOA,CACjB,YAwCAC,EAAAF,UAA2BA,EAC3BE,EAAAC,SAvCA,SAAmBF,GACjB,MAA2B,WAAnBP,EAAOO,IAAsC,OAAZA,CAC3C,EAsCAC,EAAAE,QApCA,SAAkBC,GAChB,OAAIC,MAAMC,QAAQF,GAAkBA,EAC3BL,EAAUK,GAAkB,GAE9B,CAACA,EACV,EAgCAH,EAAAM,OAjBA,SAAiBC,EAAQC,GAGvB,IAFA,IAAIC,EAAS,GAEJC,EAAQ,EAAGA,EAAQF,EAAOE,GAAS,EAC1CD,GAAUF,EAGZ,OAAOE,CACT,EAUAT,EAAAW,eARA,SAAyBC,GACvB,OAAmB,IAAXA,GAAkBC,OAAOC,oBAAsB,EAAIF,CAC7D,EAOAZ,EAAAe,OAhCA,SAAiBC,EAAQC,GACvB,GAAIA,EAGF,IAFA,IAAMC,EAAaC,OAAOC,KAAKH,GAEtBI,EAAQ,EAAGC,EAASJ,EAAWI,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CAC1E,IAAME,EAAML,EAAWG,GACvBL,EAAOO,GAAON,EAAOM,EACvB,CAGF,OAAOP,CACT,+BCxBA,SAASQ,EAAaC,EAAWC,GAC/B,IAAIC,EAAQ,GACNC,EAAUH,EAAUI,QAAU,mBAEpC,OAAKJ,EAAUK,MAEXL,EAAUK,KAAKC,OACjBJ,GAAS,OAASF,EAAUK,KAAKC,KAAO,MAG1CJ,GAAS,KAAOF,EAAUK,KAAKE,KAAO,GAAK,KAAOP,EAAUK,KAAKG,OAAS,GAAK,KAE1EP,GAAWD,EAAUK,KAAKI,UAC7BP,GAAS,OAASF,EAAUK,KAAKI,SAG5BN,EAAU,IAAMD,GAZKC,CAa9B,CAEA,SAASO,EAAeN,EAAQC,GAE9BM,MAAMC,KAAKC,MAEXA,KAAKP,KAAO,gBACZO,KAAKT,OAASA,EACdS,KAAKR,KAAOA,EACZQ,KAAKV,QAAUJ,EAAYc,MAAM,GAG7BF,MAAMG,kBAERH,MAAMG,kBAAkBD,KAAMA,KAAK1C,aAGnC0C,KAAKE,OAAS,IAAIJ,OAASI,OAAS,EAExC,YAGAL,EAActC,UAAYsB,OAAOsB,OAAOL,MAAMvC,WAC9CsC,EAActC,UAAUD,YAAcuC,EAEtCA,EAActC,UAAU6C,SAAW,SAAmBhB,GACpD,OAAOY,KAAKP,KAAO,KAAOP,EAAYc,KAAMZ,EAC9C,EAEAD,EAAiBU,iCChDjB,IAAMA,EAAgBQ,IAEhBC,EAA2B,CAC/B,OACA,QACA,UACA,YACA,aACA,YACA,YACA,gBACA,eACA,gBAGIC,EAAkB,CACtB,SACA,WACA,kBA6CFC,EA5BA,SAAeC,EAAKC,GAdpB,IAA8BC,EACtBxC,EAoCN,GAtBAuC,EAAUA,GAAW,CAAA,EAErB7B,OAAOC,KAAK4B,GAASE,QAAQ,SAAUnB,GACrC,IAA+C,IAA3Ca,EAAyBO,QAAQpB,GACnC,MAAM,IAAII,EAAc,mBAAqBJ,EAAO,8BAAgCgB,EAAM,eAE9F,GAGAT,KAAKU,QAAUA,EACfV,KAAKS,IAAMA,EACXT,KAAKc,KAAOJ,EAAc,MAAK,KAC/BV,KAAKe,QAAUL,EAAiB,SAAK,WAAc,OAAO,GAC1DV,KAAKgB,UAAYN,EAAmB,WAAK,SAAUO,GAAQ,OAAOA,GAClEjB,KAAKkB,WAAaR,EAAoB,YAAK,KAC3CV,KAAKmB,UAAYT,EAAmB,WAAK,KACzCV,KAAKoB,UAAYV,EAAmB,WAAK,KACzCV,KAAKqB,cAAgBX,EAAuB,eAAK,KACjDV,KAAKsB,aAAeZ,EAAsB,cAAK,KAC/CV,KAAKuB,MAAQb,EAAe,QAAK,EACjCV,KAAKwB,cAnCuBb,EAmCYD,EAAsB,cAAK,KAlC7DvC,EAAS,CAAA,EAEH,OAARwC,GACF9B,OAAOC,KAAK6B,GAAKC,QAAQ,SAAUa,GACjCd,EAAIc,GAAOb,QAAQ,SAAUc,GAC3BvD,EAAOwD,OAAOD,IAAUD,CAC1B,EACF,GAGKtD,IA0BoC,IAAvCoC,EAAgBM,QAAQb,KAAKc,MAC/B,MAAM,IAAIjB,EAAc,iBAAmBG,KAAKc,KAAO,uBAAyBL,EAAM,eAE1F,iCC7DA,IAAMZ,EAAgBQ,IAChBuB,EAAOC,IAEb,SAASC,EAAaC,EAAQtC,GAC5B,IAAMtB,EAAS,GAgBf,OAdA4D,EAAOtC,GAAMmB,QAAQ,SAAUoB,GAC7B,IAAIC,EAAW9D,EAAOa,OAEtBb,EAAOyC,QAAQ,SAAUsB,EAAcC,GACjCD,EAAazB,MAAQuB,EAAYvB,KACjCyB,EAAapB,OAASkB,EAAYlB,MAClCoB,EAAaX,QAAUS,EAAYT,QACrCU,EAAWE,EAEf,GAEAhE,EAAO8D,GAAYD,CACrB,GAEO7D,CACT,CA8BA,SAASiE,EAAQC,GACf,OAAOrC,KAAKvB,OAAO4D,EACrB,QAEAD,EAAO7E,UAAUkB,OAAS,SAAiB4D,GACzC,IAAIC,EAAW,GACXC,EAAW,GAEf,GAAIF,aAAsBT,EAExBW,EAASC,KAAKH,WACLvE,MAAMC,QAAQsE,GAEvBE,EAAWA,EAASE,OAAOJ,YAClBA,IAAevE,MAAMC,QAAQsE,EAAWC,YAAaxE,MAAMC,QAAQsE,EAAWE,UAKvF,MAAM,IAAI1C,EAAc,oHAHpBwC,EAAWC,WAAUA,EAAWA,EAASG,OAAOJ,EAAWC,WAC3DD,EAAWE,WAAUA,EAAWA,EAASE,OAAOJ,EAAWE,UAIjE,CAEAD,EAAS1B,QAAQ,SAAUJ,GACzB,KAAMA,aAAgBoB,GACpB,MAAM,IAAI/B,EAAc,sFAG1B,GAAIW,EAAKkC,UAA8B,WAAlBlC,EAAKkC,SACxB,MAAM,IAAI7C,EAAc,mHAG1B,GAAIW,EAAKe,MACP,MAAM,IAAI1B,EAAc,qGAE5B,GAEA0C,EAAS3B,QAAQ,SAAUJ,GACzB,KAAMA,aAAgBoB,GACpB,MAAM,IAAI/B,EAAc,qFAE5B,GAEA,IAAM1B,EAASU,OAAOsB,OAAOiC,EAAO7E,WASpC,OAPAY,EAAOmE,UAAYtC,KAAKsC,UAAY,IAAIG,OAAOH,GAC/CnE,EAAOoE,UAAYvC,KAAKuC,UAAY,IAAIE,OAAOF,GAE/CpE,EAAOwE,iBAAmBb,EAAY3D,EAAQ,YAC9CA,EAAOyE,iBAAmBd,EAAY3D,EAAQ,YAC9CA,EAAO0E,gBA9ET,WACE,IAAM1E,EAAS,CACb2E,OAAQ,CAAA,EACRjF,SAAU,CAAA,EACVkF,QAAS,CAAA,EACTC,SAAU,CAAA,EACVzB,MAAO,CACLuB,OAAQ,GACRjF,SAAU,GACVkF,QAAS,GACTC,SAAU,KAGd,SAASC,EAAazC,GAChBA,EAAKe,OACPpD,EAAOoD,MAAMf,EAAKM,MAAM0B,KAAKhC,GAC7BrC,EAAOoD,MAAgB,SAAEiB,KAAKhC,IAE9BrC,EAAOqC,EAAKM,MAAMN,EAAKC,KAAOtC,EAAiB,SAAEqC,EAAKC,KAAOD,CAEjE,CAEA,IAAA,IAASzB,EAAQ,EAAGC,EAASkE,UAAUlE,OAAQD,EAAQC,EAAQD,GAAS,EACtEmE,UAAUnE,GAAO6B,QAAQqC,GAE3B,OAAO9E,CACT,CAoD2BgF,CAAWhF,EAAOwE,iBAAkBxE,EAAOyE,kBAE7DzE,CACT,EAEA4D,EAAiBK,iCC1GjB,IAAMR,EAAOvB,WAEb+C,EAAiB,IAAIxB,EAAK,wBAAyB,CACjDd,KAAM,SACNE,UAAW,SAAUC,GAAQ,OAAgB,OAATA,EAAgBA,EAAO,EAAG,oCCJhE,IAAMW,EAAOvB,WAEbgD,EAAiB,IAAIzB,EAAK,wBAAyB,CACjDd,KAAM,WACNE,UAAW,SAAUC,GAAQ,OAAgB,OAATA,EAAgBA,EAAO,EAAG,oCCJhE,IAAMW,EAAOvB,WAEbM,EAAiB,IAAIiB,EAAK,wBAAyB,CACjDd,KAAM,UACNE,UAAW,SAAUC,GAAQ,OAAgB,OAATA,EAAgBA,EAAO,CAAA,CAAG,oCCDhE,IAAMmB,EAAS/B,WAEfiD,EAAiB,IAAIlB,EAAO,CAC1BG,SAAU,CACRV,IACA0B,KACAC,wCCTJ,IAAM5B,EAAOvB,WAmBboD,EAAiB,IAAI7B,EAAK,yBAA0B,CAClDd,KAAM,SACNC,QAnBF,SAA0BE,GACxB,GAAa,OAATA,EAAe,OAAO,EAE1B,IAAMyC,EAAMzC,EAAKjC,OAEjB,OAAgB,IAAR0E,GAAsB,MAATzC,GACL,IAARyC,IAAuB,SAATzC,GAA4B,SAATA,GAA4B,SAATA,EAC9D,EAaED,UAXF,WACE,OAAO,IACT,EAUEG,UARF,SAAiBwC,GACf,OAAkB,OAAXA,CACT,EAOEvC,UAAW,CACTwC,UAAW,WAAc,MAAO,KAChCC,UAAW,WAAc,MAAO,QAChCC,UAAW,WAAc,MAAO,QAChCC,UAAW,WAAc,MAAO,QAChCC,MAAO,WAAc,MAAO,EAAG,GAEjC1C,aAAc,8CC/BhB,IAAMM,EAAOvB,WAqBb4D,EAAiB,IAAIrC,EAAK,yBAA0B,CAClDd,KAAM,SACNC,QArBF,SAA6BE,GAC3B,GAAa,OAATA,EAAe,OAAO,EAE1B,IAAMyC,EAAMzC,EAAKjC,OAEjB,OAAgB,IAAR0E,IAAuB,SAATzC,GAA4B,SAATA,GAA4B,SAATA,IAC5C,IAARyC,IAAuB,UAATzC,GAA6B,UAATA,GAA6B,UAATA,EAChE,EAeED,UAbF,SAA+BC,GAC7B,MAAgB,SAATA,GACS,SAATA,GACS,SAATA,CACT,EAUEE,UARF,SAAoBwC,GAClB,MAAkD,qBAA3C9E,OAAOtB,UAAU6C,SAASL,KAAK4D,EACxC,EAOEvC,UAAW,CACTyC,UAAW,SAAUF,GAAU,OAAOA,EAAS,OAAS,SACxDG,UAAW,SAAUH,GAAU,OAAOA,EAAS,OAAS,SACxDI,UAAW,SAAUJ,GAAU,OAAOA,EAAS,OAAS,OAAQ,GAElErC,aAAc,8CC/BhB,IAAM5D,EAAS2C,IACTuB,EAAOC,IAEb,SAASqC,EAAWC,GAClB,OAASA,GAAK,IAAiBA,GAAK,IAC3BA,GAAK,IAAiBA,GAAK,IAC3BA,GAAK,IAAiBA,GAAK,GACtC,CAEA,SAASC,EAAWD,GAClB,OAASA,GAAK,IAAiBA,GAAK,EACtC,CAEA,SAASE,EAAWF,GAClB,OAASA,GAAK,IAAiBA,GAAK,EACtC,CA0EA,SAASG,EAAkBrD,GACzB,IAAIsD,EAAQtD,EACRuD,EAAO,EAEPC,EAAKF,EAAM,GAQf,GANW,MAAPE,GAAqB,MAAPA,IACL,MAAPA,IAAYD,GAAO,GAEvBC,GADAF,EAAQA,EAAMG,MAAM,IACT,IAGC,MAAVH,EAAe,OAAO,EAE1B,GAAW,MAAPE,EAAY,CACd,GAAiB,MAAbF,EAAM,GAAY,OAAOC,EAAOG,SAASJ,EAAMG,MAAM,GAAI,GAC7D,GAAiB,MAAbH,EAAM,GAAY,OAAOC,EAAOG,SAASJ,EAAMG,MAAM,GAAI,IAC7D,GAAiB,MAAbH,EAAM,GAAY,OAAOC,EAAOG,SAASJ,EAAMG,MAAM,GAAI,EAC/D,CAEA,OAAOF,EAAOG,SAASJ,EAAO,GAChC,QAWAK,EAAiB,IAAIhD,EAAK,wBAAyB,CACjDd,KAAM,SACNC,QA1GF,SAA6BE,GAC3B,GAAa,OAATA,EAAe,OAAO,EAE1B,IAAMyC,EAAMzC,EAAKjC,OACbD,EAAQ,EACR8F,GAAY,EAEhB,IAAKnB,EAAK,OAAO,EAEjB,IAAIe,EAAKxD,EAAKlC,GAOd,GAJW,MAAP0F,GAAqB,MAAPA,IAChBA,EAAKxD,IAAOlC,IAGH,MAAP0F,EAAY,CAEd,GAAI1F,EAAQ,IAAM2E,EAAK,OAAO,EAK9B,GAAW,OAJXe,EAAKxD,IAAOlC,IAII,CAId,IAFAA,IAEOA,EAAQ2E,EAAK3E,IAAS,CAE3B,GAAW,OADX0F,EAAKxD,EAAKlC,KACe,MAAP0F,EAAY,OAAO,EACrCI,GAAY,CACd,CACA,OAAOA,GAAaC,SAASR,EAAiBrD,GAChD,CAEA,GAAW,MAAPwD,EAAY,CAId,IAFA1F,IAEOA,EAAQ2E,EAAK3E,IAAS,CAC3B,IAAKmF,EAAUjD,EAAK8D,WAAWhG,IAAS,OAAO,EAC/C8F,GAAY,CACd,CACA,OAAOA,GAAaC,SAASR,EAAiBrD,GAChD,CAEA,GAAW,MAAPwD,EAAY,CAId,IAFA1F,IAEOA,EAAQ2E,EAAK3E,IAAS,CAC3B,IAAKqF,EAAUnD,EAAK8D,WAAWhG,IAAS,OAAO,EAC/C8F,GAAY,CACd,CACA,OAAOA,GAAaC,SAASR,EAAiBrD,GAChD,CACF,CAIA,KAAOlC,EAAQ2E,EAAK3E,IAAS,CAC3B,IAAKsF,EAAUpD,EAAK8D,WAAWhG,IAC7B,OAAO,EAET8F,GAAY,CACd,CAEA,QAAKA,GAEEC,SAASR,EAAiBrD,GACnC,EAqCED,UAZF,SAA+BC,GAC7B,OAAOqD,EAAiBrD,EAC1B,EAWEE,UATF,SAAoBwC,GAClB,MAAoD,oBAA5C9E,OAAOtB,UAAU6C,SAASL,KAAK4D,IAC/BA,EAAS,GAAM,IAAMjG,EAAOW,eAAesF,EACrD,EAOEvC,UAAW,CACT4D,OAAQ,SAAUC,GAAO,OAAOA,GAAO,EAAI,KAAOA,EAAI7E,SAAS,GAAK,MAAQ6E,EAAI7E,SAAS,GAAGsE,MAAM,IAClGQ,MAAO,SAAUD,GAAO,OAAOA,GAAO,EAAI,KAAOA,EAAI7E,SAAS,GAAK,MAAQ6E,EAAI7E,SAAS,GAAGsE,MAAM,IACjGS,QAAS,SAAUF,GAAO,OAAOA,EAAI7E,SAAS,KAC9CgF,YAAa,SAAUH,GAAO,OAAOA,GAAO,EAAI,KAAOA,EAAI7E,SAAS,IAAIiF,cAAgB,MAAQJ,EAAI7E,SAAS,IAAIiF,cAAcX,MAAM,EAAG,GAE1IpD,aAAc,UACdE,aAAc,CACZwD,OAAQ,CAAC,EAAG,OACZE,MAAO,CAAC,EAAG,OACXC,QAAS,CAAC,GAAI,OACdC,YAAa,CAAC,GAAI,0CCzItB,IAAM1H,EAAS2C,IACTuB,EAAOC,IAEPyD,EAAqB,IAAIC,OAE7B,oIASIC,EAA6B,IAAID,OACrC,oDAoCF,IAAME,EAAyB,uBAsC/BC,EAAiB,IAAI9D,EAAK,0BAA2B,CACnDd,KAAM,SACNC,QAtEF,SAA2BE,GACzB,OAAa,OAATA,MAECqE,EAAmBK,KAAK1E,OAIzB6D,SAASc,WAAW3E,EAAM,MAIvBuE,EAA2BG,KAAK1E,IACzC,EA2DED,UAzDF,SAA6BC,GAC3B,IAAIsD,EAAQtD,EAAK4E,cACXrB,EAAoB,MAAbD,EAAM,IAAa,EAAK,EAMrC,MAJI,KAAK1D,QAAQ0D,EAAM,KAAO,IAC5BA,EAAQA,EAAMG,MAAM,IAGR,SAAVH,EACe,IAATC,EAAcjG,OAAOuH,kBAAoBvH,OAAOC,kBACrC,SAAV+F,EACFwB,IAEFvB,EAAOoB,WAAWrB,EAAO,GAClC,EA4CEpD,UATF,SAAkBwC,GAChB,MAAmD,oBAA3C9E,OAAOtB,UAAU6C,SAASL,KAAK4D,KAC/BA,EAAS,GAAM,GAAKjG,EAAOW,eAAesF,GACpD,EAOEvC,UAzCF,SAA6BuC,EAAQlC,GACnC,GAAIuE,MAAMrC,GACR,OAAQlC,GACN,IAAK,YAAa,MAAO,OACzB,IAAK,YAAa,MAAO,OACzB,IAAK,YAAa,MAAO,YAE7B,GAAWlD,OAAOuH,oBAAsBnC,EACtC,OAAQlC,GACN,IAAK,YAAa,MAAO,OACzB,IAAK,YAAa,MAAO,OACzB,IAAK,YAAa,MAAO,YAE7B,GAAWlD,OAAOC,oBAAsBmF,EACtC,OAAQlC,GACN,IAAK,YAAa,MAAO,QACzB,IAAK,YAAa,MAAO,QACzB,IAAK,YAAa,MAAO,gBAElB/D,EAAOW,eAAesF,GAC/B,MAAO,OAGT,IAAMsC,EAAMtC,EAAOvD,SAAS,IAK5B,OAAOqF,EAAuBE,KAAKM,GAAOA,EAAIC,QAAQ,IAAK,MAAQD,CACrE,EAaE3E,aAAc,4CCxFhB6E,EAAiB9F,KAAsB5B,OAAO,CAC5C6D,SAAU,CACRT,KACA0B,KACAC,KACA4C,uCCNJC,EAAiBhG,sCCNjB,IAAMuB,EAAOvB,IAEPiG,EAAmB,IAAIf,OAC3B,sDAIIgB,EAAwB,IAAIhB,OAChC,2LAuEFiB,EAAiB,IAAI5E,EAAK,8BAA+B,CACvDd,KAAM,SACNC,QA9DF,SAA+BE,GAC7B,OAAa,OAATA,IACgC,OAAhCqF,EAAiBG,KAAKxF,IACe,OAArCsF,EAAsBE,KAAKxF,GAEjC,EA0DED,UAxDF,SAAiCC,GAC/B,IAAIyF,EAAW,EACXC,EAAQ,KAERC,EAAQN,EAAiBG,KAAKxF,GAGlC,GAFc,OAAV2F,IAAgBA,EAAQL,EAAsBE,KAAKxF,IAEzC,OAAV2F,EAAgB,MAAM,IAAI9G,MAAM,sBAIpC,IAAM+G,GAASD,EAAM,GACfE,GAAUF,EAAM,GAAM,EACtBG,GAAQH,EAAM,GAEpB,IAAKA,EAAM,GACT,OAAO,IAAII,KAAKA,KAAKC,IAAIJ,EAAMC,EAAOC,IAKxC,IAAMG,GAASN,EAAM,GACfO,GAAWP,EAAM,GACjBQ,GAAWR,EAAM,GAEvB,GAAIA,EAAM,GAAI,CAEZ,IADAF,EAAWE,EAAM,GAAGlC,MAAM,EAAG,GACtBgC,EAAS1H,OAAS,GACvB0H,GAAY,IAEdA,GAAYA,CACd,CAIIE,EAAM,KAGRD,EAAmC,KAAjB,IAFDC,EAAM,OACJA,EAAM,KAAO,IAEf,MAAbA,EAAM,QAAqBD,IAGjC,IAAMU,EAAO,IAAIL,KAAKA,KAAKC,IAAIJ,EAAMC,EAAOC,EAAKG,EAAMC,EAAQC,EAAQV,IAIvE,OAFIC,GAAOU,EAAKC,QAAQD,EAAKE,UAAYZ,GAElCU,CACT,EAUEnG,WAAY8F,KACZ5F,UATF,SAAiCuC,GAC/B,OAAOA,EAAO6D,aAChB,oCC7EA,IAAM5F,EAAOvB,WAMboH,EAAiB,IAAI7F,EAAK,0BAA2B,CACnDd,KAAM,SACNC,QANF,SAA2BE,GACzB,MAAgB,OAATA,GAA0B,OAATA,CAC1B,oCCJA,IAAMW,EAAOvB,IAGPqH,EAAa,+EA8GnB1C,EAAiB,IAAIpD,EAAK,2BAA4B,CACpDd,KAAM,SACNC,QA9GF,SAA4BE,GAC1B,GAAa,OAATA,EAAe,OAAO,EAO1B,IALA,IAAI0G,EAAS,EACPjE,EAAMzC,EAAKjC,OACX2B,EAAM+G,EAGHE,EAAM,EAAGA,EAAMlE,EAAKkE,IAAO,CAClC,IAAMC,EAAOlH,EAAIE,QAAQI,EAAK6G,OAAOF,IAGrC,KAAIC,EAAO,IAAX,CAGA,GAAIA,EAAO,EAAG,OAAO,EAErBF,GAAU,CALK,CAMjB,CAGA,OAAQA,EAAS,GAAO,CAC1B,EAyFE3G,UAvFF,SAA8BC,GAS5B,IARA,IAAM8G,EAAQ9G,EAAKiF,QAAQ,WAAY,IACjCxC,EAAMqE,EAAM/I,OACZ2B,EAAM+G,EACRM,EAAO,EACL7J,EAAS,GAINyJ,EAAM,EAAGA,EAAMlE,EAAKkE,IACtBA,EAAM,GAAM,GAAMA,IACrBzJ,EAAOqE,KAAMwF,GAAQ,GAAM,KAC3B7J,EAAOqE,KAAMwF,GAAQ,EAAK,KAC1B7J,EAAOqE,KAAY,IAAPwF,IAGdA,EAAQA,GAAQ,EAAKrH,EAAIE,QAAQkH,EAAMD,OAAOF,IAKhD,IAAMK,EAAYvE,EAAM,EAAK,EAa7B,OAXiB,IAAbuE,GACF9J,EAAOqE,KAAMwF,GAAQ,GAAM,KAC3B7J,EAAOqE,KAAMwF,GAAQ,EAAK,KAC1B7J,EAAOqE,KAAY,IAAPwF,IACU,KAAbC,GACT9J,EAAOqE,KAAMwF,GAAQ,GAAM,KAC3B7J,EAAOqE,KAAMwF,GAAQ,EAAK,MACJ,KAAbC,GACT9J,EAAOqE,KAAMwF,GAAQ,EAAK,KAGrB,IAAIE,WAAW/J,EACxB,EAqDEgD,UARF,SAAmB8D,GACjB,MAA+C,wBAAxCpG,OAAOtB,UAAU6C,SAASL,KAAKkF,EACxC,EAOE7D,UApDF,SAA8BuC,GAQ5B,IAPA,IAAIxF,EAAS,GACT6J,EAAO,EACLtE,EAAMC,EAAO3E,OACb2B,EAAM+G,EAIHE,EAAM,EAAGA,EAAMlE,EAAKkE,IACtBA,EAAM,GAAM,GAAMA,IACrBzJ,GAAUwC,EAAKqH,GAAQ,GAAM,IAC7B7J,GAAUwC,EAAKqH,GAAQ,GAAM,IAC7B7J,GAAUwC,EAAKqH,GAAQ,EAAK,IAC5B7J,GAAUwC,EAAW,GAAPqH,IAGhBA,GAAQA,GAAQ,GAAKrE,EAAOiE,GAK9B,IAAMO,EAAOzE,EAAM,EAmBnB,OAjBa,IAATyE,GACFhK,GAAUwC,EAAKqH,GAAQ,GAAM,IAC7B7J,GAAUwC,EAAKqH,GAAQ,GAAM,IAC7B7J,GAAUwC,EAAKqH,GAAQ,EAAK,IAC5B7J,GAAUwC,EAAW,GAAPqH,IACI,IAATG,GACThK,GAAUwC,EAAKqH,GAAQ,GAAM,IAC7B7J,GAAUwC,EAAKqH,GAAQ,EAAK,IAC5B7J,GAAUwC,EAAKqH,GAAQ,EAAK,IAC5B7J,GAAUwC,EAAI,KACI,IAATwH,IACThK,GAAUwC,EAAKqH,GAAQ,EAAK,IAC5B7J,GAAUwC,EAAKqH,GAAQ,EAAK,IAC5B7J,GAAUwC,EAAI,IACdxC,GAAUwC,EAAI,KAGTxC,CACT,oCC3GA,IAAMyD,EAAOvB,IAEP+H,EAAkBvJ,OAAOtB,UAAU8K,eACnCC,EAAYzJ,OAAOtB,UAAU6C,gBAmCnCmI,EAAiB,IAAI3G,EAAK,yBAA0B,CAClDd,KAAM,WACNC,QAnCF,SAA0BE,GACxB,GAAa,OAATA,EAAe,OAAO,EAK1B,IAHA,IAAMuH,EAAa,CAAA,EACb7E,EAAS1C,EAENlC,EAAQ,EAAGC,EAAS2E,EAAO3E,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CACtE,IAAM0J,EAAO9E,EAAO5E,GAChB2J,GAAa,EAEjB,GAA6B,oBAAzBJ,EAAUvI,KAAK0I,GAA6B,OAAO,EAEvD,IAAIE,OAAO,EACX,IAAKA,KAAWF,EACd,GAAIL,EAAgBrI,KAAK0I,EAAME,GAAU,CACvC,GAAKD,EACA,OAAO,EADKA,GAAa,CAEhC,CAGF,IAAKA,EAAY,OAAO,EAExB,GAAIN,EAAgBrI,KAAKyI,EAAYG,GAAU,OAAO,EACtD9J,OAAO+J,eAAeJ,EAAYG,EAAS,CAAEpE,OAAO,GACtD,CAEA,OAAO,CACT,EASEvD,UAPF,SAA4BC,GAC1B,OAAgB,OAATA,EAAgBA,EAAO,EAChC,oCCpCA,IAAMW,EAAOvB,IAEPiI,EAAYzJ,OAAOtB,UAAU6C,gBAyCnCyI,EAAiB,IAAIjH,EAAK,0BAA2B,CACnDd,KAAM,WACNC,QAzCF,SAA2BE,GACzB,GAAa,OAATA,EAAe,OAAO,EAM1B,IAJA,IAAM0C,EAAS1C,EAET9C,EAAS,IAAIL,MAAM6F,EAAO3E,QAEvBD,EAAQ,EAAGC,EAAS2E,EAAO3E,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CACtE,IAAM0J,EAAO9E,EAAO5E,GAEpB,GAA6B,oBAAzBuJ,EAAUvI,KAAK0I,GAA6B,OAAO,EAEvD,IAAM3J,EAAOD,OAAOC,KAAK2J,GAEzB,GAAoB,IAAhB3J,EAAKE,OAAc,OAAO,EAE9Bb,EAAOY,GAAS,CAACD,EAAK,GAAI2J,EAAK3J,EAAK,IACtC,CAEA,OAAO,CACT,EAsBEkC,UApBF,SAA6BC,GAC3B,GAAa,OAATA,EAAe,MAAO,GAK1B,IAHA,IAAM0C,EAAS1C,EACT9C,EAAS,IAAIL,MAAM6F,EAAO3E,QAEvBD,EAAQ,EAAGC,EAAS2E,EAAO3E,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CACtE,IAAM0J,EAAO9E,EAAO5E,GAEdD,EAAOD,OAAOC,KAAK2J,GAEzBtK,EAAOY,GAAS,CAACD,EAAK,GAAI2J,EAAK3J,EAAK,IACtC,CAEA,OAAOX,CACT,oCCzCA,IAAMyD,EAAOvB,IAEP+H,EAAkBvJ,OAAOtB,UAAU8K,sBAoBzCS,EAAiB,IAAIlH,EAAK,wBAAyB,CACjDd,KAAM,UACNC,QApBF,SAAyBE,GACvB,GAAa,OAATA,EAAe,OAAO,EAE1B,IAAM0C,EAAS1C,EAEf,IAAA,IAAWhC,KAAO0E,EAChB,GAAIyE,EAAgBrI,KAAK4D,EAAQ1E,IACX,OAAhB0E,EAAO1E,GAAe,OAAO,EAIrC,OAAO,CACT,EASE+B,UAPF,SAA2BC,GACzB,OAAgB,OAATA,EAAgBA,EAAO,CAAA,CAChC,kCCdA8H,EAAiB1I,KAAkB5B,OAAO,CACxC6D,SAAU,CACRT,KACA0B,MAEFhB,SAAU,CACRiB,KACA4C,KACA4C,KACAC,qCCjBQ,SAAA/L,EAAAC,GAAA,OAAAD,EAAA,mBAAAE,QAAA,iBAAAA,OAAAC,SAAA,SAAAF,GAAA,cAAAA,GAAA,SAAAA,GAAA,OAAAA,GAAA,mBAAAC,QAAAD,EAAAG,cAAAF,QAAAD,IAAAC,OAAAG,UAAA,gBAAAJ,CAAA,GAAAA,EAAA,KAEZ,IAAMO,EAAS2C,IACTR,EAAgBgC,IAChBqH,+BCFN,IAAMxL,EAAS2C,IAGf,SAAS8I,EAASC,EAAQC,EAAWC,EAASC,EAAUC,GACtD,IAAIC,EAAO,GACPtB,EAAO,GACLuB,EAAgBC,KAAKC,MAAMJ,EAAgB,GAAK,EAYtD,OAVID,EAAWF,EAAYK,IAEzBL,EAAYE,EAAWG,GADvBD,EAAO,SACqCzK,QAG1CsK,EAAUC,EAAWG,IAEvBJ,EAAUC,EAAWG,GADrBvB,EAAO,QACmCnJ,QAGrC,CACLoE,IAAKqG,EAAOL,EAAO1E,MAAM2E,EAAWC,GAASpD,QAAQ,MAAO,KAAOiC,EACnE0B,IAAKN,EAAWF,EAAYI,EAAKzK,OAErC,CAEA,SAAS8K,EAAU7L,EAAQyF,GACzB,OAAOhG,EAAOM,OAAO,IAAK0F,EAAMzF,EAAOe,QAAUf,CACnD,QAmEA2B,EAjEA,SAAsBJ,EAAMkB,GAG1B,GAFAA,EAAU7B,OAAOsB,OAAOO,GAAW,OAE9BlB,EAAK4J,OAAQ,OAAO,KAEpB1I,EAAQqJ,YAAWrJ,EAAQqJ,UAAY,IACd,iBAAnBrJ,EAAQsJ,WAA6BA,OAAS,GACtB,iBAAxBtJ,EAAQuJ,gBAAkCA,YAAc,GACjC,iBAAvBvJ,EAAQwJ,eAAiCA,WAAa,GAQjE,IANA,IAGItD,EAHEuD,EAAK,eACLC,EAAa,CAAC,GACdC,EAAW,GAEbC,GAAc,EAEV1D,EAAQuD,EAAG1D,KAAKjH,EAAK4J,SAC3BiB,EAAS7H,KAAKoE,EAAM7H,OACpBqL,EAAW5H,KAAKoE,EAAM7H,MAAQ6H,EAAM,GAAG5H,QAEnCQ,EAAK+J,UAAY3C,EAAM7H,OAASuL,EAAc,IAChDA,EAAcF,EAAWpL,OAAS,GAIlCsL,EAAc,IAAGA,EAAcF,EAAWpL,OAAS,GAMvD,IAJA,IAAIb,EAAS,GACPoM,EAAeZ,KAAKa,IAAIhL,EAAKE,KAAOgB,EAAQwJ,WAAYG,EAASrL,QAAQoB,WAAWpB,OACpFwK,EAAgB9I,EAAQqJ,WAAarJ,EAAQsJ,OAASO,EAAe,GAElEE,EAAI,EAAGA,GAAK/J,EAAQuJ,eACvBK,EAAcG,EAAI,GADkBA,IAAK,CAE7C,IAAM/K,EAAOyJ,EACX3J,EAAK4J,OACLgB,EAAWE,EAAcG,GACzBJ,EAASC,EAAcG,GACvBjL,EAAK+J,UAAYa,EAAWE,GAAeF,EAAWE,EAAcG,IACpEjB,GAEFrL,EAAST,EAAOM,OAAO,IAAK0C,EAAQsJ,QAAUF,GAAUtK,EAAKE,KAAO+K,EAAI,GAAGrK,WAAYmK,GACrF,MAAQ7K,EAAK0D,IAAM,KAAOjF,CAC9B,CAEA,IAAMuB,EAAOyJ,EAAQ3J,EAAK4J,OAAQgB,EAAWE,GAAcD,EAASC,GAAc9K,EAAK+J,SAAUC,GACjGrL,GAAUT,EAAOM,OAAO,IAAK0C,EAAQsJ,QAAUF,GAAUtK,EAAKE,KAAO,GAAGU,WAAYmK,GAClF,MAAQ7K,EAAK0D,IAAM,KACrBjF,GAAUT,EAAOM,OAAO,IAAK0C,EAAQsJ,OAASO,EAAe,EAAI7K,EAAKmK,KAAO,MAE7E,IAAA,IAASY,EAAI,EAAGA,GAAK/J,EAAQwJ,cACvBI,EAAcG,GAAKJ,EAASrL,QADOyL,IAAK,CAE5C,IAAM/K,EAAOyJ,EACX3J,EAAK4J,OACLgB,EAAWE,EAAcG,GACzBJ,EAASC,EAAcG,GACvBjL,EAAK+J,UAAYa,EAAWE,GAAeF,EAAWE,EAAcG,IACpEjB,GAEFrL,GAAUT,EAAOM,OAAO,IAAK0C,EAAQsJ,QAAUF,GAAUtK,EAAKE,KAAO+K,EAAI,GAAGrK,WAAYmK,GACtF,MAAQ7K,EAAK0D,IAAM,IACvB,CAEA,OAAOjF,EAAO+H,QAAQ,MAAO,GAC/B,EDzFoB3C,GACdmH,EAAiBlH,KAEjB4E,EAAkBvJ,OAAOtB,UAAU8K,eAYnCsC,EAAwB,sIACxBC,EAAgC,qBAEhCC,EAA0B,YAE1BC,EAAqB,6BAErBC,EAAkB,yEAExB,SAASC,EAAQ/F,GAAO,OAAOpG,OAAOtB,UAAU6C,SAASL,KAAKkF,EAAK,CAEnE,SAASgG,EAAO9G,GACd,OAAc,KAANA,GAA8B,KAANA,CAClC,CAEA,SAAS+G,EAAc/G,GACrB,OAAc,IAANA,GAA+B,KAANA,CACnC,CAEA,SAASgH,EAAWhH,GAClB,OAAc,IAANA,GACM,KAANA,GACM,KAANA,GACM,KAANA,CACV,CAEA,SAASiH,EAAiBjH,GACxB,OAAa,KAANA,GACM,KAANA,GACM,KAANA,GACM,MAANA,GACM,MAANA,CACT,CAEA,SAASkH,EAAalH,GACpB,GAAKA,GAAK,IAAiBA,GAAK,GAC9B,OAAOA,EAAI,GAGb,IAAMmH,EAAS,GAAJnH,EAEX,OAAKmH,GAAM,IAAiBA,GAAM,IACzBA,EAAK,GAAO,IAGd,CACT,CAEA,SAASC,EAAepH,GACtB,OAAU,MAANA,EAA4B,EACtB,MAANA,EAA4B,EACtB,KAANA,EAA4B,EACzB,CACT,CAEA,SAASqH,EAAiBrH,GACxB,OAAKA,GAAK,IAAiBA,GAAK,GACvBA,EAAI,IAGN,CACT,CAEA,SAASsH,EAAsBtH,GAC7B,OAAQA,GACN,KAAK,GAAa,MAAO,KACzB,KAAK,GAAa,MAAO,IACzB,KAAK,GAAa,MAAO,KACzB,KAAK,IACL,KAAK,EAAe,MAAO,KAC3B,KAAK,IAAa,MAAO,KACzB,KAAK,IAAa,MAAO,KACzB,KAAK,IAAa,MAAO,KACzB,KAAK,IAAa,MAAO,KACzB,KAAK,IAAa,MAAO,IACzB,KAAK,GAAiB,MAAO,IAC7B,KAAK,GAAa,MAAO,IACzB,KAAK,GAAa,MAAO,IACzB,KAAK,GAAa,MAAO,KACzB,KAAK,GAAa,MAAO,IACzB,KAAK,GAAa,MAAO,IACzB,KAAK,GAAa,MAAO,SACzB,KAAK,GAAa,MAAO,SACzB,QAAS,MAAO,GAEpB,CAEA,SAASuH,EAAmBvH,GAC1B,OAAIA,GAAK,MACAxC,OAAOgK,aAAaxH,GAItBxC,OAAOgK,aACa,OAAvBxH,EAAI,OAAa,IACS,OAA1BA,EAAI,MAAY,MAEtB,CAIA,SAASyH,EAAajI,EAAQ1E,EAAKsF,GAErB,cAARtF,EACFJ,OAAO+J,eAAejF,EAAQ1E,EAAK,CACjC4M,cAAc,EACdC,YAAY,EACZC,UAAU,EACVxH,UAGFZ,EAAO1E,GAAOsF,CAElB,CAIA,IAFA,IAAMyH,EAAoB,IAAIlO,MAAM,KAC9BmO,EAAkB,IAAInO,MAAM,KACzB2M,EAAI,EAAGA,EAAI,IAAKA,IACvBuB,EAAkBvB,GAAKgB,EAAqBhB,GAAK,EAAI,EACrDwB,EAAgBxB,GAAKgB,EAAqBhB,GAG5C,SAASyB,EAAOnE,EAAOrH,GACrBV,KAAK+H,MAAQA,EAEb/H,KAAKmM,SAAWzL,EAAkB,UAAK,KACvCV,KAAK+B,OAASrB,EAAgB,QAAKgK,EACnC1K,KAAKoM,UAAY1L,EAAmB,WAAK,KAGzCV,KAAKqM,OAAS3L,EAAgB,SAAK,EAEnCV,KAAKmG,KAAOzF,EAAc,OAAK,EAC/BV,KAAKsM,SAAW5L,EAAkB,UAAK,KACvCV,KAAKuM,SAA0C,iBAAxB7L,EAAkB,SAAiBA,EAAkB,SAAI,IAChFV,KAAKwM,kBAA4D,iBAAjC9L,EAA2B,kBAAiBA,EAA2B,kBAAI,IAE3GV,KAAKyM,cAAgBzM,KAAK+B,OAAOY,iBACjC3C,KAAK0M,QAAU1M,KAAK+B,OAAOc,gBAE3B7C,KAAKhB,OAAS+I,EAAM/I,OACpBgB,KAAKuJ,SAAW,EAChBvJ,KAAKN,KAAO,EACZM,KAAKqJ,UAAY,EACjBrJ,KAAK2M,WAAa,EAClB3M,KAAK4M,MAAQ,EACb5M,KAAK6M,eAAiB,EAItB7M,KAAK8M,gBAAiB,EAEtB9M,KAAK+M,UAAY,GACjB/M,KAAKgN,sBAAwB,EAW/B,CAEA,SAASC,EAAeC,EAAO5N,GAC7B,IAAME,EAAO,CACXC,KAAMyN,EAAMf,SACZ/C,OAAQ8D,EAAMnF,MAAMrD,MAAM,GAAG,GAC7B6E,SAAU2D,EAAM3D,SAChB7J,KAAMwN,EAAMxN,KACZC,OAAQuN,EAAM3D,SAAW2D,EAAM7D,WAKjC,OAFA7J,EAAKI,QAAUsJ,EAAY1J,GAEpB,IAAIK,EAAcP,EAASE,EACpC,CAEA,SAAS2N,EAAYD,EAAO5N,GAC1B,MAAM2N,EAAcC,EAAO5N,EAC7B,CAEA,SAAS8N,EAAcF,EAAO5N,GACxB4N,EAAMd,WACRc,EAAMd,UAAUrM,KAAK,KAAMkN,EAAcC,EAAO5N,GAEpD,CAEA,SAAS+N,EAAaH,EAAOzN,EAAM8E,GACjC,IAAM+I,EAAeJ,EAAMF,sBAE3B,GAA4B,IAAxBM,EAAatO,OAAc,CAC7B,IAAMuO,EAAcD,EAAaA,EAAatO,OAAS,GAElDoJ,EAAgBrI,KAAKwN,EAAa9N,KACrC8N,EAAY9N,GAAQ,CAClB+N,QAASpF,EAAgBrI,KAAKmN,EAAMO,UAAWhO,GAC/C8E,MAAO2I,EAAMO,UAAUhO,IAG7B,CAEAyN,EAAMO,UAAUhO,GAAQ8E,CAC1B,CAuCA,SAASmJ,EAAeR,GACtB,MAAO,CACL3D,SAAU2D,EAAM3D,SAChB7J,KAAMwN,EAAMxN,KACZ2J,UAAW6D,EAAM7D,UACjBsD,WAAYO,EAAMP,WAClBG,eAAgBI,EAAMJ,eACtBrM,IAAKyM,EAAMzM,IACXkN,OAAQT,EAAMS,OACd7M,KAAMoM,EAAMpM,KACZ3C,OAAQ+O,EAAM/O,OAElB,CAEA,SAASyP,EAAcV,EAAOW,GAC5BX,EAAM3D,SAAWsE,EAAStE,SAC1B2D,EAAMxN,KAAOmO,EAASnO,KACtBwN,EAAM7D,UAAYwE,EAASxE,UAC3B6D,EAAMP,WAAakB,EAASlB,WAC5BO,EAAMJ,eAAiBe,EAASf,eAChCI,EAAMzM,IAAMoN,EAASpN,IACrByM,EAAMS,OAASE,EAASF,OACxBT,EAAMpM,KAAO+M,EAAS/M,KACtBoM,EAAM/O,OAAS0P,EAAS1P,MAC1B,CAEA,IAAM2P,EAAoB,CAExBC,KAAM,SAA8Bb,EAAOzN,EAAMuO,GACzB,OAAlBd,EAAMe,SACRd,EAAWD,EAAO,kCAGA,IAAhBc,EAAKhP,QACPmO,EAAWD,EAAO,+CAGpB,IAAMtG,EAAQ,uBAAuBH,KAAKuH,EAAK,IAEjC,OAAVpH,GACFuG,EAAWD,EAAO,6CAGpB,IAAMgB,EAAQvJ,SAASiC,EAAM,GAAI,IAC3BuH,EAAQxJ,SAASiC,EAAM,GAAI,IAEnB,IAAVsH,GACFf,EAAWD,EAAO,6CAGpBA,EAAMe,QAAUD,EAAK,GACrBd,EAAMkB,gBAAmBD,EAAQ,EAEnB,IAAVA,GAAyB,IAAVA,GACjBf,EAAaF,EAAO,6CAIxBmB,IAAK,SAA6BnB,EAAOzN,EAAMuO,GAC7C,IAAIM,EAEgB,IAAhBN,EAAKhP,QACPmO,EAAWD,EAAO,+CAGpB,IAAMqB,EAASP,EAAK,GACpBM,EAASN,EAAK,GAETlD,EAAmBnF,KAAK4I,IAC3BpB,EAAWD,EAAO,+DAGhB9E,EAAgBrI,KAAKmN,EAAMsB,OAAQD,IACrCpB,EAAWD,EAAO,8CAAgDqB,EAAS,gBAGxExD,EAAgBpF,KAAK2I,IACxBnB,EAAWD,EAAO,gEAGpB,IACEoB,EAASG,mBAAmBH,SACrBI,GACPvB,EAAWD,EAAO,4BAA8BoB,EAClD,CAEApB,EAAMsB,OAAOD,GAAUD,CACzB,GAGF,SAASK,EAAgBzB,EAAO0B,EAAOC,EAAKC,GAC1C,GAAIF,EAAQC,EAAK,CACf,IAAME,EAAU7B,EAAMnF,MAAMrD,MAAMkK,EAAOC,GAEzC,GAAIC,EACF,IAAA,IAASE,EAAY,EAAGC,EAAUF,EAAQ/P,OAAQgQ,EAAYC,EAASD,GAAa,EAAG,CACrF,IAAME,EAAaH,EAAQhK,WAAWiK,GACjB,IAAfE,GACCA,GAAc,IAAQA,GAAc,SACzC/B,EAAWD,EAAO,gCAEtB,MACSvC,EAAsBhF,KAAKoJ,IACpC5B,EAAWD,EAAO,gDAGpBA,EAAM/O,QAAU4Q,CAClB,CACF,CAEA,SAASI,EAAejC,EAAOkC,EAAazQ,EAAQ0Q,GAC7C3R,EAAOC,SAASgB,IACnBwO,EAAWD,EAAO,qEAKpB,IAFA,IAAMtO,EAAaC,OAAOC,KAAKH,GAEtBI,EAAQ,EAAGuQ,EAAW1Q,EAAWI,OAAQD,EAAQuQ,EAAUvQ,GAAS,EAAG,CAC9E,IAAME,EAAML,EAAWG,IAES,IAA5BmO,EAAMV,qBAA8BU,EAAML,eAAiBK,EAAMV,mBACnEW,EAAWD,EAAO,0CAA4CA,EAAMV,kBAAoB,KAGrFpE,EAAgBrI,KAAKqP,EAAanQ,KACrC2M,EAAYwD,EAAanQ,EAAKN,EAAOM,IACrCoQ,EAAgBpQ,IAAO,EAE3B,CACF,CAEA,SAASsQ,EAAkBrC,EAAO6B,EAASM,EAAiBG,EAAQC,EAASC,EAC3EC,EAAWC,EAAgBC,GAI3B,GAAI/R,MAAMC,QAAQ0R,GAGhB,IAAA,IAAS1Q,EAAQ,EAAGuQ,GAFpBG,EAAU3R,MAAMP,UAAUmH,MAAM3E,KAAK0P,IAEEzQ,OAAQD,EAAQuQ,EAAUvQ,GAAS,EACpEjB,MAAMC,QAAQ0R,EAAQ1Q,KACxBoO,EAAWD,EAAO,+CAGG,WAAnBhQ,EAAOuS,IAAmD,oBAA3BzE,EAAOyE,EAAQ1Q,MAChD0Q,EAAQ1Q,GAAS,mBAkBvB,GAVuB,WAAnB7B,EAAOuS,IAA4C,oBAApBzE,EAAOyE,KACxCA,EAAU,mBAGZA,EAAU9N,OAAO8N,GAED,OAAZV,IACFA,EAAU,CAAA,GAGG,4BAAXS,EACF,GAAI1R,MAAMC,QAAQ2R,GAChB,IAAA,IAAS3Q,EAAQ,EAAGuQ,EAAWI,EAAU1Q,OAAQD,EAAQuQ,EAAUvQ,GAAS,EAC1EoQ,EAAcjC,EAAO6B,EAASW,EAAU3Q,GAAQsQ,QAGlDF,EAAcjC,EAAO6B,EAASW,EAAWL,QAGtCnC,EAAM/G,MACNiC,EAAgBrI,KAAKsP,EAAiBI,KACvCrH,EAAgBrI,KAAKgP,EAASU,KAChCvC,EAAMxN,KAAOiQ,GAAazC,EAAMxN,KAChCwN,EAAM7D,UAAYuG,GAAkB1C,EAAM7D,UAC1C6D,EAAM3D,SAAWsG,GAAY3C,EAAM3D,SACnC4D,EAAWD,EAAO,2BAGpBtB,EAAYmD,EAASU,EAASC,UACvBL,EAAgBI,GAGzB,OAAOV,CACT,CAEA,SAASe,EAAe5C,GACtB,IAAMzI,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAE7B,KAAP9E,EACFyI,EAAM3D,WACU,KAAP9E,GACTyI,EAAM3D,WACyC,KAA3C2D,EAAMnF,MAAMhD,WAAWmI,EAAM3D,WAC/B2D,EAAM3D,YAGR4D,EAAWD,EAAO,4BAGpBA,EAAMxN,MAAQ,EACdwN,EAAM7D,UAAY6D,EAAM3D,SACxB2D,EAAMJ,gBAAiB,CACzB,CAEA,SAASiD,EAAqB7C,EAAO8C,EAAeC,GAIlD,IAHA,IAAIC,EAAa,EACbzL,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAExB,IAAP9E,GAAU,CACf,KAAOyG,EAAazG,IACP,IAAPA,IAAiD,IAAzByI,EAAMJ,iBAChCI,EAAMJ,eAAiBI,EAAM3D,UAE/B9E,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGtC,GAAIyG,GAAwB,KAAPvL,EACnB,GACEA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,gBACtB,KAAP9E,GAA8B,KAAPA,GAA8B,IAAPA,GAGzD,IAAIwG,EAAMxG,GAYR,MALA,IANAqL,EAAc5C,GAEdzI,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAClC2G,IACAhD,EAAMP,WAAa,EAEL,KAAPlI,GACLyI,EAAMP,aACNlI,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,SAK1C,CAMA,OAJoB,IAAhB0G,GAAqC,IAAfC,GAAoBhD,EAAMP,WAAasD,GAC/D7C,EAAaF,EAAO,yBAGfgD,CACT,CAEA,SAASC,EAAuBjD,GAC9B,IAAI8B,EAAY9B,EAAM3D,SAClB9E,EAAKyI,EAAMnF,MAAMhD,WAAWiK,GAIhC,QAAY,KAAPvK,GAA6B,KAAPA,GACvBA,IAAOyI,EAAMnF,MAAMhD,WAAWiK,EAAY,IAC1CvK,IAAOyI,EAAMnF,MAAMhD,WAAWiK,EAAY,KAC5CA,GAAa,EAIF,KAFXvK,EAAKyI,EAAMnF,MAAMhD,WAAWiK,MAEZ7D,EAAU1G,IAM9B,CAEA,SAAS2L,EAAkBlD,EAAOhP,GAClB,IAAVA,EACFgP,EAAM/O,QAAU,IACPD,EAAQ,IACjBgP,EAAM/O,QAAUT,EAAOM,OAAO,KAAME,EAAQ,GAEhD,CAwdA,SAASmS,EAAmBnD,EAAOoD,GACjC,IAAMC,EAAOrD,EAAMzM,IACb+P,EAAUtD,EAAMS,OAChBoB,EAAU,GACZ0B,GAAW,EAIf,IAA6B,IAAzBvD,EAAMJ,eAAuB,OAAO,EAEnB,OAAjBI,EAAMS,QACRN,EAAYH,EAAOA,EAAMS,OAAQoB,GAKnC,IAFA,IAAItK,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAExB,IAAP9E,KACwB,IAAzByI,EAAMJ,iBACRI,EAAM3D,SAAW2D,EAAMJ,eACvBK,EAAWD,EAAO,mDAGT,KAAPzI,IANW,CAYf,IAAK0G,EAFa+B,EAAMnF,MAAMhD,WAAWmI,EAAM3D,SAAW,IAGxD,MAMF,GAHAkH,GAAW,EACXvD,EAAM3D,WAEFwG,EAAoB7C,GAAO,GAAM,IAC/BA,EAAMP,YAAc2D,EACtBvB,EAAQvM,KAAK,MACbiC,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,cAHtC,CAQA,IAAMmH,EAAQxD,EAAMxN,KAOpB,GANAiR,EAAYzD,EAAOoD,EAnhCE,GAmhC4B,GAAO,GACxDvB,EAAQvM,KAAK0K,EAAM/O,QACnB4R,EAAoB7C,GAAO,GAAM,GAEjCzI,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,WAE7B2D,EAAMxN,OAASgR,GAASxD,EAAMP,WAAa2D,IAAuB,IAAP7L,EAC9D0I,EAAWD,EAAO,4CACpB,GAAWA,EAAMP,WAAa2D,EAC5B,KAZF,CAcF,CAEA,QAAIG,IACFvD,EAAMzM,IAAM8P,EACZrD,EAAMS,OAAS6C,EACftD,EAAMpM,KAAO,WACboM,EAAM/O,OAAS4Q,GACR,EAGX,CAEA,SAAS6B,EAAkB1D,EAAOoD,EAAYO,GAC5C,IAAIC,EACAC,EACAC,EACAC,EACEV,EAAOrD,EAAMzM,IACb+P,EAAUtD,EAAMS,OAChBoB,EAAU,CAAA,EACVM,EAAkBxQ,OAAOsB,OAAO,MAClCqP,EAAS,KACTC,EAAU,KACVC,EAAY,KACZwB,GAAgB,EAChBT,GAAW,EAIf,IAA6B,IAAzBvD,EAAMJ,eAAuB,OAAO,EAEnB,OAAjBI,EAAMS,QACRN,EAAYH,EAAOA,EAAMS,OAAQoB,GAKnC,IAFA,IAAItK,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAExB,IAAP9E,GAAU,CACVyM,IAA0C,IAAzBhE,EAAMJ,iBAC1BI,EAAM3D,SAAW2D,EAAMJ,eACvBK,EAAWD,EAAO,mDAGpB,IAAMiE,EAAYjE,EAAMnF,MAAMhD,WAAWmI,EAAM3D,SAAW,GACpDmH,EAAQxD,EAAMxN,KAMpB,GAAY,KAAP+E,GAA6B,KAAPA,IAAuB0G,EAAUgG,GAwBrD,CAKL,GAJAJ,EAAW7D,EAAMxN,KACjBsR,EAAgB9D,EAAM7D,UACtB4H,EAAU/D,EAAM3D,UAEXoH,EAAYzD,EAAO2D,EA9mCL,GA8mCmC,GAAO,GAG3D,MAGF,GAAI3D,EAAMxN,OAASgR,EAAO,CAGxB,IAFAjM,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAE3B2B,EAAazG,IAClBA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGtC,GAAW,KAAP9E,EAGG0G,EAFL1G,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,YAGlC4D,EAAWD,EAAO,2FAGhBgE,IACF3B,EAAiBrC,EAAO6B,EAASM,EAAiBG,EAAQC,EAAS,KAAMsB,EAAUC,EAAeC,GAClGzB,EAASC,EAAUC,EAAY,MAGjCe,GAAW,EACXS,GAAgB,EAChBJ,GAAe,EACftB,EAAStC,EAAMzM,IACfgP,EAAUvC,EAAM/O,gBACPsS,EAKT,OAFAvD,EAAMzM,IAAM8P,EACZrD,EAAMS,OAAS6C,GACR,EAJPrD,EAAWD,EAAO,2DAKpB,WACSuD,EAKT,OAFAvD,EAAMzM,IAAM8P,EACZrD,EAAMS,OAAS6C,GACR,EAJPrD,EAAWD,EAAO,iFAKpB,CACF,MAxEa,KAAPzI,GACEyM,IACF3B,EAAiBrC,EAAO6B,EAASM,EAAiBG,EAAQC,EAAS,KAAMsB,EAAUC,EAAeC,GAClGzB,EAASC,EAAUC,EAAY,MAGjCe,GAAW,EACXS,GAAgB,EAChBJ,GAAe,GACNI,GAETA,GAAgB,EAChBJ,GAAe,GAEf3D,EAAWD,EAAO,qGAGpBA,EAAM3D,UAAY,EAClB9E,EAAK0M,EAmFP,IAxBIjE,EAAMxN,OAASgR,GAASxD,EAAMP,WAAa2D,KACzCY,IACFH,EAAW7D,EAAMxN,KACjBsR,EAAgB9D,EAAM7D,UACtB4H,EAAU/D,EAAM3D,UAGdoH,EAAYzD,EAAOoD,EApqCH,GAoqCkC,EAAMQ,KACtDI,EACFzB,EAAUvC,EAAM/O,OAEhBuR,EAAYxC,EAAM/O,QAIjB+S,IACH3B,EAAiBrC,EAAO6B,EAASM,EAAiBG,EAAQC,EAASC,EAAWqB,EAAUC,EAAeC,GACvGzB,EAASC,EAAUC,EAAY,MAGjCK,EAAoB7C,GAAO,GAAM,GACjCzI,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,YAG/B2D,EAAMxN,OAASgR,GAASxD,EAAMP,WAAa2D,IAAuB,IAAP7L,EAC9D0I,EAAWD,EAAO,2CACpB,GAAWA,EAAMP,WAAa2D,EAC5B,KAEJ,CAmBA,OAZIY,GACF3B,EAAiBrC,EAAO6B,EAASM,EAAiBG,EAAQC,EAAS,KAAMsB,EAAUC,EAAeC,GAIhGR,IACFvD,EAAMzM,IAAM8P,EACZrD,EAAMS,OAAS6C,EACftD,EAAMpM,KAAO,UACboM,EAAM/O,OAAS4Q,GAGV0B,CACT,CAEA,SAASW,EAAiBlE,GACxB,IAEImE,EACAC,EAHAC,GAAa,EACbC,GAAU,EAIV/M,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAEtC,GAAW,KAAP9E,EAAoB,OAAO,EAEb,OAAdyI,EAAMzM,KACR0M,EAAWD,EAAO,iCAKT,MAFXzI,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,YAGlCgI,GAAa,EACb9M,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,WACpB,KAAP9E,GACT+M,GAAU,EACVH,EAAY,KACZ5M,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,WAEpC8H,EAAY,IAGd,IAAIrC,EAAY9B,EAAM3D,SAEtB,GAAIgI,EAAY,CACd,GAAK9M,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,gBAC3B,IAAP9E,GAAmB,KAAPA,GAEfyI,EAAM3D,SAAW2D,EAAMlO,QACzBsS,EAAUpE,EAAMnF,MAAMrD,MAAMsK,EAAW9B,EAAM3D,UAC7C9E,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,WAEpC4D,EAAWD,EAAO,qDAEtB,KAAO,CACL,KAAc,IAAPzI,IAAa0G,EAAU1G,IACjB,KAAPA,IACG+M,EAUHrE,EAAWD,EAAO,gDATlBmE,EAAYnE,EAAMnF,MAAMrD,MAAMsK,EAAY,EAAG9B,EAAM3D,SAAW,GAEzDuB,EAAmBnF,KAAK0L,IAC3BlE,EAAWD,EAAO,mDAGpBsE,GAAU,EACVxC,EAAY9B,EAAM3D,SAAW,IAMjC9E,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGtC+H,EAAUpE,EAAMnF,MAAMrD,MAAMsK,EAAW9B,EAAM3D,UAEzCsB,EAAwBlF,KAAK2L,IAC/BnE,EAAWD,EAAO,sDAEtB,CAEIoE,IAAYvG,EAAgBpF,KAAK2L,IACnCnE,EAAWD,EAAO,4CAA8CoE,GAGlE,IACEA,EAAU7C,mBAAmB6C,SACtB5C,GACPvB,EAAWD,EAAO,0BAA4BoE,EAChD,CAcA,OAZIC,EACFrE,EAAMzM,IAAM6Q,EACHlJ,EAAgBrI,KAAKmN,EAAMsB,OAAQ6C,GAC5CnE,EAAMzM,IAAMyM,EAAMsB,OAAO6C,GAAaC,EACf,MAAdD,EACTnE,EAAMzM,IAAM,IAAM6Q,EACK,OAAdD,EACTnE,EAAMzM,IAAM,qBAAuB6Q,EAEnCnE,EAAWD,EAAO,0BAA4BmE,EAAY,MAGrD,CACT,CAEA,SAASI,EAAoBvE,GAC3B,IAAIzI,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAEtC,GAAW,KAAP9E,EAAoB,OAAO,EAEV,OAAjByI,EAAMS,QACRR,EAAWD,EAAO,qCAGpBzI,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGpC,IAFA,IAAMyF,EAAY9B,EAAM3D,SAEV,IAAP9E,IAAa0G,EAAU1G,KAAQ2G,EAAgB3G,IACpDA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAQtC,OALI2D,EAAM3D,WAAayF,GACrB7B,EAAWD,EAAO,8DAGpBA,EAAMS,OAAST,EAAMnF,MAAMrD,MAAMsK,EAAW9B,EAAM3D,WAC3C,CACT,CA6BA,SAASmI,EAAiCxE,EAAOyE,EAAerB,EAAYO,GAC1E,IAAMe,EAAgBlE,EAAcR,GAYpC,OArpCF,SAAiCA,GAC/BA,EAAMF,sBAAsBxK,KAAK3D,OAAOsB,OAAO,MACjD,CAyoCE0R,CAAuB3E,GACvBU,EAAaV,EAAOyE,GAIpBzE,EAAMzM,IAAM,KACZyM,EAAMS,OAAS,KACfT,EAAMpM,KAAO,KACboM,EAAM/O,OAAS,KAEXyS,EAAiB1D,EAAOoD,EAAYO,IAA8B,YAAf3D,EAAMpM,MAjpC/D,SAAkCoM,GAChC,IAAMK,EAAcL,EAAMF,sBAAsB8E,MAC1CxE,EAAeJ,EAAMF,sBAE3B,GAA4B,IAAxBM,EAAatO,OAKjB,IAHA,IAAM+S,EAASzE,EAAaA,EAAatO,OAAS,GAC5CgT,EAAQnT,OAAOC,KAAKyO,GAEjBxO,EAAQ,EAAGC,EAASgT,EAAMhT,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CACrE,IAAMU,EAAOuS,EAAMjT,GAEdqJ,EAAgBrI,KAAKgS,EAAQtS,KAChCsS,EAAOtS,GAAQ8N,EAAY9N,GAE/B,CACF,CAkoCIwS,CAAwB/E,IACjB,IAjoCX,SAAoCA,GAIlC,IAHA,IAAMK,EAAcL,EAAMF,sBAAsB8E,MAC1CE,EAAQnT,OAAOC,KAAKyO,GAEjBxO,EAAQiT,EAAMhT,OAAS,EAAGD,GAAS,EAAGA,GAAS,EAAG,CACzD,IAAMmT,EAAQ3E,EAAYyE,EAAMjT,IAE5BmT,EAAM1E,QACRN,EAAMO,UAAUuE,EAAMjT,IAAUmT,EAAM3N,aAE/B2I,EAAMO,UAAUuE,EAAMjT,GAEjC,CACF,CAunCEoT,CAA0BjF,GAC1BU,EAAaV,EAAO0E,IACb,EACT,CAEA,SAASjB,EAAazD,EAAOkF,EAAcC,EAAaC,EAAaxB,GACnE,IAAIyB,EACAC,EAKAhS,EACAqQ,EACA4B,EANAC,EAAe,EACfC,GAAY,EACZC,GAAa,EACbjB,EAAgB,KAKhBzE,EAAMN,OAASM,EAAMX,UACvBY,EAAWD,EAAO,8BAAgCA,EAAMX,SAAW,KAGrEW,EAAMN,OAAS,EAEQ,OAAnBM,EAAMZ,UACRY,EAAMZ,SAAS,OAAQY,GAGzBA,EAAMzM,IAAM,KACZyM,EAAMS,OAAS,KACfT,EAAMpM,KAAO,KACboM,EAAM/O,OAAS,KAEf,IAAM0U,EAAmBN,EAAoBC,EA/4CrB,IAg5CAH,GAj5CD,IAk5CAA,EAgBvB,GAdIC,GACEvC,EAAoB7C,GAAO,GAAM,KACnCyF,GAAY,EAERzF,EAAMP,WAAayF,EACrBM,EAAe,EACNxF,EAAMP,aAAeyF,EAC9BM,EAAe,EACNxF,EAAMP,WAAayF,IAC5BM,GAAe,IAKA,IAAjBA,EACF,OAAa,CACX,IAAMjO,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAClCuJ,EAAgBpF,EAAcR,GAIpC,GAAIyF,IACS,KAAPlO,GAAoC,OAAdyI,EAAMzM,KACrB,KAAPgE,GAAuC,OAAjByI,EAAMS,QAChC,MAGF,IAAKyD,EAAgBlE,KAAWuE,EAAmBvE,GACjD,MAGoB,OAAlByE,IACFA,EAAgBmB,GAGd/C,EAAoB7C,GAAO,GAAM,IACnCyF,GAAY,EACZH,EAAwBK,EAEpB3F,EAAMP,WAAayF,EACrBM,EAAe,EACNxF,EAAMP,aAAeyF,EAC9BM,EAAe,EACNxF,EAAMP,WAAayF,IAC5BM,GAAe,IAGjBF,GAAwB,CAE5B,CAOF,GAJIA,IACFA,EAAwBG,GAAa7B,GAGlB,IAAjB4B,GA38CoB,IA28CwBL,EAS9C,GAPExB,EAh9CkB,IA+8CIwB,GA98CH,IA88CuCA,EAC7CD,EAEAA,EAAe,EAG9BK,EAAcvF,EAAM3D,SAAW2D,EAAM7D,UAEhB,IAAjBqJ,EACF,GAAKF,IACAnC,EAAkBnD,EAAOuF,IAAgB7B,EAAiB1D,EAAOuF,EAAa5B,KA5uBzF,SAA6B3D,EAAOoD,GAClC,IACII,EACAqC,EACAC,EAEAjE,EAEAkE,EACAC,EACAC,EACAC,EAEA3D,EACAD,EACAE,EAdA2D,GAAW,EAIT9C,EAAOrD,EAAMzM,IAEb+P,EAAUtD,EAAMS,OAKhB0B,EAAkBxQ,OAAOsB,OAAO,MAKlCsE,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAEtC,GAAW,KAAP9E,EACFwO,EAAa,GACbG,GAAY,EACZrE,EAAU,OACZ,IAAkB,MAAPtK,EAKT,OAAO,EAJPwO,EAAa,IACbG,GAAY,EACZrE,EAAU,CAAA,CAGZ,CAQA,IANqB,OAAjB7B,EAAMS,QACRN,EAAYH,EAAOA,EAAMS,OAAQoB,GAGnCtK,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAEtB,IAAP9E,GAAU,CAKf,GAJAsL,EAAoB7C,GAAO,EAAMoD,IAEjC7L,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,aAEvB0J,EAMT,OALA/F,EAAM3D,WACN2D,EAAMzM,IAAM8P,EACZrD,EAAMS,OAAS6C,EACftD,EAAMpM,KAAOsS,EAAY,UAAY,WACrClG,EAAM/O,OAAS4Q,GACR,EACGsE,EAEM,KAAP5O,GAET0I,EAAWD,EAAO,4CAHlBC,EAAWD,EAAO,gDAMDwC,EAAY,KAC/BwD,EAASC,GAAiB,EAEf,KAAP1O,GAGE0G,EAFc+B,EAAMnF,MAAMhD,WAAWmI,EAAM3D,SAAW,MAGxD2J,EAASC,GAAiB,EAC1BjG,EAAM3D,WACNwG,EAAoB7C,GAAO,EAAMoD,IAIrCI,EAAQxD,EAAMxN,KACdqT,EAAa7F,EAAM7D,UACnB2J,EAAO9F,EAAM3D,SACboH,EAAYzD,EAAOoD,EArzBC,GAqzB4B,GAAO,GACvDd,EAAStC,EAAMzM,IACfgP,EAAUvC,EAAM/O,OAChB4R,EAAoB7C,GAAO,EAAMoD,GAEjC7L,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,WAE7B4J,GAAkBjG,EAAMxN,OAASgR,GAAiB,KAAPjM,IAC9CyO,GAAS,EACTzO,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UACpCwG,EAAoB7C,GAAO,EAAMoD,GACjCK,EAAYzD,EAAOoD,EAh0BD,GAg0B8B,GAAO,GACvDZ,EAAYxC,EAAM/O,QAGhBiV,EACF7D,EAAiBrC,EAAO6B,EAASM,EAAiBG,EAAQC,EAASC,EAAWgB,EAAOqC,EAAYC,GACxFE,EACTnE,EAAQvM,KAAK+M,EAAiBrC,EAAO,KAAMmC,EAAiBG,EAAQC,EAASC,EAAWgB,EAAOqC,EAAYC,IAE3GjE,EAAQvM,KAAKiN,GAGfM,EAAoB7C,GAAO,EAAMoD,GAItB,MAFX7L,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,YAGhC8J,GAAW,EACX5O,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,WAEpC8J,GAAW,CAEf,CAEAlG,EAAWD,EAAO,wDACpB,CAioBUoG,CAAmBpG,EAAO2D,GAC5B+B,GAAa,MACR,CACL,IAAMnO,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAElB,OAAlBoI,GAA0BkB,IAAqBL,GACxC,MAAP/N,GAA6B,KAAPA,GACtBiN,EACExE,EACAyE,EACAA,EAAcpI,SAAWoI,EAActI,UACvCwH,IAGM0B,GA7oBpB,SAA0BrF,EAAOoD,GAC/B,IAAIiD,EAOAC,EANAC,EAx1BgB,EAy1BhBC,GAAiB,EACjBC,GAAiB,EACjBC,EAAatD,EACbuD,EAAa,EACbC,GAAiB,EAGjBrP,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAEtC,GAAW,MAAP9E,EACF8O,GAAU,MACZ,IAAkB,KAAP9O,EAGT,OAAO,EAFP8O,GAAU,CAGZ,CAKA,IAHArG,EAAMpM,KAAO,SACboM,EAAM/O,OAAS,GAED,IAAPsG,GAGL,GAAW,MAFXA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,YAEH,KAAP9E,EAh3BR,IAi3BMgP,EACpBA,EAAmB,KAAPhP,EAh3BE,EADC,EAm3Bf0I,EAAWD,EAAO,mDAEVsG,EAAMhI,EAAgB/G,KAAQ,GAUxC,MATY,IAAR+O,EACFrG,EAAWD,EAAO,gFACRyG,EAIVxG,EAAWD,EAAO,8CAHlB0G,EAAatD,EAAakD,EAAM,EAChCG,GAAiB,EAMrB,CAGF,GAAIzI,EAAazG,GAAK,CACpB,GAAKA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,gBAClC2B,EAAazG,IAEpB,GAAW,KAAPA,EACF,GAAKA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,iBACjC0B,EAAMxG,IAAe,IAAPA,EAE1B,CAEA,KAAc,IAAPA,GAAU,CAOf,IANAqL,EAAc5C,GACdA,EAAMP,WAAa,EAEnBlI,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,YAGzBoK,GAAkBzG,EAAMP,WAAaiH,IAC/B,KAAPnP,GACNyI,EAAMP,aACNlI,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAOtC,IAJKoK,GAAkBzG,EAAMP,WAAaiH,IACxCA,EAAa1G,EAAMP,YAGjB1B,EAAMxG,GACRoP,QADF,CAUA,GALKF,GAAiC,IAAfC,GACrBzG,EAAWD,EAAO,wCAIhBA,EAAMP,WAAaiH,EAAY,CAv6BjB,IAy6BZH,EACFvG,EAAM/O,QAAUT,EAAOM,OAAO,KAAM0V,EAAiB,EAAIG,EAAaA,GA56BxD,IA66BLJ,GACLC,IACFxG,EAAM/O,QAAU,MAKpB,KACF,CAGIoV,EAEErI,EAAazG,IACfqP,GAAiB,EAEjB5G,EAAM/O,QAAUT,EAAOM,OAAO,KAAM0V,EAAiB,EAAIG,EAAaA,IAG7DC,GACTA,GAAiB,EACjB5G,EAAM/O,QAAUT,EAAOM,OAAO,KAAM6V,EAAa,IAGzB,IAAfA,EACLH,IACFxG,EAAM/O,QAAU,KAKlB+O,EAAM/O,QAAUT,EAAOM,OAAO,KAAM6V,GAMtC3G,EAAM/O,QAAUT,EAAOM,OAAO,KAAM0V,EAAiB,EAAIG,EAAaA,GAGxEH,GAAiB,EACjBC,GAAiB,EACjBE,EAAa,EAGb,IAFA,IAAME,EAAe7G,EAAM3D,UAEnB0B,EAAMxG,IAAe,IAAPA,GACpBA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGtCoF,EAAezB,EAAO6G,EAAc7G,EAAM3D,UAAU,EA5DpD,CA6DF,CAEA,OAAO,CACT,CAigByCyK,CAAgB9G,EAAO2D,IA92BhE,SAAiC3D,EAAOoD,GACtC,IAAIyD,EACAE,EAEAxP,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAEtC,GAAW,KAAP9E,EACF,OAAO,EAQT,IALAyI,EAAMpM,KAAO,SACboM,EAAM/O,OAAS,GACf+O,EAAM3D,WACNwK,EAAeE,EAAa/G,EAAM3D,SAEuB,KAAjD9E,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,YACxC,GAAW,KAAP9E,EAAoB,CAItB,GAHAkK,EAAezB,EAAO6G,EAAc7G,EAAM3D,UAAU,GAGzC,MAFX9E,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,WAOlC,OAAO,EAJPwK,EAAe7G,EAAM3D,SACrB2D,EAAM3D,WACN0K,EAAa/G,EAAM3D,QAIvB,MAAW0B,EAAMxG,IACfkK,EAAezB,EAAO6G,EAAcE,GAAY,GAChD7D,EAAiBlD,EAAO6C,EAAoB7C,GAAO,EAAOoD,IAC1DyD,EAAeE,EAAa/G,EAAM3D,UACzB2D,EAAM3D,WAAa2D,EAAM7D,WAAa8G,EAAsBjD,GACrEC,EAAWD,EAAO,iEAElBA,EAAM3D,WACD2B,EAAazG,KAChBwP,EAAa/G,EAAM3D,WAKzB4D,EAAWD,EAAO,6DACpB,CAq0BYgH,CAAuBhH,EAAO2D,IAn0B1C,SAAiC3D,EAAOoD,GACtC,IAAIyD,EACAE,EACAT,EAEA/O,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAEtC,GAAW,KAAP9E,EACF,OAAO,EAQT,IALAyI,EAAMpM,KAAO,SACboM,EAAM/O,OAAS,GACf+O,EAAM3D,WACNwK,EAAeE,EAAa/G,EAAM3D,SAEuB,KAAjD9E,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,YAAkB,CAC1D,GAAW,KAAP9E,EAGF,OAFAkK,EAAezB,EAAO6G,EAAc7G,EAAM3D,UAAU,GACpD2D,EAAM3D,YACC,EACT,GAAkB,KAAP9E,EAAoB,CAI7B,GAHAkK,EAAezB,EAAO6G,EAAc7G,EAAM3D,UAAU,GAGhD0B,EAFJxG,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,WAGlCwG,EAAoB7C,GAAO,EAAOoD,WAGzB7L,EAAK,KAAOuH,EAAkBvH,GACvCyI,EAAM/O,QAAU8N,EAAgBxH,GAChCyI,EAAM3D,oBACIiK,EAAMjI,EAAc9G,IAAO,EAAG,CAIxC,IAHA,IAAI0P,EAAYX,EACZY,EAAY,EAETD,EAAY,EAAGA,KAGfX,EAAMnI,EAFX5G,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,aAEL,EAC7B6K,GAAaA,GAAa,GAAKZ,EAE/BrG,EAAWD,EAAO,kCAItBA,EAAM/O,QAAUuN,EAAkB0I,GAElClH,EAAM3D,UACR,MACE4D,EAAWD,EAAO,2BAGpB6G,EAAeE,EAAa/G,EAAM3D,QACpC,MAAW0B,EAAMxG,IACfkK,EAAezB,EAAO6G,EAAcE,GAAY,GAChD7D,EAAiBlD,EAAO6C,EAAoB7C,GAAO,EAAOoD,IAC1DyD,EAAeE,EAAa/G,EAAM3D,UACzB2D,EAAM3D,WAAa2D,EAAM7D,WAAa8G,EAAsBjD,GACrEC,EAAWD,EAAO,iEAElBA,EAAM3D,WACD2B,EAAazG,KAChBwP,EAAa/G,EAAM3D,UAGzB,CAEA4D,EAAWD,EAAO,6DACpB,CA+vBYmH,CAAuBnH,EAAO2D,GAHhC+B,GAAa,GAjKvB,SAAoB1F,GAClB,IAAIzI,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAEtC,GAAW,KAAP9E,EAAoB,OAAO,EAE/BA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGpC,IAFA,IAAMyF,EAAY9B,EAAM3D,SAEV,IAAP9E,IAAa0G,EAAU1G,KAAQ2G,EAAgB3G,IACpDA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGlC2D,EAAM3D,WAAayF,GACrB7B,EAAWD,EAAO,6DAGpB,IAAMxL,EAAQwL,EAAMnF,MAAMrD,MAAMsK,EAAW9B,EAAM3D,UAQjD,OANKnB,EAAgBrI,KAAKmN,EAAMO,UAAW/L,IACzCyL,EAAWD,EAAO,uBAAyBxL,EAAQ,KAGrDwL,EAAM/O,OAAS+O,EAAMO,UAAU/L,GAC/BqO,EAAoB7C,GAAO,GAAM,IAC1B,CACT,CA6ImBoH,CAAUpH,GAz9B7B,SAA0BA,EAAOoD,EAAYiE,GAC3C,IAAIR,EACAE,EACAO,EACA9D,EACAqC,EACA0B,EACEC,EAAQxH,EAAMpM,KACdiO,EAAU7B,EAAM/O,OAElBsG,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAEtC,GAAI4B,EAAU1G,IACV2G,EAAgB3G,IACT,KAAPA,GACO,KAAPA,GACO,KAAPA,GACO,KAAPA,GACO,MAAPA,GACO,KAAPA,GACO,KAAPA,GACO,KAAPA,GACO,KAAPA,GACO,KAAPA,GACO,KAAPA,EACF,OAAO,EAGT,GAAW,KAAPA,GAA6B,KAAPA,EAAoB,CAC5C,IAAM0M,EAAYjE,EAAMnF,MAAMhD,WAAWmI,EAAM3D,SAAW,GAE1D,GAAI4B,EAAUgG,IACToD,GAAwBnJ,EAAgB+F,GAC3C,OAAO,CAEX,CAOA,IALAjE,EAAMpM,KAAO,SACboM,EAAM/O,OAAS,GACf4V,EAAeE,EAAa/G,EAAM3D,SAClCiL,GAAoB,EAEN,IAAP/P,GAAU,CACf,GAAW,KAAPA,EAAoB,CACtB,IAAM0M,EAAYjE,EAAMnF,MAAMhD,WAAWmI,EAAM3D,SAAW,GAE1D,GAAI4B,EAAUgG,IACToD,GAAwBnJ,EAAgB+F,GAC3C,KAEJ,MAAA,GAAkB,KAAP1M,GAGT,GAAI0G,EAFc+B,EAAMnF,MAAMhD,WAAWmI,EAAM3D,SAAW,IAGxD,cAEQ2D,EAAM3D,WAAa2D,EAAM7D,WAAa8G,EAAsBjD,IAC5DqH,GAAwBnJ,EAAgB3G,GAClD,MACF,GAAWwG,EAAMxG,GAAK,CAMpB,GALAiM,EAAQxD,EAAMxN,KACdqT,EAAa7F,EAAM7D,UACnBoL,EAAcvH,EAAMP,WACpBoD,EAAoB7C,GAAO,GAAO,GAE9BA,EAAMP,YAAc2D,EAAY,CAClCkE,GAAoB,EACpB/P,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,UAClC,QACF,CACE2D,EAAM3D,SAAW0K,EACjB/G,EAAMxN,KAAOgR,EACbxD,EAAM7D,UAAY0J,EAClB7F,EAAMP,WAAa8H,EACnB,KAEJ,EAEID,IACF7F,EAAezB,EAAO6G,EAAcE,GAAY,GAChD7D,EAAiBlD,EAAOA,EAAMxN,KAAOgR,GACrCqD,EAAeE,EAAa/G,EAAM3D,SAClCiL,GAAoB,GAGjBtJ,EAAazG,KAChBwP,EAAa/G,EAAM3D,SAAW,GAGhC9E,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,SACtC,CAIA,OAFAoF,EAAezB,EAAO6G,EAAcE,GAAY,KAE5C/G,EAAM/O,SAIV+O,EAAMpM,KAAO4T,EACbxH,EAAM/O,OAAS4Q,GACR,EACT,CA03BmB4F,CAAgBzH,EAAO2D,EAl/ClB,IAk/CkDwB,KAChEO,GAAa,EAEK,OAAd1F,EAAMzM,MACRyM,EAAMzM,IAAM,OATdmS,GAAa,EAEK,OAAd1F,EAAMzM,KAAiC,OAAjByM,EAAMS,QAC9BR,EAAWD,EAAO,8CAUD,OAAjBA,EAAMS,QACRN,EAAYH,EAAOA,EAAMS,OAAQT,EAAM/O,OAE3C,MAC0B,IAAjBuU,IAGTE,EAAaJ,GAAyBnC,EAAkBnD,EAAOuF,IAInE,GAAkB,OAAdvF,EAAMzM,IACa,OAAjByM,EAAMS,QACRN,EAAYH,EAAOA,EAAMS,OAAQT,EAAM/O,aAE3C,GAAyB,MAAd+O,EAAMzM,IAAa,CAOP,OAAjByM,EAAM/O,QAAkC,WAAf+O,EAAMpM,MACjCqM,EAAWD,EAAO,oEAAsEA,EAAMpM,KAAO,KAGvG,IAAA,IAAS8T,EAAY,EAAGC,EAAe3H,EAAMT,cAAczN,OAAQ4V,EAAYC,EAAcD,GAAa,EAGxG,IAFApU,EAAO0M,EAAMT,cAAcmI,IAElB7T,QAAQmM,EAAM/O,QAAS,CAC9B+O,EAAM/O,OAASqC,EAAKQ,UAAUkM,EAAM/O,QACpC+O,EAAMzM,IAAMD,EAAKC,IACI,OAAjByM,EAAMS,QACRN,EAAYH,EAAOA,EAAMS,OAAQT,EAAM/O,QAEzC,KACF,CAEJ,MAAA,GAAyB,MAAd+O,EAAMzM,IAAa,CAC5B,GAAI2H,EAAgBrI,KAAKmN,EAAMR,QAAQQ,EAAMpM,MAAQ,YAAaoM,EAAMzM,KACtED,EAAO0M,EAAMR,QAAQQ,EAAMpM,MAAQ,YAAYoM,EAAMzM,SAChD,CAELD,EAAO,KAGP,IAFA,IAAMsU,EAAW5H,EAAMR,QAAQnL,MAAM2L,EAAMpM,MAAQ,YAE1C8T,EAAY,EAAGC,EAAeC,EAAS9V,OAAQ4V,EAAYC,EAAcD,GAAa,EAC7F,GAAI1H,EAAMzM,IAAIiE,MAAM,EAAGoQ,EAASF,GAAWnU,IAAIzB,UAAY8V,EAASF,GAAWnU,IAAK,CAClFD,EAAOsU,EAASF,GAChB,KACF,CAEJ,CAEKpU,GACH2M,EAAWD,EAAO,iBAAmBA,EAAMzM,IAAM,KAG9B,OAAjByM,EAAM/O,QAAmBqC,EAAKM,OAASoM,EAAMpM,MAC/CqM,EAAWD,EAAO,gCAAkCA,EAAMzM,IAAM,wBAA0BD,EAAKM,KAAO,WAAaoM,EAAMpM,KAAO,KAG7HN,EAAKO,QAAQmM,EAAM/O,OAAQ+O,EAAMzM,MAGpCyM,EAAM/O,OAASqC,EAAKQ,UAAUkM,EAAM/O,OAAQ+O,EAAMzM,KAC7B,OAAjByM,EAAMS,QACRN,EAAYH,EAAOA,EAAMS,OAAQT,EAAM/O,SAJzCgP,EAAWD,EAAO,gCAAkCA,EAAMzM,IAAM,iBAOpE,CAOA,OALuB,OAAnByM,EAAMZ,UACRY,EAAMZ,SAAS,QAASY,GAG1BA,EAAMN,OAAS,EACM,OAAdM,EAAMzM,KAAiC,OAAjByM,EAAMS,QAAmBiF,CACxD,CAEA,SAASmC,EAAc7H,GACrB,IAEIzI,EAFEuQ,EAAgB9H,EAAM3D,SACxB0L,GAAgB,EAQpB,IALA/H,EAAMe,QAAU,KAChBf,EAAMkB,gBAAkBlB,EAAMb,OAC9Ba,EAAMsB,OAAS3P,OAAOsB,OAAO,MAC7B+M,EAAMO,UAAY5O,OAAOsB,OAAO,MAEyB,KAAjDsE,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,aACxCwG,EAAoB7C,GAAO,GAAM,GAEjCzI,EAAKyI,EAAMnF,MAAMhD,WAAWmI,EAAM3D,YAE9B2D,EAAMP,WAAa,GAAY,KAAPlI,KAL8B,CAS1DwQ,GAAgB,EAChBxQ,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGpC,IAFA,IAAIyF,EAAY9B,EAAM3D,SAER,IAAP9E,IAAa0G,EAAU1G,IAC5BA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGtC,IAAM2L,EAAgBhI,EAAMnF,MAAMrD,MAAMsK,EAAW9B,EAAM3D,UACnD4L,EAAgB,GAMtB,IAJID,EAAclW,OAAS,GACzBmO,EAAWD,EAAO,gEAGN,IAAPzI,GAAU,CACf,KAAOyG,EAAazG,IAClBA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGtC,GAAW,KAAP9E,EAAoB,CACtB,GAAKA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,gBAC3B,IAAP9E,IAAawG,EAAMxG,IAC1B,KACF,CAEA,GAAIwG,EAAMxG,GAAK,MAIf,IAFAuK,EAAY9B,EAAM3D,SAEJ,IAAP9E,IAAa0G,EAAU1G,IAC5BA,EAAKyI,EAAMnF,MAAMhD,aAAamI,EAAM3D,UAGtC4L,EAAc3S,KAAK0K,EAAMnF,MAAMrD,MAAMsK,EAAW9B,EAAM3D,UACxD,CAEW,IAAP9E,GAAUqL,EAAc5C,GAExB9E,EAAgBrI,KAAK+N,EAAmBoH,GAC1CpH,EAAkBoH,GAAehI,EAAOgI,EAAeC,GAEvD/H,EAAaF,EAAO,+BAAiCgI,EAAgB,IAEzE,CAEAnF,EAAoB7C,GAAO,GAAM,GAER,IAArBA,EAAMP,YACqC,KAA3CO,EAAMnF,MAAMhD,WAAWmI,EAAM3D,WACkB,KAA/C2D,EAAMnF,MAAMhD,WAAWmI,EAAM3D,SAAW,IACO,KAA/C2D,EAAMnF,MAAMhD,WAAWmI,EAAM3D,SAAW,IAC1C2D,EAAM3D,UAAY,EAClBwG,EAAoB7C,GAAO,GAAM,IACxB+H,GACT9H,EAAWD,EAAO,mCAGpByD,EAAYzD,EAAOA,EAAMP,WAAa,EAppDd,GAopDoC,GAAO,GACnEoD,EAAoB7C,GAAO,GAAM,GAE7BA,EAAMkB,iBACNxD,EAA8BjF,KAAKuH,EAAMnF,MAAMrD,MAAMsQ,EAAe9H,EAAM3D,YAC5E6D,EAAaF,EAAO,oDAGtBA,EAAMH,UAAUvK,KAAK0K,EAAM/O,QAEvB+O,EAAM3D,WAAa2D,EAAM7D,WAAa8G,EAAsBjD,GACf,KAA3CA,EAAMnF,MAAMhD,WAAWmI,EAAM3D,YAC/B2D,EAAM3D,UAAY,EAClBwG,EAAoB7C,GAAO,GAAM,IAKjCA,EAAM3D,SAAY2D,EAAMlO,OAAS,GACnCmO,EAAWD,EAAO,wDAEtB,CAEA,SAASkI,EAAerN,EAAOrH,GAE7BA,EAAUA,GAAW,CAAA,EAEA,KAHrBqH,EAAQpG,OAAOoG,IAGL/I,SAEmC,KAAvC+I,EAAMhD,WAAWgD,EAAM/I,OAAS,IACO,KAAvC+I,EAAMhD,WAAWgD,EAAM/I,OAAS,KAClC+I,GAAS,MAIiB,QAAxBA,EAAMhD,WAAW,KACnBgD,EAAQA,EAAMrD,MAAM,KAIxB,IAAMwI,EAAQ,IAAIhB,EAAMnE,EAAOrH,GAEzB2U,EAAUtN,EAAMlH,QAAQ,MAU9B,KARgB,IAAZwU,IACFnI,EAAM3D,SAAW8L,EACjBlI,EAAWD,EAAO,sCAIpBA,EAAMnF,OAAS,KAEmC,KAA3CmF,EAAMnF,MAAMhD,WAAWmI,EAAM3D,WAClC2D,EAAMP,YAAc,EACpBO,EAAM3D,UAAY,EAGpB,KAAO2D,EAAM3D,SAAY2D,EAAMlO,OAAS,GACtC+V,EAAa7H,GAGf,OAAOA,EAAMH,SACf,QA8BAuI,EAAAC,QA5BA,SAAkBxN,EAAO1K,EAAUqD,GAChB,OAAbrD,GAAyC,WAApBH,EAAOG,SAA4C,IAAZqD,IAC9DA,EAAUrD,EACVA,EAAW,MAGb,IAAM0P,EAAYqI,EAAcrN,EAAOrH,GAEvC,GAAwB,mBAAbrD,EACT,OAAO0P,EAGT,IAAA,IAAShO,EAAQ,EAAGC,EAAS+N,EAAU/N,OAAQD,EAAQC,EAAQD,GAAS,EACtE1B,EAAS0P,EAAUhO,GAEvB,EAcAuW,EAAAE,KAZA,SAAezN,EAAOrH,GACpB,IAAMqM,EAAYqI,EAAcrN,EAAOrH,GAEvC,GAAyB,IAArBqM,EAAU/N,OAAd,CAEA,GAAgC,IAArB+N,EAAU/N,OACnB,OAAO+N,EAAU,GAEnB,MAAM,IAAIlN,EAAc,2DADxB,CAEF,kDE1vDY,SAAA3C,EAAAC,GAAA,OAAAD,EAAA,mBAAAE,QAAA,iBAAAA,OAAAC,SAAA,SAAAF,GAAA,cAAAA,GAAA,SAAAA,GAAA,OAAAA,GAAA,mBAAAC,QAAAD,EAAAG,cAAAF,QAAAD,IAAAC,OAAAG,UAAA,gBAAAJ,CAAA,GAAAA,EAAA,MAEZ,IAAMO,EAAS2C,IACTR,EAAgBgC,IAChB6I,EAAiBnH,KAEjB+E,EAAYzJ,OAAOtB,UAAU6C,SAC7BgI,EAAkBvJ,OAAOtB,UAAU8K,eAEnCoN,EAAW,MA0BXC,EAAmB,CAEzBA,EAAyB,MACzBA,EAAyB,MACzBA,EAAyB,MACzBA,EAAyB,MACzBA,GAAyB,MACzBA,GAAyB,MACzBA,GAAyB,MACzBA,GAAyB,MACzBA,GAAyB,MACzBA,GAAyB,MACzBA,GAAyB,OACzBA,IAAyB,MACzBA,IAAyB,MACzBA,KAA2B,MAC3BA,KAA2B,OAErBC,EAA6B,CACjC,IAAK,IAAK,MAAO,MAAO,MAAO,KAAM,KAAM,KAC3C,IAAK,IAAK,KAAM,KAAM,KAAM,MAAO,MAAO,OAGtCC,EAA2B,4CA2BjC,SAASC,EAAWC,GAClB,IAAIvH,EACAvP,EAEEf,EAAS6X,EAAU1V,SAAS,IAAIiF,cAEtC,GAAIyQ,GAAa,IACfvH,EAAS,IACTvP,EAAS,OACX,GAAW8W,GAAa,MACtBvH,EAAS,IACTvP,EAAS,MACX,MAAW8W,GAAa,YAItB,MAAM,IAAIjW,EAAc,iEAHxB0O,EAAS,IACTvP,EAAS,CAGX,CAEA,MAAO,KAAOuP,EAAS7Q,EAAOM,OAAO,IAAKgB,EAASf,EAAOe,QAAUf,CACtE,CAKA,SAASiO,EAAOxL,GACdV,KAAK+B,OAASrB,EAAgB,QAAKgK,EACnC1K,KAAKgK,OAASL,KAAKjG,IAAI,EAAIhD,EAAgB,QAAK,GAChDV,KAAK+V,cAAgBrV,EAAuB,gBAAK,EACjDV,KAAKgW,YAActV,EAAqB,cAAK,EAC7CV,KAAKiW,UAAavY,EAAOF,UAAUkD,EAAmB,YAAK,EAAKA,EAAmB,UACnFV,KAAKkW,SAxDP,SAA0BnU,EAAQpB,GAChC,GAAY,OAARA,EAAc,MAAO,CAAA,EAKzB,IAHA,IAAMxC,EAAS,CAAA,EACTW,EAAOD,OAAOC,KAAK6B,GAEhB5B,EAAQ,EAAGC,EAASF,EAAKE,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CACpE,IAAI0B,EAAM3B,EAAKC,GACX0C,EAAQE,OAAOhB,EAAIF,IAEC,OAApBA,EAAIiE,MAAM,EAAG,KACfjE,EAAM,qBAAuBA,EAAIiE,MAAM,IAEzC,IAAMlE,EAAOuB,EAAOc,gBAA0B,SAAEpC,GAE5CD,GAAQ4H,EAAgBrI,KAAKS,EAAKgB,aAAcC,KAClDA,EAAQjB,EAAKgB,aAAaC,IAG5BtD,EAAOsC,GAAOgB,CAChB,CAEA,OAAOtD,CACT,CAiCkBgY,CAAgBnW,KAAK+B,OAAQrB,EAAgB,QAAK,MAClEV,KAAKoW,SAAW1V,EAAkB,WAAK,EACvCV,KAAKqW,UAAY3V,EAAmB,WAAK,GACzCV,KAAKsW,OAAS5V,EAAgB,SAAK,EACnCV,KAAKuW,aAAe7V,EAAsB,eAAK,EAC/CV,KAAKwW,aAAe9V,EAAsB,eAAK,EAC/CV,KAAKyW,YAAyC,MAA3B/V,EAAqB,YAdd,EADA,EAgB1BV,KAAK0W,YAAchW,EAAqB,cAAK,EAC7CV,KAAK2W,SAA0C,mBAAxBjW,EAAkB,SAAmBA,EAAkB,SAAI,KAElFV,KAAKyM,cAAgBzM,KAAK+B,OAAOY,iBACjC3C,KAAK4W,cAAgB5W,KAAK+B,OAAOa,iBAEjC5C,KAAKS,IAAM,KACXT,KAAK7B,OAAS,GAEd6B,KAAK6W,WAAa,GAClB7W,KAAK8W,eAAiB,IACxB,CAGA,SAASC,EAAc9Y,EAAQ+Y,GAM7B,IALA,IAAMC,EAAMvZ,EAAOM,OAAO,IAAKgZ,GAC3BzN,EAAW,EACXpL,EAAS,GACPa,EAASf,EAAOe,OAEfuK,EAAWvK,GAAQ,CACxB,IAAIU,OAAI,EACFwX,EAAOjZ,EAAO4C,QAAQ,KAAM0I,IACrB,IAAT2N,GACFxX,EAAOzB,EAAOyG,MAAM6E,GACpBA,EAAWvK,IAEXU,EAAOzB,EAAOyG,MAAM6E,EAAU2N,EAAO,GACrC3N,EAAW2N,EAAO,GAGhBxX,EAAKV,QAAmB,OAATU,IAAevB,GAAU8Y,GAE5C9Y,GAAUuB,CACZ,CAEA,OAAOvB,CACT,CAEA,SAASgZ,EAAkBjK,EAAOkK,GAChC,MAAO,KAAO1Z,EAAOM,OAAO,IAAKkP,EAAMlD,OAASoN,EAClD,CAeA,SAASC,EAAclT,GACrB,OAvKiB,KAuKVA,GA1KQ,IA0KYA,CAC7B,CAMA,SAASmT,EAAanT,GACpB,OAAQA,GAAK,IAAWA,GAAK,KACzBA,GAAK,KAAWA,GAAK,OAAmB,OAANA,GAAsB,OAANA,GAClDA,GAAK,OAAWA,GAAK,OAAaA,IAAMsR,GACzCtR,GAAK,OAAWA,GAAK,OAC1B,CAOA,SAASoT,EAAsBpT,GAC7B,OAAOmT,EAAYnT,IACjBA,IAAMsR,GA7LmB,KA+LzBtR,GAhMmB,KAiMnBA,CACJ,CAWA,SAASqT,EAAarT,EAAGsT,EAAMC,GAC7B,IAAMC,EAAwBJ,EAAqBpT,GAC7CyT,EAAYD,IAA0BN,EAAalT,GACzD,OAGIuT,EACIC,EACAA,GA3MS,KA6MTxT,GAtMuB,KAuMvBA,GAtMwB,KAuMxBA,GArMsB,MAsMtBA,GApMuB,MAqMvBA,IAtNS,KAyNfA,KAlNe,KAmNbsT,IAAwBG,IAE3BL,EAAqBE,KAAUJ,EAAaI,IA5N5B,KA4NqCtT,GArNrC,KAsNhBsT,GAAuBG,CAC1B,CA2CA,SAASC,EAAa5Z,EAAQ4L,GAC5B,IACIzC,EADE0Q,EAAQ7Z,EAAO8G,WAAW8E,GAGhC,OAAIiO,GAAS,OAAUA,GAAS,OAAUjO,EAAM,EAAI5L,EAAOe,SACzDoI,EAASnJ,EAAO8G,WAAW8E,EAAM,KACnB,OAAUzC,GAAU,MAEN,MAAlB0Q,EAAQ,OAAkB1Q,EAAS,MAAS,MAGjD0Q,CACT,CAGA,SAASC,EAAqB9Z,GAE5B,MADuB,QACD0H,KAAK1H,EAC7B,CAeA,SAAS+Z,EAAmB/Z,EAAQga,EAAgBC,EAAgB7B,EAClE8B,EAAmB1B,EAAaC,EAAagB,GAC7C,IAAIjN,EA3EqBtG,EA4ErBiU,EAAO,EACPC,EAAW,KACXC,GAAe,EACfC,GAAkB,EAChBC,GAAiC,IAAdnC,EACrBoC,GAAoB,EACpBC,EA9EGpB,EAJkBnT,EAkFI0T,EAAY5Z,EAAQ,KA7E/CkG,IAAMsR,IACL4B,EAAalT,IAjOC,KAoOfA,GAhOkB,KAiOlBA,GApOe,KAqOfA,GAvOe,KAwOfA,GAjO6B,KAkO7BA,GAjO8B,KAkO9BA,GAhO4B,MAiO5BA,GA/N6B,MAgO7BA,GAjPe,KAmPfA,GAjPmB,KAkPnBA,GAhPkB,KAiPlBA,GAvPqB,KAwPrBA,GAtOuB,MAuOvBA,GA/OgB,KAgPhBA,GA/OsB,KAgPtBA,GAtPsB,KAuPtBA,GA3PsB,KA4PtBA,GA1PiB,KA4PjBA,GAlPuB,KAmPvBA,GAhPsB,KAiPtBA,GAIJ,SAA0BA,GAExB,OAAQkT,EAAalT,IA9PJ,KA8PUA,CAC7B,CA8CIwU,CAAgBd,EAAY5Z,EAAQA,EAAOe,OAAS,IAEtD,GAAIiZ,GAAkBvB,EAGpB,IAAKjM,EAAI,EAAGA,EAAIxM,EAAOe,OAAQoZ,GAAQ,MAAU3N,GAAK,EAAIA,IAAK,CAE7D,IAAK6M,EADLc,EAAOP,EAAY5Z,EAAQwM,IAEzB,OA3Ba,EA6BfiO,EAAQA,GAASlB,EAAYY,EAAMC,EAAUX,GAC7CW,EAAWD,CACb,KACK,CAEL,IAAK3N,EAAI,EAAGA,EAAIxM,EAAOe,OAAQoZ,GAAQ,MAAU3N,GAAK,EAAIA,IAAK,CAE7D,GA1UiB,MAyUjB2N,EAAOP,EAAY5Z,EAAQwM,IAEzB6N,GAAe,EAEXE,IACFD,EAAkBA,GAEf9N,EAAIgO,EAAoB,EAAIpC,GACM,MAAlCpY,EAAOwa,EAAoB,GAC9BA,EAAoBhO,QAExB,IAAY6M,EAAYc,GACtB,OA/Ca,EAiDfM,EAAQA,GAASlB,EAAYY,EAAMC,EAAUX,GAC7CW,EAAWD,CACb,CAEAG,EAAkBA,GAAoBC,GACnC/N,EAAIgO,EAAoB,EAAIpC,GACM,MAAlCpY,EAAOwa,EAAoB,EAChC,CAIA,OAAKH,GAAiBC,EASlBL,EAAiB,GAAKH,EAAoB9Z,GArE3B,EA0EdyY,EA/QqB,IAkRnBD,EA7EY,EAHA,EA8EV8B,EA5EU,EADC,GAiEdG,GAAUhC,GAAgByB,EAAkBla,GApQxB,IAuQjBwY,EAlEU,EAHA,EADD,CAkFpB,CAQA,SAASmC,EAAa1L,EAAOjP,EAAQmZ,EAAOyB,EAAOnB,GACjDxK,EAAM4L,gBACJ,GAAsB,IAAlB7a,EAAOe,OACT,OA9RsB,IA8RfkO,EAAMuJ,YAAsC,KAAO,KAE5D,IAAKvJ,EAAMqJ,oBACLZ,EAA2B9U,QAAQ5C,IAAkB2X,EAAyBjQ,KAAK1H,IACrF,OAlSoB,IAkSbiP,EAAMuJ,YAAuC,IAAMxY,EAAS,IAAQ,IAAMA,EAAS,IAI9F,IAAM+L,EAASkD,EAAMlD,OAASL,KAAKjG,IAAI,EAAG0T,GAQpCf,GAAiC,IAApBnJ,EAAMmJ,aAErB1M,KAAKjG,IAAIiG,KAAKa,IAAI0C,EAAMmJ,UAAW,IAAKnJ,EAAMmJ,UAAYrM,GAGxDiO,EAAiBY,GAEpB3L,EAAM+I,WAAY,GAAMmB,GAASlK,EAAM+I,UAK1C,OAAQ+B,EAAkB/Z,EAAQga,EAAgB/K,EAAMlD,OAAQqM,EAJhE,SAAwBpY,GACtB,OA7PN,SAAgCiP,EAAO9J,GACrC,IAAA,IAASrE,EAAQ,EAAGC,EAASkO,EAAMT,cAAczN,OAAQD,EAAQC,EAAQD,GAAS,EAGhF,GAFamO,EAAMT,cAAc1N,GAExBgC,QAAQqC,GACf,OAAO,EAIX,OAAO,CACT,CAmPa2V,CAAsB7L,EAAOjP,EACtC,EAGiBiP,EAAMuJ,YAAavJ,EAAMwJ,cAAgBmC,EAAOnB,IAC/D,KA3Hc,EA4HZ,OAAOzZ,EACT,KA5He,EA6Hb,MAAO,IAAMA,EAAOiI,QAAQ,KAAM,MAAQ,IAC5C,KA7HgB,EA8Hd,MAAO,IAAM8S,EAAY/a,EAAQiP,EAAMlD,QACrCiP,EAAkBlC,EAAa9Y,EAAQ+L,IAC3C,KA/He,EAgIb,MAAO,IAAMgP,EAAY/a,EAAQiP,EAAMlD,QACrCiP,EAAkBlC,EA4B5B,SAAqB9Y,EAAQib,GAK3B,IAWIC,EAGAvS,EAdEwS,EAAS,iBAGXjb,GACEkb,EAASpb,EAAO4C,QAAQ,MAC5BwY,GAAoB,IAAXA,EAAgBA,EAASpb,EAAOe,OACzCoa,EAAOE,UAAYD,EACZE,EAAStb,EAAOyG,MAAM,EAAG2U,GAASH,IAGvCM,EAAiC,OAAdvb,EAAO,IAA6B,MAAdA,EAAO,OAN9Cob,EAWN,KAAQzS,EAAQwS,EAAO3S,KAAKxI,IAAU,CACpC,IAAMqQ,EAAS1H,EAAM,GACflH,EAAOkH,EAAM,GAEnBuS,EAA4B,MAAZzZ,EAAK,GACrBvB,GAAUmQ,GACLkL,GAAqBL,GAAyB,KAATzZ,EAAsB,GAAP,MACvD6Z,EAAS7Z,EAAMwZ,GACjBM,EAAmBL,CACrB,CAEA,OAAOhb,CACT,CA5DyCsb,CAAWxb,EAAQoY,GAAYrM,IAClE,KAjIe,EAkIb,MAAO,IA2Gf,SAAuB/L,GAIrB,IAHA,IAAIE,EAAS,GACTia,EAAO,EAEF3N,EAAI,EAAGA,EAAIxM,EAAOe,OAAQoZ,GAAQ,MAAU3N,GAAK,EAAIA,IAAK,CACjE2N,EAAOP,EAAY5Z,EAAQwM,GAC3B,IAAMiP,EAAYhE,EAAiB0C,IAE9BsB,GAAapC,EAAYc,IAC5Bja,GAAUF,EAAOwM,GACb2N,GAAQ,QAASja,GAAUF,EAAOwM,EAAI,KAE1CtM,GAAUub,GAAa7D,EAAUuC,EAErC,CAEA,OAAOja,CACT,CA5HqBwb,CAAa1b,GAAqB,IACjD,QACE,MAAM,IAAI4B,EAAc,0CAE9B,GACF,CAGA,SAASmZ,EAAa/a,EAAQia,GAC5B,IAAM0B,EAAkB7B,EAAoB9Z,GAAU0D,OAAOuW,GAAkB,GAGzE2B,EAAqC,OAA9B5b,EAAOA,EAAOe,OAAS,GAIpC,OAAO4a,GAHMC,IAAuC,OAA9B5b,EAAOA,EAAOe,OAAS,IAA0B,OAAXf,GACvC,IAAO4b,EAAO,GAAK,KAEP,IACnC,CAGA,SAASZ,EAAmBhb,GAC1B,MAAqC,OAA9BA,EAAOA,EAAOe,OAAS,GAAcf,EAAOyG,MAAM,GAAG,GAAMzG,CACpE,CA0CA,SAASsb,EAAU7Z,EAAMwZ,GACvB,GAAa,KAATxZ,GAA2B,MAAZA,EAAK,GAAY,OAAOA,EAgB3C,IAbA,IACIkH,EAGAiI,EAJEiL,EAAU,SAGZlL,EAAQ,EAERmL,EAAO,EACP7C,EAAO,EACP/Y,EAAS,GAMLyI,EAAQkT,EAAQrT,KAAK/G,KAC3BwX,EAAOtQ,EAAM7H,OAEF6P,EAAQsK,IACjBrK,EAAOkL,EAAOnL,EAASmL,EAAO7C,EAC9B/Y,GAAU,KAAOuB,EAAKgF,MAAMkK,EAAOC,GAEnCD,EAAQC,EAAM,GAEhBkL,EAAO7C,EAaT,OARA/Y,GAAU,KAENuB,EAAKV,OAAS4P,EAAQsK,GAASa,EAAOnL,EACxCzQ,GAAUuB,EAAKgF,MAAMkK,EAAOmL,GAAQ,KAAOra,EAAKgF,MAAMqV,EAAO,GAE7D5b,GAAUuB,EAAKgF,MAAMkK,GAGhBzQ,EAAOuG,MAAM,EACtB,CA8CA,SAASsV,EAAoB9M,EAAOkK,EAAOzT,EAAQvE,GAIjD,IAHA,IAAI2P,EAAU,GACRwB,EAAOrD,EAAMzM,IAEV1B,EAAQ,EAAGC,EAAS2E,EAAO3E,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CACtE,IAAIwF,EAAQZ,EAAO5E,GAEfmO,EAAMyJ,WACRpS,EAAQ2I,EAAMyJ,SAAS5W,KAAK4D,EAAQhC,OAAO5C,GAAQwF,KAIjD0V,EAAU/M,EAAOkK,EAAQ,EAAG7S,GAAO,GAAM,GAAM,GAAO,SACpC,IAAVA,GACP0V,EAAU/M,EAAOkK,EAAQ,EAAG,MAAM,GAAM,GAAM,GAAO,MACnDhY,GAAuB,KAAZ2P,IACdA,GAAWoI,EAAiBjK,EAAOkK,IAGjClK,EAAM4L,MAjlBO,KAilBoB5L,EAAM4L,KAAK/T,WAAW,GACzDgK,GAAW,IAEXA,GAAW,KAGbA,GAAW7B,EAAM4L,KAErB,CAEA5L,EAAMzM,IAAM8P,EACZrD,EAAM4L,KAAO/J,GAAW,IAC1B,CAkHA,SAASmL,EAAYhN,EAAOvJ,EAAQpB,GAGlC,IAFA,IAAMuS,EAAWvS,EAAW2K,EAAM0J,cAAgB1J,EAAMT,cAE/C1N,EAAQ,EAAGC,EAAS8V,EAAS9V,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CACxE,IAAMyB,EAAOsU,EAAS/V,GAEtB,IAAKyB,EAAKU,YAAcV,EAAKW,cACvBX,EAAKU,YAAkC,WAAlBhE,EAAOyG,IAAyBA,aAAkBnD,EAAKU,eAC5EV,EAAKW,WAAaX,EAAKW,UAAUwC,IAAU,CAW/C,GAVIpB,EACE/B,EAAKe,OAASf,EAAKa,cACrB6L,EAAMzM,IAAMD,EAAKa,cAAcsC,GAE/BuJ,EAAMzM,IAAMD,EAAKC,IAGnByM,EAAMzM,IAAM,IAGVD,EAAKY,UAAW,CAClB,IAAMK,EAAQyL,EAAMgJ,SAAS1V,EAAKC,MAAQD,EAAKc,aAE3CyN,OAAO,EACX,GAAuC,sBAAnCzG,EAAUvI,KAAKS,EAAKY,WACtB2N,EAAUvO,EAAKY,UAAUuC,EAAQlC,YACxB2G,EAAgBrI,KAAKS,EAAKY,UAAWK,GAG9C,MAAM,IAAI5B,EAAc,KAAOW,EAAKC,IAAM,+BAAiCgB,EAAQ,WAFnFsN,EAAUvO,EAAKY,UAAUK,GAAOkC,EAAQlC,EAG1C,CAEAyL,EAAM4L,KAAO/J,CACf,CAEA,OAAO,CACT,CACF,CAEA,OAAO,CACT,CAKA,SAASkL,EAAW/M,EAAOkK,EAAOzT,EAAQwW,EAAO/a,EAASyZ,EAAOuB,GAC/DlN,EAAMzM,IAAM,KACZyM,EAAM4L,KAAOnV,EAERuW,EAAWhN,EAAOvJ,GAAQ,IAC7BuW,EAAWhN,EAAOvJ,GAAQ,GAG5B,IAAMnD,EAAO8H,EAAUvI,KAAKmN,EAAM4L,MAC5BpB,EAAUyC,EAEZA,IACFA,EAASjN,EAAM+I,UAAY,GAAK/I,EAAM+I,UAAYmB,GAGpD,IACIiD,EACAC,EAFEC,EAAyB,oBAAT/Z,GAAuC,mBAATA,EAapD,GATI+Z,IAEFD,GAA+B,KAD/BD,EAAiBnN,EAAM2J,WAAWhW,QAAQ8C,MAIzB,OAAduJ,EAAMzM,KAA8B,MAAdyM,EAAMzM,KAAgB6Z,GAA+B,IAAjBpN,EAAMlD,QAAgBoN,EAAQ,KAC3FhY,GAAU,GAGRkb,GAAapN,EAAM4J,eAAeuD,GACpCnN,EAAM4L,KAAO,QAAUuB,MAClB,CAIL,GAHIE,GAAiBD,IAAcpN,EAAM4J,eAAeuD,KACtDnN,EAAM4J,eAAeuD,IAAkB,GAE5B,oBAAT7Z,EACE2Z,GAA6C,IAAnCtb,OAAOC,KAAKoO,EAAM4L,MAAM9Z,SAvJ5C,SAA4BkO,EAAOkK,EAAOzT,EAAQvE,GAChD,IAAI2P,EAAU,GACRwB,EAAOrD,EAAMzM,IACb+Z,EAAgB3b,OAAOC,KAAK6E,GAGlC,IAAuB,IAAnBuJ,EAAMkJ,SAERoE,EAAcC,eACqB,mBAAnBvN,EAAMkJ,SAEtBoE,EAAcC,KAAKvN,EAAMkJ,eAC3B,GAAWlJ,EAAMkJ,SAEf,MAAM,IAAIvW,EAAc,4CAG1B,IAAA,IAASd,EAAQ,EAAGC,EAASwb,EAAcxb,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CAC7E,IAAI2b,EAAa,GAEZtb,GAAuB,KAAZ2P,IACd2L,GAAcvD,EAAiBjK,EAAOkK,IAGxC,IAAMuD,EAAYH,EAAczb,GAC5B6b,EAAcjX,EAAOgX,GAMzB,GAJIzN,EAAMyJ,WACRiE,EAAc1N,EAAMyJ,SAAS5W,KAAK4D,EAAQgX,EAAWC,IAGlDX,EAAU/M,EAAOkK,EAAQ,EAAGuD,GAAW,GAAM,GAAM,GAAxD,CAIA,IAAME,EAA8B,OAAd3N,EAAMzM,KAA8B,MAAdyM,EAAMzM,KAClCyM,EAAM4L,MAAQ5L,EAAM4L,KAAK9Z,OAAS,KAE9C6b,IACE3N,EAAM4L,MA9qBO,KA8qBoB5L,EAAM4L,KAAK/T,WAAW,GACzD2V,GAAc,IAEdA,GAAc,MAIlBA,GAAcxN,EAAM4L,KAEhB+B,IACFH,GAAcvD,EAAiBjK,EAAOkK,IAGnC6C,EAAU/M,EAAOkK,EAAQ,EAAGwD,GAAa,EAAMC,KAIhD3N,EAAM4L,MA/rBS,KA+rBkB5L,EAAM4L,KAAK/T,WAAW,GACzD2V,GAAc,IAEdA,GAAc,KAMhB3L,GAHA2L,GAAcxN,EAAM4L,KA7BpB,CAiCF,CAEA5L,EAAMzM,IAAM8P,EACZrD,EAAM4L,KAAO/J,GAAW,IAC1B,CAkFQ+L,CAAkB5N,EAAOkK,EAAOlK,EAAM4L,KAAM1Z,GACxCkb,IACFpN,EAAM4L,KAAO,QAAUuB,EAAiBnN,EAAM4L,SAlMxD,SAA2B5L,EAAOkK,EAAOzT,GAKvC,IAJA,IAAIoL,EAAU,GACRwB,EAAOrD,EAAMzM,IACb+Z,EAAgB3b,OAAOC,KAAK6E,GAEzB5E,EAAQ,EAAGC,EAASwb,EAAcxb,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CAC7E,IAAI2b,EAAa,GACD,KAAZ3L,IAAgB2L,GAAc,MAE9BxN,EAAMsJ,eAAckE,GAAc,KAEtC,IAAMC,EAAYH,EAAczb,GAC5B6b,EAAcjX,EAAOgX,GAErBzN,EAAMyJ,WACRiE,EAAc1N,EAAMyJ,SAAS5W,KAAK4D,EAAQgX,EAAWC,IAGlDX,EAAU/M,EAAOkK,EAAOuD,GAAW,GAAO,KAI3CzN,EAAM4L,KAAK9Z,OAAS,OAAM0b,GAAc,MAE5CA,GAAcxN,EAAM4L,MAAQ5L,EAAMsJ,aAAe,IAAM,IAAM,KAAOtJ,EAAMsJ,aAAe,GAAK,KAEzFyD,EAAU/M,EAAOkK,EAAOwD,GAAa,GAAO,KAOjD7L,GAHA2L,GAAcxN,EAAM4L,MAItB,CAEA5L,EAAMzM,IAAM8P,EACZrD,EAAM4L,KAAO,IAAM/J,EAAU,GAC/B,CA+JQgM,CAAiB7N,EAAOkK,EAAOlK,EAAM4L,MACjCwB,IACFpN,EAAM4L,KAAO,QAAUuB,EAAiB,IAAMnN,EAAM4L,YAG1D,GAAoB,mBAATtY,EACL2Z,GAAgC,IAAtBjN,EAAM4L,KAAK9Z,QACnBkO,EAAM6I,gBAAkBqE,GAAchD,EAAQ,EAChD4C,EAAmB9M,EAAOkK,EAAQ,EAAGlK,EAAM4L,KAAM1Z,GAEjD4a,EAAmB9M,EAAOkK,EAAOlK,EAAM4L,KAAM1Z,GAE3Ckb,IACFpN,EAAM4L,KAAO,QAAUuB,EAAiBnN,EAAM4L,SA3QxD,SAA4B5L,EAAOkK,EAAOzT,GAIxC,IAHA,IAAIoL,EAAU,GACRwB,EAAOrD,EAAMzM,IAEV1B,EAAQ,EAAGC,EAAS2E,EAAO3E,OAAQD,EAAQC,EAAQD,GAAS,EAAG,CACtE,IAAIwF,EAAQZ,EAAO5E,GAEfmO,EAAMyJ,WACRpS,EAAQ2I,EAAMyJ,SAAS5W,KAAK4D,EAAQhC,OAAO5C,GAAQwF,KAIjD0V,EAAU/M,EAAOkK,EAAO7S,GAAO,GAAO,SACpB,IAAVA,GACP0V,EAAU/M,EAAOkK,EAAO,MAAM,GAAO,MACxB,KAAZrI,IAAgBA,GAAW,KAAQ7B,EAAMsJ,aAAqB,GAAN,MAC5DzH,GAAW7B,EAAM4L,KAErB,CAEA5L,EAAMzM,IAAM8P,EACZrD,EAAM4L,KAAO,IAAM/J,EAAU,GAC/B,CAwPQiM,CAAkB9N,EAAOkK,EAAOlK,EAAM4L,MAClCwB,IACFpN,EAAM4L,KAAO,QAAUuB,EAAiB,IAAMnN,EAAM4L,WAG1D,IAAoB,oBAATtY,EAIX,IAAoB,uBAATA,EACT,OAAO,EAEP,GAAI0M,EAAM8I,YAAa,OAAO,EAC9B,MAAM,IAAInW,EAAc,0CAA4CW,EACtE,CARoB,MAAd0M,EAAMzM,KACRmY,EAAY1L,EAAOA,EAAM4L,KAAM1B,EAAOyB,EAAOnB,EAOjD,CAEA,GAAkB,OAAdxK,EAAMzM,KAA8B,MAAdyM,EAAMzM,IAAa,CAc3C,IAAIwa,EAASC,UACM,MAAjBhO,EAAMzM,IAAI,GAAayM,EAAMzM,IAAIiE,MAAM,GAAKwI,EAAMzM,KAClDyF,QAAQ,KAAM,OAGd+U,EADmB,MAAjB/N,EAAMzM,IAAI,GACH,IAAMwa,EACkB,uBAAxBA,EAAOvW,MAAM,EAAG,IAChB,KAAOuW,EAAOvW,MAAM,IAEpB,KAAOuW,EAAS,IAG3B/N,EAAM4L,KAAOmC,EAAS,IAAM/N,EAAM4L,IACpC,CACF,CAEA,OAAO,CACT,CAEA,SAASqC,EAAwBxX,EAAQuJ,GACvC,IAAMkO,EAAU,GACVC,EAAoB,GAE1BC,EAAY3X,EAAQyX,EAASC,GAG7B,IADA,IAAMrc,EAASqc,EAAkBrc,OACxBD,EAAQ,EAAGA,EAAQC,EAAQD,GAAS,EAC3CmO,EAAM2J,WAAWrU,KAAK4Y,EAAQC,EAAkBtc,KAElDmO,EAAM4J,eAAiB,IAAIhZ,MAAMkB,EACnC,CAEA,SAASsc,EAAa3X,EAAQyX,EAASC,GACrC,GAAe,OAAX1X,GAAqC,WAAlBzG,EAAOyG,GAAqB,CACjD,IAAM5E,EAAQqc,EAAQva,QAAQ8C,GAC9B,IAAc,IAAV5E,GACuC,IAArCsc,EAAkBxa,QAAQ9B,IAC5Bsc,EAAkB7Y,KAAKzD,QAKzB,GAFAqc,EAAQ5Y,KAAKmB,GAET7F,MAAMC,QAAQ4F,GAChB,IAAA,IAAS8G,EAAI,EAAGzL,EAAS2E,EAAO3E,OAAQyL,EAAIzL,EAAQyL,GAAK,EACvD6Q,EAAY3X,EAAO8G,GAAI2Q,EAASC,QAKlC,IAFA,IAAMb,EAAgB3b,OAAOC,KAAK6E,GAEzB8G,EAAI,EAAGzL,EAASwb,EAAcxb,OAAQyL,EAAIzL,EAAQyL,GAAK,EAC9D6Q,EAAY3X,EAAO6W,EAAc/P,IAAK2Q,EAASC,EAIvD,CACF,QAoBAE,GAAAzC,KAlBA,SAAe/Q,EAAOrH,GAGpB,IAAMwM,EAAQ,IAAIhB,EAFlBxL,EAAUA,GAAW,CAAA,GAIhBwM,EAAMoJ,QAAQ6E,EAAuBpT,EAAOmF,GAEjD,IAAI3I,EAAQwD,EAMZ,OAJImF,EAAMyJ,WACRpS,EAAQ2I,EAAMyJ,SAAS5W,KAAK,CAAE,GAAIwE,GAAS,GAAIA,IAG7C0V,EAAU/M,EAAO,EAAG3I,GAAO,GAAM,GAAc2I,EAAM4L,KAAO,KAEzD,EACT,6CCp6BA,IAAMxD,EAASjV,KACTkb,EAAS1Z,KAEf,SAAS2Z,EAASC,EAAMC,GACtB,OAAO,WACL,MAAM,IAAI5b,MAAM,iBAAmB2b,EAAO,sCAC1BC,EAAK,2CAEzB,QAEAC,EAAA/Z,KAAsB2B,IACtBoY,EAAAvZ,OAAwBoB,IACxBmY,EAAAC,gBAAiCxV,KACjCuV,EAAAE,YAA6B7S,KAC7B2S,EAAAG,YAA6B7S,KAC7B0S,EAAAjR,eAAgCqR,KAChCJ,EAAAnG,KAAsBF,EAAOE,KAC7BmG,EAAApG,QAAyBD,EAAOC,QAChCoG,EAAA7C,KAAsByC,EAAOzC,KAC7B6C,EAAA9b,cAA+Bmc,IAG/BL,EAAAM,MAAuB,CACrBjX,OAAQkX,KACRxW,MAAOyW,KACPxb,IAAKyb,KACLC,KAAMC,KACNzT,MAAO0T,KACPzT,IAAK0T,KACLhW,UAAWiW,KACXxY,KAAMyY,KACN9X,IAAK+X,KACLlV,MAAOmV,KACPrU,KAAMsU,KACNxZ,IAAKyZ,KACL1Z,IAAK2Z,KAIPpB,EAAAqB,SAA0BxB,EAAQ,WAAY,QAC9CG,EAAAsB,YAA6BzB,EAAQ,cAAe,WACpDG,EAAAuB,SAA0B1B,EAAQ,WAAY,cCxC5C5Z,GAcEub,GAdFvb,KACAQ,GAaE+a,GAbF/a,OACAwZ,GAYEuB,GAZFvB,gBACAC,GAWEsB,GAXFtB,YACAC,GAUEqB,GAVFrB,YACApR,GASEyS,GATFzS,eACA8K,GAQE2H,GARF3H,KACAD,GAOE4H,GAPF5H,QACAuD,GAMEqE,GANFrE,KACAjZ,GAKEsd,GALFtd,cACAoc,GAIEkB,GAJFlB,MACAe,GAGEG,GAHFH,SACAC,GAEEE,GAFFF,YACAC,GACEC,GADFD"}function getDefaultExportFromCjs(x) {
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
}
var jsYaml = {};
var loader = {};
var common = {};
var hasRequiredCommon;
function requireCommon() {
  if (hasRequiredCommon) return common;
  hasRequiredCommon = 1;
  function isNothing(subject) {
    return typeof subject === "undefined" || subject === null;
  }
  function isObject(subject) {
    return typeof subject === "object" && subject !== null;
  }
  function toArray(sequence) {
    if (Array.isArray(sequence)) return sequence;
    else if (isNothing(sequence)) return [];
    return [sequence];
  }
  function extend(target, source) {
    if (source) {
      const sourceKeys = Object.keys(source);
      for (let index = 0, length = sourceKeys.length; index < length; index += 1) {
        const key = sourceKeys[index];
        target[key] = source[key];
      }
    }
    return target;
  }
  function repeat(string, count) {
    let result = "";
    for (let cycle = 0; cycle < count; cycle += 1) {
      result += string;
    }
    return result;
  }
  function isNegativeZero(number) {
    return number === 0 && Number.NEGATIVE_INFINITY === 1 / number;
  }
  common.isNothing = isNothing;
  common.isObject = isObject;
  common.toArray = toArray;
  common.repeat = repeat;
  common.isNegativeZero = isNegativeZero;
  common.extend = extend;
  return common;
}
var exception;
var hasRequiredException;
function requireException() {
  if (hasRequiredException) return exception;
  hasRequiredException = 1;
  function formatError(exception2, compact) {
    let where = "";
    const message = exception2.reason || "(unknown reason)";
    if (!exception2.mark) return message;
    if (exception2.mark.name) {
      where += 'in "' + exception2.mark.name + '" ';
    }
    where += "(" + (exception2.mark.line + 1) + ":" + (exception2.mark.column + 1) + ")";
    if (!compact && exception2.mark.snippet) {
      where += "\n\n" + exception2.mark.snippet;
    }
    return message + " " + where;
  }
  function YAMLException2(reason, mark) {
    Error.call(this);
    this.name = "YAMLException";
    this.reason = reason;
    this.mark = mark;
    this.message = formatError(this, false);
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, this.constructor);
    } else {
      this.stack = new Error().stack || "";
    }
  }
  YAMLException2.prototype = Object.create(Error.prototype);
  YAMLException2.prototype.constructor = YAMLException2;
  YAMLException2.prototype.toString = function toString(compact) {
    return this.name + ": " + formatError(this, compact);
  };
  exception = YAMLException2;
  return exception;
}
var snippet;
var hasRequiredSnippet;
function requireSnippet() {
  if (hasRequiredSnippet) return snippet;
  hasRequiredSnippet = 1;
  const common2 = requireCommon();
  function getLine(buffer, lineStart, lineEnd, position, maxLineLength) {
    let head = "";
    let tail = "";
    const maxHalfLength = Math.floor(maxLineLength / 2) - 1;
    if (position - lineStart > maxHalfLength) {
      head = " ... ";
      lineStart = position - maxHalfLength + head.length;
    }
    if (lineEnd - position > maxHalfLength) {
      tail = " ...";
      lineEnd = position + maxHalfLength - tail.length;
    }
    return {
      str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "→") + tail,
      pos: position - lineStart + head.length
      // relative position
    };
  }
  function padStart(string, max) {
    return common2.repeat(" ", max - string.length) + string;
  }
  function makeSnippet(mark, options) {
    options = Object.create(options || null);
    if (!mark.buffer) return null;
    if (!options.maxLength) options.maxLength = 79;
    if (typeof options.indent !== "number") options.indent = 1;
    if (typeof options.linesBefore !== "number") options.linesBefore = 3;
    if (typeof options.linesAfter !== "number") options.linesAfter = 2;
    const re = /\r?\n|\r|\0/g;
    const lineStarts = [0];
    const lineEnds = [];
    let match;
    let foundLineNo = -1;
    while (match = re.exec(mark.buffer)) {
      lineEnds.push(match.index);
      lineStarts.push(match.index + match[0].length);
      if (mark.position <= match.index && foundLineNo < 0) {
        foundLineNo = lineStarts.length - 2;
      }
    }
    if (foundLineNo < 0) foundLineNo = lineStarts.length - 1;
    let result = "";
    const lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length;
    const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);
    for (let i = 1; i <= options.linesBefore; i++) {
      if (foundLineNo - i < 0) break;
      const line2 = getLine(
        mark.buffer,
        lineStarts[foundLineNo - i],
        lineEnds[foundLineNo - i],
        mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
        maxLineLength
      );
      result = common2.repeat(" ", options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) + " | " + line2.str + "\n" + result;
    }
    const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength);
    result += common2.repeat(" ", options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + " | " + line.str + "\n";
    result += common2.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n";
    for (let i = 1; i <= options.linesAfter; i++) {
      if (foundLineNo + i >= lineEnds.length) break;
      const line2 = getLine(
        mark.buffer,
        lineStarts[foundLineNo + i],
        lineEnds[foundLineNo + i],
        mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
        maxLineLength
      );
      result += common2.repeat(" ", options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) + " | " + line2.str + "\n";
    }
    return result.replace(/\n$/, "");
  }
  snippet = makeSnippet;
  return snippet;
}
var type;
var hasRequiredType;
function requireType() {
  if (hasRequiredType) return type;
  hasRequiredType = 1;
  const YAMLException2 = requireException();
  const TYPE_CONSTRUCTOR_OPTIONS = [
    "kind",
    "multi",
    "resolve",
    "construct",
    "instanceOf",
    "predicate",
    "represent",
    "representName",
    "defaultStyle",
    "styleAliases"
  ];
  const YAML_NODE_KINDS = [
    "scalar",
    "sequence",
    "mapping"
  ];
  function compileStyleAliases(map2) {
    const result = {};
    if (map2 !== null) {
      Object.keys(map2).forEach(function(style) {
        map2[style].forEach(function(alias) {
          result[String(alias)] = style;
        });
      });
    }
    return result;
  }
  function Type2(tag, options) {
    options = options || {};
    Object.keys(options).forEach(function(name) {
      if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
        throw new YAMLException2('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
      }
    });
    this.options = options;
    this.tag = tag;
    this.kind = options["kind"] || null;
    this.resolve = options["resolve"] || function() {
      return true;
    };
    this.construct = options["construct"] || function(data) {
      return data;
    };
    this.instanceOf = options["instanceOf"] || null;
    this.predicate = options["predicate"] || null;
    this.represent = options["represent"] || null;
    this.representName = options["representName"] || null;
    this.defaultStyle = options["defaultStyle"] || null;
    this.multi = options["multi"] || false;
    this.styleAliases = compileStyleAliases(options["styleAliases"] || null);
    if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
      throw new YAMLException2('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
    }
  }
  type = Type2;
  return type;
}
var schema;
var hasRequiredSchema;
function requireSchema() {
  if (hasRequiredSchema) return schema;
  hasRequiredSchema = 1;
  const YAMLException2 = requireException();
  const Type2 = requireType();
  function compileList(schema2, name) {
    const result = [];
    schema2[name].forEach(function(currentType) {
      let newIndex = result.length;
      result.forEach(function(previousType, previousIndex) {
        if (previousType.tag === currentType.tag && previousType.kind === currentType.kind && previousType.multi === currentType.multi) {
          newIndex = previousIndex;
        }
      });
      result[newIndex] = currentType;
    });
    return result;
  }
  function compileMap() {
    const result = {
      scalar: {},
      sequence: {},
      mapping: {},
      fallback: {},
      multi: {
        scalar: [],
        sequence: [],
        mapping: [],
        fallback: []
      }
    };
    function collectType(type2) {
      if (type2.multi) {
        result.multi[type2.kind].push(type2);
        result.multi["fallback"].push(type2);
      } else {
        result[type2.kind][type2.tag] = result["fallback"][type2.tag] = type2;
      }
    }
    for (let index = 0, length = arguments.length; index < length; index += 1) {
      arguments[index].forEach(collectType);
    }
    return result;
  }
  function Schema2(definition) {
    return this.extend(definition);
  }
  Schema2.prototype.extend = function extend(definition) {
    let implicit = [];
    let explicit = [];
    if (definition instanceof Type2) {
      explicit.push(definition);
    } else if (Array.isArray(definition)) {
      explicit = explicit.concat(definition);
    } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {
      if (definition.implicit) implicit = implicit.concat(definition.implicit);
      if (definition.explicit) explicit = explicit.concat(definition.explicit);
    } else {
      throw new YAMLException2("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");
    }
    implicit.forEach(function(type2) {
      if (!(type2 instanceof Type2)) {
        throw new YAMLException2("Specified list of YAML types (or a single Type object) contains a non-Type object.");
      }
      if (type2.loadKind && type2.loadKind !== "scalar") {
        throw new YAMLException2("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");
      }
      if (type2.multi) {
        throw new YAMLException2("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.");
      }
    });
    explicit.forEach(function(type2) {
      if (!(type2 instanceof Type2)) {
        throw new YAMLException2("Specified list of YAML types (or a single Type object) contains a non-Type object.");
      }
    });
    const result = Object.create(Schema2.prototype);
    result.implicit = (this.implicit || []).concat(implicit);
    result.explicit = (this.explicit || []).concat(explicit);
    result.compiledImplicit = compileList(result, "implicit");
    result.compiledExplicit = compileList(result, "explicit");
    result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit);
    return result;
  };
  schema = Schema2;
  return schema;
}
var str;
var hasRequiredStr;
function requireStr() {
  if (hasRequiredStr) return str;
  hasRequiredStr = 1;
  const Type2 = requireType();
  str = new Type2("tag:yaml.org,2002:str", {
    kind: "scalar",
    construct: function(data) {
      return data !== null ? data : "";
    }
  });
  return str;
}
var seq;
var hasRequiredSeq;
function requireSeq() {
  if (hasRequiredSeq) return seq;
  hasRequiredSeq = 1;
  const Type2 = requireType();
  seq = new Type2("tag:yaml.org,2002:seq", {
    kind: "sequence",
    construct: function(data) {
      return data !== null ? data : [];
    }
  });
  return seq;
}
var map;
var hasRequiredMap;
function requireMap() {
  if (hasRequiredMap) return map;
  hasRequiredMap = 1;
  const Type2 = requireType();
  map = new Type2("tag:yaml.org,2002:map", {
    kind: "mapping",
    construct: function(data) {
      return data !== null ? data : {};
    }
  });
  return map;
}
var failsafe;
var hasRequiredFailsafe;
function requireFailsafe() {
  if (hasRequiredFailsafe) return failsafe;
  hasRequiredFailsafe = 1;
  const Schema2 = requireSchema();
  failsafe = new Schema2({
    explicit: [
      requireStr(),
      requireSeq(),
      requireMap()
    ]
  });
  return failsafe;
}
var _null;
var hasRequired_null;
function require_null() {
  if (hasRequired_null) return _null;
  hasRequired_null = 1;
  const Type2 = requireType();
  function resolveYamlNull(data) {
    if (data === null) return true;
    const max = data.length;
    return max === 1 && data === "~" || max === 4 && (data === "null" || data === "Null" || data === "NULL");
  }
  function constructYamlNull() {
    return null;
  }
  function isNull(object) {
    return object === null;
  }
  _null = new Type2("tag:yaml.org,2002:null", {
    kind: "scalar",
    resolve: resolveYamlNull,
    construct: constructYamlNull,
    predicate: isNull,
    represent: {
      canonical: function() {
        return "~";
      },
      lowercase: function() {
        return "null";
      },
      uppercase: function() {
        return "NULL";
      },
      camelcase: function() {
        return "Null";
      },
      empty: function() {
        return "";
      }
    },
    defaultStyle: "lowercase"
  });
  return _null;
}
var bool;
var hasRequiredBool;
function requireBool() {
  if (hasRequiredBool) return bool;
  hasRequiredBool = 1;
  const Type2 = requireType();
  function resolveYamlBoolean(data) {
    if (data === null) return false;
    const max = data.length;
    return max === 4 && (data === "true" || data === "True" || data === "TRUE") || max === 5 && (data === "false" || data === "False" || data === "FALSE");
  }
  function constructYamlBoolean(data) {
    return data === "true" || data === "True" || data === "TRUE";
  }
  function isBoolean(object) {
    return Object.prototype.toString.call(object) === "[object Boolean]";
  }
  bool = new Type2("tag:yaml.org,2002:bool", {
    kind: "scalar",
    resolve: resolveYamlBoolean,
    construct: constructYamlBoolean,
    predicate: isBoolean,
    represent: {
      lowercase: function(object) {
        return object ? "true" : "false";
      },
      uppercase: function(object) {
        return object ? "TRUE" : "FALSE";
      },
      camelcase: function(object) {
        return object ? "True" : "False";
      }
    },
    defaultStyle: "lowercase"
  });
  return bool;
}
var int;
var hasRequiredInt;
function requireInt() {
  if (hasRequiredInt) return int;
  hasRequiredInt = 1;
  const common2 = requireCommon();
  const Type2 = requireType();
  function isHexCode(c) {
    return c >= 48 && c <= 57 || c >= 65 && c <= 70 || c >= 97 && c <= 102;
  }
  function isOctCode(c) {
    return c >= 48 && c <= 55;
  }
  function isDecCode(c) {
    return c >= 48 && c <= 57;
  }
  function resolveYamlInteger(data) {
    if (data === null) return false;
    const max = data.length;
    let index = 0;
    let hasDigits = false;
    if (!max) return false;
    let ch = data[index];
    if (ch === "-" || ch === "+") {
      ch = data[++index];
    }
    if (ch === "0") {
      if (index + 1 === max) return true;
      ch = data[++index];
      if (ch === "b") {
        index++;
        for (; index < max; index++) {
          ch = data[index];
          if (ch !== "0" && ch !== "1") return false;
          hasDigits = true;
        }
        return hasDigits && isFinite(parseYamlInteger(data));
      }
      if (ch === "x") {
        index++;
        for (; index < max; index++) {
          if (!isHexCode(data.charCodeAt(index))) return false;
          hasDigits = true;
        }
        return hasDigits && isFinite(parseYamlInteger(data));
      }
      if (ch === "o") {
        index++;
        for (; index < max; index++) {
          if (!isOctCode(data.charCodeAt(index))) return false;
          hasDigits = true;
        }
        return hasDigits && isFinite(parseYamlInteger(data));
      }
    }
    for (; index < max; index++) {
      if (!isDecCode(data.charCodeAt(index))) {
        return false;
      }
      hasDigits = true;
    }
    if (!hasDigits) return false;
    return isFinite(parseYamlInteger(data));
  }
  function parseYamlInteger(data) {
    let value = data;
    let sign = 1;
    let ch = value[0];
    if (ch === "-" || ch === "+") {
      if (ch === "-") sign = -1;
      value = value.slice(1);
      ch = value[0];
    }
    if (value === "0") return 0;
    if (ch === "0") {
      if (value[1] === "b") return sign * parseInt(value.slice(2), 2);
      if (value[1] === "x") return sign * parseInt(value.slice(2), 16);
      if (value[1] === "o") return sign * parseInt(value.slice(2), 8);
    }
    return sign * parseInt(value, 10);
  }
  function constructYamlInteger(data) {
    return parseYamlInteger(data);
  }
  function isInteger(object) {
    return Object.prototype.toString.call(object) === "[object Number]" && (object % 1 === 0 && !common2.isNegativeZero(object));
  }
  int = new Type2("tag:yaml.org,2002:int", {
    kind: "scalar",
    resolve: resolveYamlInteger,
    construct: constructYamlInteger,
    predicate: isInteger,
    represent: {
      binary: function(obj) {
        return obj >= 0 ? "0b" + obj.toString(2) : "-0b" + obj.toString(2).slice(1);
      },
      octal: function(obj) {
        return obj >= 0 ? "0o" + obj.toString(8) : "-0o" + obj.toString(8).slice(1);
      },
      decimal: function(obj) {
        return obj.toString(10);
      },
      hexadecimal: function(obj) {
        return obj >= 0 ? "0x" + obj.toString(16).toUpperCase() : "-0x" + obj.toString(16).toUpperCase().slice(1);
      }
    },
    defaultStyle: "decimal",
    styleAliases: {
      binary: [2, "bin"],
      octal: [8, "oct"],
      decimal: [10, "dec"],
      hexadecimal: [16, "hex"]
    }
  });
  return int;
}
var float;
var hasRequiredFloat;
function requireFloat() {
  if (hasRequiredFloat) return float;
  hasRequiredFloat = 1;
  const common2 = requireCommon();
  const Type2 = requireType();
  const YAML_FLOAT_PATTERN = new RegExp(
    // 2.5e4, 2.5 and integers
    "^(?:[-+]?(?:[0-9]+)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"
  );
  const YAML_FLOAT_SPECIAL_PATTERN = new RegExp(
    "^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"
  );
  function resolveYamlFloat(data) {
    if (data === null) return false;
    if (!YAML_FLOAT_PATTERN.test(data)) {
      return false;
    }
    if (isFinite(parseFloat(data, 10))) {
      return true;
    }
    return YAML_FLOAT_SPECIAL_PATTERN.test(data);
  }
  function constructYamlFloat(data) {
    let value = data.toLowerCase();
    const sign = value[0] === "-" ? -1 : 1;
    if ("+-".indexOf(value[0]) >= 0) {
      value = value.slice(1);
    }
    if (value === ".inf") {
      return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
    } else if (value === ".nan") {
      return NaN;
    }
    return sign * parseFloat(value, 10);
  }
  const SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
  function representYamlFloat(object, style) {
    if (isNaN(object)) {
      switch (style) {
        case "lowercase":
          return ".nan";
        case "uppercase":
          return ".NAN";
        case "camelcase":
          return ".NaN";
      }
    } else if (Number.POSITIVE_INFINITY === object) {
      switch (style) {
        case "lowercase":
          return ".inf";
        case "uppercase":
          return ".INF";
        case "camelcase":
          return ".Inf";
      }
    } else if (Number.NEGATIVE_INFINITY === object) {
      switch (style) {
        case "lowercase":
          return "-.inf";
        case "uppercase":
          return "-.INF";
        case "camelcase":
          return "-.Inf";
      }
    } else if (common2.isNegativeZero(object)) {
      return "-0.0";
    }
    const res = object.toString(10);
    return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace("e", ".e") : res;
  }
  function isFloat(object) {
    return Object.prototype.toString.call(object) === "[object Number]" && (object % 1 !== 0 || common2.isNegativeZero(object));
  }
  float = new Type2("tag:yaml.org,2002:float", {
    kind: "scalar",
    resolve: resolveYamlFloat,
    construct: constructYamlFloat,
    predicate: isFloat,
    represent: representYamlFloat,
    defaultStyle: "lowercase"
  });
  return float;
}
var json;
var hasRequiredJson;
function requireJson() {
  if (hasRequiredJson) return json;
  hasRequiredJson = 1;
  json = requireFailsafe().extend({
    implicit: [
      require_null(),
      requireBool(),
      requireInt(),
      requireFloat()
    ]
  });
  return json;
}
var core;
var hasRequiredCore;
function requireCore() {
  if (hasRequiredCore) return core;
  hasRequiredCore = 1;
  core = requireJson();
  return core;
}
var timestamp;
var hasRequiredTimestamp;
function requireTimestamp() {
  if (hasRequiredTimestamp) return timestamp;
  hasRequiredTimestamp = 1;
  const Type2 = requireType();
  const YAML_DATE_REGEXP = new RegExp(
    "^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"
  );
  const YAML_TIMESTAMP_REGEXP = new RegExp(
    "^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"
  );
  function resolveYamlTimestamp(data) {
    if (data === null) return false;
    if (YAML_DATE_REGEXP.exec(data) !== null) return true;
    if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
    return false;
  }
  function constructYamlTimestamp(data) {
    let fraction = 0;
    let delta = null;
    let match = YAML_DATE_REGEXP.exec(data);
    if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);
    if (match === null) throw new Error("Date resolve error");
    const year = +match[1];
    const month = +match[2] - 1;
    const day = +match[3];
    if (!match[4]) {
      return new Date(Date.UTC(year, month, day));
    }
    const hour = +match[4];
    const minute = +match[5];
    const second = +match[6];
    if (match[7]) {
      fraction = match[7].slice(0, 3);
      while (fraction.length < 3) {
        fraction += "0";
      }
      fraction = +fraction;
    }
    if (match[9]) {
      const tzHour = +match[10];
      const tzMinute = +(match[11] || 0);
      delta = (tzHour * 60 + tzMinute) * 6e4;
      if (match[9] === "-") delta = -delta;
    }
    const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));
    if (delta) date.setTime(date.getTime() - delta);
    return date;
  }
  function representYamlTimestamp(object) {
    return object.toISOString();
  }
  timestamp = new Type2("tag:yaml.org,2002:timestamp", {
    kind: "scalar",
    resolve: resolveYamlTimestamp,
    construct: constructYamlTimestamp,
    instanceOf: Date,
    represent: representYamlTimestamp
  });
  return timestamp;
}
var merge;
var hasRequiredMerge;
function requireMerge() {
  if (hasRequiredMerge) return merge;
  hasRequiredMerge = 1;
  const Type2 = requireType();
  function resolveYamlMerge(data) {
    return data === "<<" || data === null;
  }
  merge = new Type2("tag:yaml.org,2002:merge", {
    kind: "scalar",
    resolve: resolveYamlMerge
  });
  return merge;
}
var binary;
var hasRequiredBinary;
function requireBinary() {
  if (hasRequiredBinary) return binary;
  hasRequiredBinary = 1;
  const Type2 = requireType();
  const BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";
  function resolveYamlBinary(data) {
    if (data === null) return false;
    let bitlen = 0;
    const max = data.length;
    const map2 = BASE64_MAP;
    for (let idx = 0; idx < max; idx++) {
      const code = map2.indexOf(data.charAt(idx));
      if (code > 64) continue;
      if (code < 0) return false;
      bitlen += 6;
    }
    return bitlen % 8 === 0;
  }
  function constructYamlBinary(data) {
    const input = data.replace(/[\r\n=]/g, "");
    const max = input.length;
    const map2 = BASE64_MAP;
    let bits = 0;
    const result = [];
    for (let idx = 0; idx < max; idx++) {
      if (idx % 4 === 0 && idx) {
        result.push(bits >> 16 & 255);
        result.push(bits >> 8 & 255);
        result.push(bits & 255);
      }
      bits = bits << 6 | map2.indexOf(input.charAt(idx));
    }
    const tailbits = max % 4 * 6;
    if (tailbits === 0) {
      result.push(bits >> 16 & 255);
      result.push(bits >> 8 & 255);
      result.push(bits & 255);
    } else if (tailbits === 18) {
      result.push(bits >> 10 & 255);
      result.push(bits >> 2 & 255);
    } else if (tailbits === 12) {
      result.push(bits >> 4 & 255);
    }
    return new Uint8Array(result);
  }
  function representYamlBinary(object) {
    let result = "";
    let bits = 0;
    const max = object.length;
    const map2 = BASE64_MAP;
    for (let idx = 0; idx < max; idx++) {
      if (idx % 3 === 0 && idx) {
        result += map2[bits >> 18 & 63];
        result += map2[bits >> 12 & 63];
        result += map2[bits >> 6 & 63];
        result += map2[bits & 63];
      }
      bits = (bits << 8) + object[idx];
    }
    const tail = max % 3;
    if (tail === 0) {
      result += map2[bits >> 18 & 63];
      result += map2[bits >> 12 & 63];
      result += map2[bits >> 6 & 63];
      result += map2[bits & 63];
    } else if (tail === 2) {
      result += map2[bits >> 10 & 63];
      result += map2[bits >> 4 & 63];
      result += map2[bits << 2 & 63];
      result += map2[64];
    } else if (tail === 1) {
      result += map2[bits >> 2 & 63];
      result += map2[bits << 4 & 63];
      result += map2[64];
      result += map2[64];
    }
    return result;
  }
  function isBinary(obj) {
    return Object.prototype.toString.call(obj) === "[object Uint8Array]";
  }
  binary = new Type2("tag:yaml.org,2002:binary", {
    kind: "scalar",
    resolve: resolveYamlBinary,
    construct: constructYamlBinary,
    predicate: isBinary,
    represent: representYamlBinary
  });
  return binary;
}
var omap;
var hasRequiredOmap;
function requireOmap() {
  if (hasRequiredOmap) return omap;
  hasRequiredOmap = 1;
  const Type2 = requireType();
  const _hasOwnProperty = Object.prototype.hasOwnProperty;
  const _toString = Object.prototype.toString;
  function resolveYamlOmap(data) {
    if (data === null) return true;
    const objectKeys = {};
    const object = data;
    for (let index = 0, length = object.length; index < length; index += 1) {
      const pair = object[index];
      let pairHasKey = false;
      if (_toString.call(pair) !== "[object Object]") return false;
      let pairKey;
      for (pairKey in pair) {
        if (_hasOwnProperty.call(pair, pairKey)) {
          if (!pairHasKey) pairHasKey = true;
          else return false;
        }
      }
      if (!pairHasKey) return false;
      if (_hasOwnProperty.call(objectKeys, pairKey)) return false;
      Object.defineProperty(objectKeys, pairKey, { value: true });
    }
    return true;
  }
  function constructYamlOmap(data) {
    return data !== null ? data : [];
  }
  omap = new Type2("tag:yaml.org,2002:omap", {
    kind: "sequence",
    resolve: resolveYamlOmap,
    construct: constructYamlOmap
  });
  return omap;
}
var pairs;
var hasRequiredPairs;
function requirePairs() {
  if (hasRequiredPairs) return pairs;
  hasRequiredPairs = 1;
  const Type2 = requireType();
  const _toString = Object.prototype.toString;
  function resolveYamlPairs(data) {
    if (data === null) return true;
    const object = data;
    const result = new Array(object.length);
    for (let index = 0, length = object.length; index < length; index += 1) {
      const pair = object[index];
      if (_toString.call(pair) !== "[object Object]") return false;
      const keys = Object.keys(pair);
      if (keys.length !== 1) return false;
      result[index] = [keys[0], pair[keys[0]]];
    }
    return true;
  }
  function constructYamlPairs(data) {
    if (data === null) return [];
    const object = data;
    const result = new Array(object.length);
    for (let index = 0, length = object.length; index < length; index += 1) {
      const pair = object[index];
      const keys = Object.keys(pair);
      result[index] = [keys[0], pair[keys[0]]];
    }
    return result;
  }
  pairs = new Type2("tag:yaml.org,2002:pairs", {
    kind: "sequence",
    resolve: resolveYamlPairs,
    construct: constructYamlPairs
  });
  return pairs;
}
var set;
var hasRequiredSet;
function requireSet() {
  if (hasRequiredSet) return set;
  hasRequiredSet = 1;
  const Type2 = requireType();
  const _hasOwnProperty = Object.prototype.hasOwnProperty;
  function resolveYamlSet(data) {
    if (data === null) return true;
    const object = data;
    for (const key in object) {
      if (_hasOwnProperty.call(object, key)) {
        if (object[key] !== null) return false;
      }
    }
    return true;
  }
  function constructYamlSet(data) {
    return data !== null ? data : {};
  }
  set = new Type2("tag:yaml.org,2002:set", {
    kind: "mapping",
    resolve: resolveYamlSet,
    construct: constructYamlSet
  });
  return set;
}
var _default;
var hasRequired_default;
function require_default() {
  if (hasRequired_default) return _default;
  hasRequired_default = 1;
  _default = requireCore().extend({
    implicit: [
      requireTimestamp(),
      requireMerge()
    ],
    explicit: [
      requireBinary(),
      requireOmap(),
      requirePairs(),
      requireSet()
    ]
  });
  return _default;
}
var hasRequiredLoader;
function requireLoader() {
  if (hasRequiredLoader) return loader;
  hasRequiredLoader = 1;
  const common2 = requireCommon();
  const YAMLException2 = requireException();
  const makeSnippet = requireSnippet();
  const DEFAULT_SCHEMA2 = require_default();
  const _hasOwnProperty = Object.prototype.hasOwnProperty;
  const CONTEXT_FLOW_IN = 1;
  const CONTEXT_FLOW_OUT = 2;
  const CONTEXT_BLOCK_IN = 3;
  const CONTEXT_BLOCK_OUT = 4;
  const CHOMPING_CLIP = 1;
  const CHOMPING_STRIP = 2;
  const CHOMPING_KEEP = 3;
  const PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
  const PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
  const PATTERN_FLOW_INDICATORS = /[,\[\]{}]/;
  const PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/;
  const PATTERN_TAG_URI = /^(?:!|[^,\[\]{}])(?:%[0-9a-f]{2}|[0-9a-z\-#;/?:@&=+$,_.!~*'()\[\]])*$/i;
  function _class(obj) {
    return Object.prototype.toString.call(obj);
  }
  function isEol(c) {
    return c === 10 || c === 13;
  }
  function isWhiteSpace(c) {
    return c === 9 || c === 32;
  }
  function isWsOrEol(c) {
    return c === 9 || c === 32 || c === 10 || c === 13;
  }
  function isFlowIndicator(c) {
    return c === 44 || c === 91 || c === 93 || c === 123 || c === 125;
  }
  function fromHexCode(c) {
    if (c >= 48 && c <= 57) {
      return c - 48;
    }
    const lc = c | 32;
    if (lc >= 97 && lc <= 102) {
      return lc - 97 + 10;
    }
    return -1;
  }
  function escapedHexLen(c) {
    if (c === 120) {
      return 2;
    }
    if (c === 117) {
      return 4;
    }
    if (c === 85) {
      return 8;
    }
    return 0;
  }
  function fromDecimalCode(c) {
    if (c >= 48 && c <= 57) {
      return c - 48;
    }
    return -1;
  }
  function simpleEscapeSequence(c) {
    switch (c) {
      case 48:
        return "\0";
      case 97:
        return "\x07";
      case 98:
        return "\b";
      case 116:
        return "	";
      case 9:
        return "	";
      case 110:
        return "\n";
      case 118:
        return "\v";
      case 102:
        return "\f";
      case 114:
        return "\r";
      case 101:
        return "\x1B";
      case 32:
        return " ";
      case 34:
        return '"';
      case 47:
        return "/";
      case 92:
        return "\\";
      case 78:
        return "";
      case 95:
        return " ";
      case 76:
        return "\u2028";
      case 80:
        return "\u2029";
      default:
        return "";
    }
  }
  function charFromCodepoint(c) {
    if (c <= 65535) {
      return String.fromCharCode(c);
    }
    return String.fromCharCode(
      (c - 65536 >> 10) + 55296,
      (c - 65536 & 1023) + 56320
    );
  }
  function setProperty(object, key, value) {
    if (key === "__proto__") {
      Object.defineProperty(object, key, {
        configurable: true,
        enumerable: true,
        writable: true,
        value
      });
    } else {
      object[key] = value;
    }
  }
  const simpleEscapeCheck = new Array(256);
  const simpleEscapeMap = new Array(256);
  for (let i = 0; i < 256; i++) {
    simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;
    simpleEscapeMap[i] = simpleEscapeSequence(i);
  }
  function State(input, options) {
    this.input = input;
    this.filename = options["filename"] || null;
    this.schema = options["schema"] || DEFAULT_SCHEMA2;
    this.onWarning = options["onWarning"] || null;
    this.legacy = options["legacy"] || false;
    this.json = options["json"] || false;
    this.listener = options["listener"] || null;
    this.maxDepth = typeof options["maxDepth"] === "number" ? options["maxDepth"] : 100;
    this.maxTotalMergeKeys = typeof options["maxTotalMergeKeys"] === "number" ? options["maxTotalMergeKeys"] : 1e4;
    this.implicitTypes = this.schema.compiledImplicit;
    this.typeMap = this.schema.compiledTypeMap;
    this.length = input.length;
    this.position = 0;
    this.line = 0;
    this.lineStart = 0;
    this.lineIndent = 0;
    this.depth = 0;
    this.totalMergeKeys = 0;
    this.firstTabInLine = -1;
    this.documents = [];
    this.anchorMapTransactions = [];
  }
  function generateError(state, message) {
    const mark = {
      name: state.filename,
      buffer: state.input.slice(0, -1),
      // omit trailing \0
      position: state.position,
      line: state.line,
      column: state.position - state.lineStart
    };
    mark.snippet = makeSnippet(mark);
    return new YAMLException2(message, mark);
  }
  function throwError(state, message) {
    throw generateError(state, message);
  }
  function throwWarning(state, message) {
    if (state.onWarning) {
      state.onWarning.call(null, generateError(state, message));
    }
  }
  function storeAnchor(state, name, value) {
    const transactions = state.anchorMapTransactions;
    if (transactions.length !== 0) {
      const transaction = transactions[transactions.length - 1];
      if (!_hasOwnProperty.call(transaction, name)) {
        transaction[name] = {
          existed: _hasOwnProperty.call(state.anchorMap, name),
          value: state.anchorMap[name]
        };
      }
    }
    state.anchorMap[name] = value;
  }
  function beginAnchorTransaction(state) {
    state.anchorMapTransactions.push(/* @__PURE__ */ Object.create(null));
  }
  function commitAnchorTransaction(state) {
    const transaction = state.anchorMapTransactions.pop();
    const transactions = state.anchorMapTransactions;
    if (transactions.length === 0) return;
    const parent = transactions[transactions.length - 1];
    const names = Object.keys(transaction);
    for (let index = 0, length = names.length; index < length; index += 1) {
      const name = names[index];
      if (!_hasOwnProperty.call(parent, name)) {
        parent[name] = transaction[name];
      }
    }
  }
  function rollbackAnchorTransaction(state) {
    const transaction = state.anchorMapTransactions.pop();
    const names = Object.keys(transaction);
    for (let index = names.length - 1; index >= 0; index -= 1) {
      const entry = transaction[names[index]];
      if (entry.existed) {
        state.anchorMap[names[index]] = entry.value;
      } else {
        delete state.anchorMap[names[index]];
      }
    }
  }
  function snapshotState(state) {
    return {
      position: state.position,
      line: state.line,
      lineStart: state.lineStart,
      lineIndent: state.lineIndent,
      firstTabInLine: state.firstTabInLine,
      tag: state.tag,
      anchor: state.anchor,
      kind: state.kind,
      result: state.result
    };
  }
  function restoreState(state, snapshot) {
    state.position = snapshot.position;
    state.line = snapshot.line;
    state.lineStart = snapshot.lineStart;
    state.lineIndent = snapshot.lineIndent;
    state.firstTabInLine = snapshot.firstTabInLine;
    state.tag = snapshot.tag;
    state.anchor = snapshot.anchor;
    state.kind = snapshot.kind;
    state.result = snapshot.result;
  }
  const directiveHandlers = {
    YAML: function handleYamlDirective(state, name, args) {
      if (state.version !== null) {
        throwError(state, "duplication of %YAML directive");
      }
      if (args.length !== 1) {
        throwError(state, "YAML directive accepts exactly one argument");
      }
      const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);
      if (match === null) {
        throwError(state, "ill-formed argument of the YAML directive");
      }
      const major = parseInt(match[1], 10);
      const minor = parseInt(match[2], 10);
      if (major !== 1) {
        throwError(state, "unacceptable YAML version of the document");
      }
      state.version = args[0];
      state.checkLineBreaks = minor < 2;
      if (minor !== 1 && minor !== 2) {
        throwWarning(state, "unsupported YAML version of the document");
      }
    },
    TAG: function handleTagDirective(state, name, args) {
      let prefix;
      if (args.length !== 2) {
        throwError(state, "TAG directive accepts exactly two arguments");
      }
      const handle = args[0];
      prefix = args[1];
      if (!PATTERN_TAG_HANDLE.test(handle)) {
        throwError(state, "ill-formed tag handle (first argument) of the TAG directive");
      }
      if (_hasOwnProperty.call(state.tagMap, handle)) {
        throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle');
      }
      if (!PATTERN_TAG_URI.test(prefix)) {
        throwError(state, "ill-formed tag prefix (second argument) of the TAG directive");
      }
      try {
        prefix = decodeURIComponent(prefix);
      } catch (err) {
        throwError(state, "tag prefix is malformed: " + prefix);
      }
      state.tagMap[handle] = prefix;
    }
  };
  function captureSegment(state, start, end, checkJson) {
    if (start < end) {
      const _result = state.input.slice(start, end);
      if (checkJson) {
        for (let _position = 0, _length = _result.length; _position < _length; _position += 1) {
          const _character = _result.charCodeAt(_position);
          if (!(_character === 9 || _character >= 32 && _character <= 1114111)) {
            throwError(state, "expected valid JSON character");
          }
        }
      } else if (PATTERN_NON_PRINTABLE.test(_result)) {
        throwError(state, "the stream contains non-printable characters");
      }
      state.result += _result;
    }
  }
  function mergeMappings(state, destination, source, overridableKeys) {
    if (!common2.isObject(source)) {
      throwError(state, "cannot merge mappings; the provided source object is unacceptable");
    }
    const sourceKeys = Object.keys(source);
    for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
      const key = sourceKeys[index];
      if (state.maxTotalMergeKeys !== -1 && ++state.totalMergeKeys > state.maxTotalMergeKeys) {
        throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
      }
      if (!_hasOwnProperty.call(destination, key)) {
        setProperty(destination, key, source[key]);
        overridableKeys[key] = true;
      }
    }
  }
  function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, startLine, startLineStart, startPos) {
    if (Array.isArray(keyNode)) {
      keyNode = Array.prototype.slice.call(keyNode);
      for (let index = 0, quantity = keyNode.length; index < quantity; index += 1) {
        if (Array.isArray(keyNode[index])) {
          throwError(state, "nested arrays are not supported inside keys");
        }
        if (typeof keyNode === "object" && _class(keyNode[index]) === "[object Object]") {
          keyNode[index] = "[object Object]";
        }
      }
    }
    if (typeof keyNode === "object" && _class(keyNode) === "[object Object]") {
      keyNode = "[object Object]";
    }
    keyNode = String(keyNode);
    if (_result === null) {
      _result = {};
    }
    if (keyTag === "tag:yaml.org,2002:merge") {
      if (Array.isArray(valueNode)) {
        for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {
          mergeMappings(state, _result, valueNode[index], overridableKeys);
        }
      } else {
        mergeMappings(state, _result, valueNode, overridableKeys);
      }
    } else {
      if (!state.json && !_hasOwnProperty.call(overridableKeys, keyNode) && _hasOwnProperty.call(_result, keyNode)) {
        state.line = startLine || state.line;
        state.lineStart = startLineStart || state.lineStart;
        state.position = startPos || state.position;
        throwError(state, "duplicated mapping key");
      }
      setProperty(_result, keyNode, valueNode);
      delete overridableKeys[keyNode];
    }
    return _result;
  }
  function readLineBreak(state) {
    const ch = state.input.charCodeAt(state.position);
    if (ch === 10) {
      state.position++;
    } else if (ch === 13) {
      state.position++;
      if (state.input.charCodeAt(state.position) === 10) {
        state.position++;
      }
    } else {
      throwError(state, "a line break is expected");
    }
    state.line += 1;
    state.lineStart = state.position;
    state.firstTabInLine = -1;
  }
  function skipSeparationSpace(state, allowComments, checkIndent) {
    let lineBreaks = 0;
    let ch = state.input.charCodeAt(state.position);
    while (ch !== 0) {
      while (isWhiteSpace(ch)) {
        if (ch === 9 && state.firstTabInLine === -1) {
          state.firstTabInLine = state.position;
        }
        ch = state.input.charCodeAt(++state.position);
      }
      if (allowComments && ch === 35) {
        do {
          ch = state.input.charCodeAt(++state.position);
        } while (ch !== 10 && ch !== 13 && ch !== 0);
      }
      if (isEol(ch)) {
        readLineBreak(state);
        ch = state.input.charCodeAt(state.position);
        lineBreaks++;
        state.lineIndent = 0;
        while (ch === 32) {
          state.lineIndent++;
          ch = state.input.charCodeAt(++state.position);
        }
      } else {
        break;
      }
    }
    if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
      throwWarning(state, "deficient indentation");
    }
    return lineBreaks;
  }
  function testDocumentSeparator(state) {
    let _position = state.position;
    let ch = state.input.charCodeAt(_position);
    if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(_position + 1) && ch === state.input.charCodeAt(_position + 2)) {
      _position += 3;
      ch = state.input.charCodeAt(_position);
      if (ch === 0 || isWsOrEol(ch)) {
        return true;
      }
    }
    return false;
  }
  function writeFoldedLines(state, count) {
    if (count === 1) {
      state.result += " ";
    } else if (count > 1) {
      state.result += common2.repeat("\n", count - 1);
    }
  }
  function readPlainScalar(state, nodeIndent, withinFlowCollection) {
    let captureStart;
    let captureEnd;
    let hasPendingContent;
    let _line;
    let _lineStart;
    let _lineIndent;
    const _kind = state.kind;
    const _result = state.result;
    let ch = state.input.charCodeAt(state.position);
    if (isWsOrEol(ch) || isFlowIndicator(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96) {
      return false;
    }
    if (ch === 63 || ch === 45) {
      const following = state.input.charCodeAt(state.position + 1);
      if (isWsOrEol(following) || withinFlowCollection && isFlowIndicator(following)) {
        return false;
      }
    }
    state.kind = "scalar";
    state.result = "";
    captureStart = captureEnd = state.position;
    hasPendingContent = false;
    while (ch !== 0) {
      if (ch === 58) {
        const following = state.input.charCodeAt(state.position + 1);
        if (isWsOrEol(following) || withinFlowCollection && isFlowIndicator(following)) {
          break;
        }
      } else if (ch === 35) {
        const preceding = state.input.charCodeAt(state.position - 1);
        if (isWsOrEol(preceding)) {
          break;
        }
      } else if (state.position === state.lineStart && testDocumentSeparator(state) || withinFlowCollection && isFlowIndicator(ch)) {
        break;
      } else if (isEol(ch)) {
        _line = state.line;
        _lineStart = state.lineStart;
        _lineIndent = state.lineIndent;
        skipSeparationSpace(state, false, -1);
        if (state.lineIndent >= nodeIndent) {
          hasPendingContent = true;
          ch = state.input.charCodeAt(state.position);
          continue;
        } else {
          state.position = captureEnd;
          state.line = _line;
          state.lineStart = _lineStart;
          state.lineIndent = _lineIndent;
          break;
        }
      }
      if (hasPendingContent) {
        captureSegment(state, captureStart, captureEnd, false);
        writeFoldedLines(state, state.line - _line);
        captureStart = captureEnd = state.position;
        hasPendingContent = false;
      }
      if (!isWhiteSpace(ch)) {
        captureEnd = state.position + 1;
      }
      ch = state.input.charCodeAt(++state.position);
    }
    captureSegment(state, captureStart, captureEnd, false);
    if (state.result) {
      return true;
    }
    state.kind = _kind;
    state.result = _result;
    return false;
  }
  function readSingleQuotedScalar(state, nodeIndent) {
    let captureStart;
    let captureEnd;
    let ch = state.input.charCodeAt(state.position);
    if (ch !== 39) {
      return false;
    }
    state.kind = "scalar";
    state.result = "";
    state.position++;
    captureStart = captureEnd = state.position;
    while ((ch = state.input.charCodeAt(state.position)) !== 0) {
      if (ch === 39) {
        captureSegment(state, captureStart, state.position, true);
        ch = state.input.charCodeAt(++state.position);
        if (ch === 39) {
          captureStart = state.position;
          state.position++;
          captureEnd = state.position;
        } else {
          return true;
        }
      } else if (isEol(ch)) {
        captureSegment(state, captureStart, captureEnd, true);
        writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
        captureStart = captureEnd = state.position;
      } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
        throwError(state, "unexpected end of the document within a single quoted scalar");
      } else {
        state.position++;
        if (!isWhiteSpace(ch)) {
          captureEnd = state.position;
        }
      }
    }
    throwError(state, "unexpected end of the stream within a single quoted scalar");
  }
  function readDoubleQuotedScalar(state, nodeIndent) {
    let captureStart;
    let captureEnd;
    let tmp;
    let ch = state.input.charCodeAt(state.position);
    if (ch !== 34) {
      return false;
    }
    state.kind = "scalar";
    state.result = "";
    state.position++;
    captureStart = captureEnd = state.position;
    while ((ch = state.input.charCodeAt(state.position)) !== 0) {
      if (ch === 34) {
        captureSegment(state, captureStart, state.position, true);
        state.position++;
        return true;
      } else if (ch === 92) {
        captureSegment(state, captureStart, state.position, true);
        ch = state.input.charCodeAt(++state.position);
        if (isEol(ch)) {
          skipSeparationSpace(state, false, nodeIndent);
        } else if (ch < 256 && simpleEscapeCheck[ch]) {
          state.result += simpleEscapeMap[ch];
          state.position++;
        } else if ((tmp = escapedHexLen(ch)) > 0) {
          let hexLength = tmp;
          let hexResult = 0;
          for (; hexLength > 0; hexLength--) {
            ch = state.input.charCodeAt(++state.position);
            if ((tmp = fromHexCode(ch)) >= 0) {
              hexResult = (hexResult << 4) + tmp;
            } else {
              throwError(state, "expected hexadecimal character");
            }
          }
          state.result += charFromCodepoint(hexResult);
          state.position++;
        } else {
          throwError(state, "unknown escape sequence");
        }
        captureStart = captureEnd = state.position;
      } else if (isEol(ch)) {
        captureSegment(state, captureStart, captureEnd, true);
        writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
        captureStart = captureEnd = state.position;
      } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
        throwError(state, "unexpected end of the document within a double quoted scalar");
      } else {
        state.position++;
        if (!isWhiteSpace(ch)) {
          captureEnd = state.position;
        }
      }
    }
    throwError(state, "unexpected end of the stream within a double quoted scalar");
  }
  function readFlowCollection(state, nodeIndent) {
    let readNext = true;
    let _line;
    let _lineStart;
    let _pos;
    const _tag = state.tag;
    let _result;
    const _anchor = state.anchor;
    let terminator;
    let isPair;
    let isExplicitPair;
    let isMapping;
    const overridableKeys = /* @__PURE__ */ Object.create(null);
    let keyNode;
    let keyTag;
    let valueNode;
    let ch = state.input.charCodeAt(state.position);
    if (ch === 91) {
      terminator = 93;
      isMapping = false;
      _result = [];
    } else if (ch === 123) {
      terminator = 125;
      isMapping = true;
      _result = {};
    } else {
      return false;
    }
    if (state.anchor !== null) {
      storeAnchor(state, state.anchor, _result);
    }
    ch = state.input.charCodeAt(++state.position);
    while (ch !== 0) {
      skipSeparationSpace(state, true, nodeIndent);
      ch = state.input.charCodeAt(state.position);
      if (ch === terminator) {
        state.position++;
        state.tag = _tag;
        state.anchor = _anchor;
        state.kind = isMapping ? "mapping" : "sequence";
        state.result = _result;
        return true;
      } else if (!readNext) {
        throwError(state, "missed comma between flow collection entries");
      } else if (ch === 44) {
        throwError(state, "expected the node content, but found ','");
      }
      keyTag = keyNode = valueNode = null;
      isPair = isExplicitPair = false;
      if (ch === 63) {
        const following = state.input.charCodeAt(state.position + 1);
        if (isWsOrEol(following)) {
          isPair = isExplicitPair = true;
          state.position++;
          skipSeparationSpace(state, true, nodeIndent);
        }
      }
      _line = state.line;
      _lineStart = state.lineStart;
      _pos = state.position;
      composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
      keyTag = state.tag;
      keyNode = state.result;
      skipSeparationSpace(state, true, nodeIndent);
      ch = state.input.charCodeAt(state.position);
      if ((isExplicitPair || state.line === _line) && ch === 58) {
        isPair = true;
        ch = state.input.charCodeAt(++state.position);
        skipSeparationSpace(state, true, nodeIndent);
        composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
        valueNode = state.result;
      }
      if (isMapping) {
        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos);
      } else if (isPair) {
        _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos));
      } else {
        _result.push(keyNode);
      }
      skipSeparationSpace(state, true, nodeIndent);
      ch = state.input.charCodeAt(state.position);
      if (ch === 44) {
        readNext = true;
        ch = state.input.charCodeAt(++state.position);
      } else {
        readNext = false;
      }
    }
    throwError(state, "unexpected end of the stream within a flow collection");
  }
  function readBlockScalar(state, nodeIndent) {
    let folding;
    let chomping = CHOMPING_CLIP;
    let didReadContent = false;
    let detectedIndent = false;
    let textIndent = nodeIndent;
    let emptyLines = 0;
    let atMoreIndented = false;
    let tmp;
    let ch = state.input.charCodeAt(state.position);
    if (ch === 124) {
      folding = false;
    } else if (ch === 62) {
      folding = true;
    } else {
      return false;
    }
    state.kind = "scalar";
    state.result = "";
    while (ch !== 0) {
      ch = state.input.charCodeAt(++state.position);
      if (ch === 43 || ch === 45) {
        if (CHOMPING_CLIP === chomping) {
          chomping = ch === 43 ? CHOMPING_KEEP : CHOMPING_STRIP;
        } else {
          throwError(state, "repeat of a chomping mode identifier");
        }
      } else if ((tmp = fromDecimalCode(ch)) >= 0) {
        if (tmp === 0) {
          throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one");
        } else if (!detectedIndent) {
          textIndent = nodeIndent + tmp - 1;
          detectedIndent = true;
        } else {
          throwError(state, "repeat of an indentation width identifier");
        }
      } else {
        break;
      }
    }
    if (isWhiteSpace(ch)) {
      do {
        ch = state.input.charCodeAt(++state.position);
      } while (isWhiteSpace(ch));
      if (ch === 35) {
        do {
          ch = state.input.charCodeAt(++state.position);
        } while (!isEol(ch) && ch !== 0);
      }
    }
    while (ch !== 0) {
      readLineBreak(state);
      state.lineIndent = 0;
      ch = state.input.charCodeAt(state.position);
      while ((!detectedIndent || state.lineIndent < textIndent) && ch === 32) {
        state.lineIndent++;
        ch = state.input.charCodeAt(++state.position);
      }
      if (!detectedIndent && state.lineIndent > textIndent) {
        textIndent = state.lineIndent;
      }
      if (isEol(ch)) {
        emptyLines++;
        continue;
      }
      if (!detectedIndent && textIndent === 0) {
        throwError(state, "missing indentation for block scalar");
      }
      if (state.lineIndent < textIndent) {
        if (chomping === CHOMPING_KEEP) {
          state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
        } else if (chomping === CHOMPING_CLIP) {
          if (didReadContent) {
            state.result += "\n";
          }
        }
        break;
      }
      if (folding) {
        if (isWhiteSpace(ch)) {
          atMoreIndented = true;
          state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
        } else if (atMoreIndented) {
          atMoreIndented = false;
          state.result += common2.repeat("\n", emptyLines + 1);
        } else if (emptyLines === 0) {
          if (didReadContent) {
            state.result += " ";
          }
        } else {
          state.result += common2.repeat("\n", emptyLines);
        }
      } else {
        state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
      }
      didReadContent = true;
      detectedIndent = true;
      emptyLines = 0;
      const captureStart = state.position;
      while (!isEol(ch) && ch !== 0) {
        ch = state.input.charCodeAt(++state.position);
      }
      captureSegment(state, captureStart, state.position, false);
    }
    return true;
  }
  function readBlockSequence(state, nodeIndent) {
    const _tag = state.tag;
    const _anchor = state.anchor;
    const _result = [];
    let detected = false;
    if (state.firstTabInLine !== -1) return false;
    if (state.anchor !== null) {
      storeAnchor(state, state.anchor, _result);
    }
    let ch = state.input.charCodeAt(state.position);
    while (ch !== 0) {
      if (state.firstTabInLine !== -1) {
        state.position = state.firstTabInLine;
        throwError(state, "tab characters must not be used in indentation");
      }
      if (ch !== 45) {
        break;
      }
      const following = state.input.charCodeAt(state.position + 1);
      if (!isWsOrEol(following)) {
        break;
      }
      detected = true;
      state.position++;
      if (skipSeparationSpace(state, true, -1)) {
        if (state.lineIndent <= nodeIndent) {
          _result.push(null);
          ch = state.input.charCodeAt(state.position);
          continue;
        }
      }
      const _line = state.line;
      composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);
      _result.push(state.result);
      skipSeparationSpace(state, true, -1);
      ch = state.input.charCodeAt(state.position);
      if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) {
        throwError(state, "bad indentation of a sequence entry");
      } else if (state.lineIndent < nodeIndent) {
        break;
      }
    }
    if (detected) {
      state.tag = _tag;
      state.anchor = _anchor;
      state.kind = "sequence";
      state.result = _result;
      return true;
    }
    return false;
  }
  function readBlockMapping(state, nodeIndent, flowIndent) {
    let allowCompact;
    let _keyLine;
    let _keyLineStart;
    let _keyPos;
    const _tag = state.tag;
    const _anchor = state.anchor;
    const _result = {};
    const overridableKeys = /* @__PURE__ */ Object.create(null);
    let keyTag = null;
    let keyNode = null;
    let valueNode = null;
    let atExplicitKey = false;
    let detected = false;
    if (state.firstTabInLine !== -1) return false;
    if (state.anchor !== null) {
      storeAnchor(state, state.anchor, _result);
    }
    let ch = state.input.charCodeAt(state.position);
    while (ch !== 0) {
      if (!atExplicitKey && state.firstTabInLine !== -1) {
        state.position = state.firstTabInLine;
        throwError(state, "tab characters must not be used in indentation");
      }
      const following = state.input.charCodeAt(state.position + 1);
      const _line = state.line;
      if ((ch === 63 || ch === 58) && isWsOrEol(following)) {
        if (ch === 63) {
          if (atExplicitKey) {
            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
            keyTag = keyNode = valueNode = null;
          }
          detected = true;
          atExplicitKey = true;
          allowCompact = true;
        } else if (atExplicitKey) {
          atExplicitKey = false;
          allowCompact = true;
        } else {
          throwError(state, "incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line");
        }
        state.position += 1;
        ch = following;
      } else {
        _keyLine = state.line;
        _keyLineStart = state.lineStart;
        _keyPos = state.position;
        if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
          break;
        }
        if (state.line === _line) {
          ch = state.input.charCodeAt(state.position);
          while (isWhiteSpace(ch)) {
            ch = state.input.charCodeAt(++state.position);
          }
          if (ch === 58) {
            ch = state.input.charCodeAt(++state.position);
            if (!isWsOrEol(ch)) {
              throwError(state, "a whitespace character is expected after the key-value separator within a block mapping");
            }
            if (atExplicitKey) {
              storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
              keyTag = keyNode = valueNode = null;
            }
            detected = true;
            atExplicitKey = false;
            allowCompact = false;
            keyTag = state.tag;
            keyNode = state.result;
          } else if (detected) {
            throwError(state, "can not read an implicit mapping pair; a colon is missed");
          } else {
            state.tag = _tag;
            state.anchor = _anchor;
            return true;
          }
        } else if (detected) {
          throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key");
        } else {
          state.tag = _tag;
          state.anchor = _anchor;
          return true;
        }
      }
      if (state.line === _line || state.lineIndent > nodeIndent) {
        if (atExplicitKey) {
          _keyLine = state.line;
          _keyLineStart = state.lineStart;
          _keyPos = state.position;
        }
        if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
          if (atExplicitKey) {
            keyNode = state.result;
          } else {
            valueNode = state.result;
          }
        }
        if (!atExplicitKey) {
          storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos);
          keyTag = keyNode = valueNode = null;
        }
        skipSeparationSpace(state, true, -1);
        ch = state.input.charCodeAt(state.position);
      }
      if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) {
        throwError(state, "bad indentation of a mapping entry");
      } else if (state.lineIndent < nodeIndent) {
        break;
      }
    }
    if (atExplicitKey) {
      storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
    }
    if (detected) {
      state.tag = _tag;
      state.anchor = _anchor;
      state.kind = "mapping";
      state.result = _result;
    }
    return detected;
  }
  function readTagProperty(state) {
    let isVerbatim = false;
    let isNamed = false;
    let tagHandle;
    let tagName;
    let ch = state.input.charCodeAt(state.position);
    if (ch !== 33) return false;
    if (state.tag !== null) {
      throwError(state, "duplication of a tag property");
    }
    ch = state.input.charCodeAt(++state.position);
    if (ch === 60) {
      isVerbatim = true;
      ch = state.input.charCodeAt(++state.position);
    } else if (ch === 33) {
      isNamed = true;
      tagHandle = "!!";
      ch = state.input.charCodeAt(++state.position);
    } else {
      tagHandle = "!";
    }
    let _position = state.position;
    if (isVerbatim) {
      do {
        ch = state.input.charCodeAt(++state.position);
      } while (ch !== 0 && ch !== 62);
      if (state.position < state.length) {
        tagName = state.input.slice(_position, state.position);
        ch = state.input.charCodeAt(++state.position);
      } else {
        throwError(state, "unexpected end of the stream within a verbatim tag");
      }
    } else {
      while (ch !== 0 && !isWsOrEol(ch)) {
        if (ch === 33) {
          if (!isNamed) {
            tagHandle = state.input.slice(_position - 1, state.position + 1);
            if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
              throwError(state, "named tag handle cannot contain such characters");
            }
            isNamed = true;
            _position = state.position + 1;
          } else {
            throwError(state, "tag suffix cannot contain exclamation marks");
          }
        }
        ch = state.input.charCodeAt(++state.position);
      }
      tagName = state.input.slice(_position, state.position);
      if (PATTERN_FLOW_INDICATORS.test(tagName)) {
        throwError(state, "tag suffix cannot contain flow indicator characters");
      }
    }
    if (tagName && !PATTERN_TAG_URI.test(tagName)) {
      throwError(state, "tag name cannot contain such characters: " + tagName);
    }
    try {
      tagName = decodeURIComponent(tagName);
    } catch (err) {
      throwError(state, "tag name is malformed: " + tagName);
    }
    if (isVerbatim) {
      state.tag = tagName;
    } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {
      state.tag = state.tagMap[tagHandle] + tagName;
    } else if (tagHandle === "!") {
      state.tag = "!" + tagName;
    } else if (tagHandle === "!!") {
      state.tag = "tag:yaml.org,2002:" + tagName;
    } else {
      throwError(state, 'undeclared tag handle "' + tagHandle + '"');
    }
    return true;
  }
  function readAnchorProperty(state) {
    let ch = state.input.charCodeAt(state.position);
    if (ch !== 38) return false;
    if (state.anchor !== null) {
      throwError(state, "duplication of an anchor property");
    }
    ch = state.input.charCodeAt(++state.position);
    const _position = state.position;
    while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {
      ch = state.input.charCodeAt(++state.position);
    }
    if (state.position === _position) {
      throwError(state, "name of an anchor node must contain at least one character");
    }
    state.anchor = state.input.slice(_position, state.position);
    return true;
  }
  function readAlias(state) {
    let ch = state.input.charCodeAt(state.position);
    if (ch !== 42) return false;
    ch = state.input.charCodeAt(++state.position);
    const _position = state.position;
    while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {
      ch = state.input.charCodeAt(++state.position);
    }
    if (state.position === _position) {
      throwError(state, "name of an alias node must contain at least one character");
    }
    const alias = state.input.slice(_position, state.position);
    if (!_hasOwnProperty.call(state.anchorMap, alias)) {
      throwError(state, 'unidentified alias "' + alias + '"');
    }
    state.result = state.anchorMap[alias];
    skipSeparationSpace(state, true, -1);
    return true;
  }
  function tryReadBlockMappingFromProperty(state, propertyStart, nodeIndent, flowIndent) {
    const fallbackState = snapshotState(state);
    beginAnchorTransaction(state);
    restoreState(state, propertyStart);
    state.tag = null;
    state.anchor = null;
    state.kind = null;
    state.result = null;
    if (readBlockMapping(state, nodeIndent, flowIndent) && state.kind === "mapping") {
      commitAnchorTransaction(state);
      return true;
    }
    rollbackAnchorTransaction(state);
    restoreState(state, fallbackState);
    return false;
  }
  function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
    let allowBlockScalars;
    let allowBlockCollections;
    let indentStatus = 1;
    let atNewLine = false;
    let hasContent = false;
    let propertyStart = null;
    let type2;
    let flowIndent;
    let blockIndent;
    if (state.depth >= state.maxDepth) {
      throwError(state, "nesting exceeded maxDepth (" + state.maxDepth + ")");
    }
    state.depth += 1;
    if (state.listener !== null) {
      state.listener("open", state);
    }
    state.tag = null;
    state.anchor = null;
    state.kind = null;
    state.result = null;
    const allowBlockStyles = allowBlockScalars = allowBlockCollections = CONTEXT_BLOCK_OUT === nodeContext || CONTEXT_BLOCK_IN === nodeContext;
    if (allowToSeek) {
      if (skipSeparationSpace(state, true, -1)) {
        atNewLine = true;
        if (state.lineIndent > parentIndent) {
          indentStatus = 1;
        } else if (state.lineIndent === parentIndent) {
          indentStatus = 0;
        } else if (state.lineIndent < parentIndent) {
          indentStatus = -1;
        }
      }
    }
    if (indentStatus === 1) {
      while (true) {
        const ch = state.input.charCodeAt(state.position);
        const propertyState = snapshotState(state);
        if (atNewLine && (ch === 33 && state.tag !== null || ch === 38 && state.anchor !== null)) {
          break;
        }
        if (!readTagProperty(state) && !readAnchorProperty(state)) {
          break;
        }
        if (propertyStart === null) {
          propertyStart = propertyState;
        }
        if (skipSeparationSpace(state, true, -1)) {
          atNewLine = true;
          allowBlockCollections = allowBlockStyles;
          if (state.lineIndent > parentIndent) {
            indentStatus = 1;
          } else if (state.lineIndent === parentIndent) {
            indentStatus = 0;
          } else if (state.lineIndent < parentIndent) {
            indentStatus = -1;
          }
        } else {
          allowBlockCollections = false;
        }
      }
    }
    if (allowBlockCollections) {
      allowBlockCollections = atNewLine || allowCompact;
    }
    if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
      if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
        flowIndent = parentIndent;
      } else {
        flowIndent = parentIndent + 1;
      }
      blockIndent = state.position - state.lineStart;
      if (indentStatus === 1) {
        if (allowBlockCollections && (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent)) || readFlowCollection(state, flowIndent)) {
          hasContent = true;
        } else {
          const ch = state.input.charCodeAt(state.position);
          if (propertyStart !== null && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62 && tryReadBlockMappingFromProperty(
            state,
            propertyStart,
            propertyStart.position - propertyStart.lineStart,
            flowIndent
          )) {
            hasContent = true;
          } else if (allowBlockScalars && readBlockScalar(state, flowIndent) || readSingleQuotedScalar(state, flowIndent) || readDoubleQuotedScalar(state, flowIndent)) {
            hasContent = true;
          } else if (readAlias(state)) {
            hasContent = true;
            if (state.tag !== null || state.anchor !== null) {
              throwError(state, "alias node should not have any properties");
            }
          } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
            hasContent = true;
            if (state.tag === null) {
              state.tag = "?";
            }
          }
          if (state.anchor !== null) {
            storeAnchor(state, state.anchor, state.result);
          }
        }
      } else if (indentStatus === 0) {
        hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
      }
    }
    if (state.tag === null) {
      if (state.anchor !== null) {
        storeAnchor(state, state.anchor, state.result);
      }
    } else if (state.tag === "?") {
      if (state.result !== null && state.kind !== "scalar") {
        throwError(state, 'unacceptable node kind for !<?> tag; it should be "scalar", not "' + state.kind + '"');
      }
      for (let typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {
        type2 = state.implicitTypes[typeIndex];
        if (type2.resolve(state.result)) {
          state.result = type2.construct(state.result);
          state.tag = type2.tag;
          if (state.anchor !== null) {
            storeAnchor(state, state.anchor, state.result);
          }
          break;
        }
      }
    } else if (state.tag !== "!") {
      if (_hasOwnProperty.call(state.typeMap[state.kind || "fallback"], state.tag)) {
        type2 = state.typeMap[state.kind || "fallback"][state.tag];
      } else {
        type2 = null;
        const typeList = state.typeMap.multi[state.kind || "fallback"];
        for (let typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {
          if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {
            type2 = typeList[typeIndex];
            break;
          }
        }
      }
      if (!type2) {
        throwError(state, "unknown tag !<" + state.tag + ">");
      }
      if (state.result !== null && type2.kind !== state.kind) {
        throwError(state, "unacceptable node kind for !<" + state.tag + '> tag; it should be "' + type2.kind + '", not "' + state.kind + '"');
      }
      if (!type2.resolve(state.result, state.tag)) {
        throwError(state, "cannot resolve a node with !<" + state.tag + "> explicit tag");
      } else {
        state.result = type2.construct(state.result, state.tag);
        if (state.anchor !== null) {
          storeAnchor(state, state.anchor, state.result);
        }
      }
    }
    if (state.listener !== null) {
      state.listener("close", state);
    }
    state.depth -= 1;
    return state.tag !== null || state.anchor !== null || hasContent;
  }
  function readDocument(state) {
    const documentStart = state.position;
    let hasDirectives = false;
    let ch;
    state.version = null;
    state.checkLineBreaks = state.legacy;
    state.tagMap = /* @__PURE__ */ Object.create(null);
    state.anchorMap = /* @__PURE__ */ Object.create(null);
    while ((ch = state.input.charCodeAt(state.position)) !== 0) {
      skipSeparationSpace(state, true, -1);
      ch = state.input.charCodeAt(state.position);
      if (state.lineIndent > 0 || ch !== 37) {
        break;
      }
      hasDirectives = true;
      ch = state.input.charCodeAt(++state.position);
      let _position = state.position;
      while (ch !== 0 && !isWsOrEol(ch)) {
        ch = state.input.charCodeAt(++state.position);
      }
      const directiveName = state.input.slice(_position, state.position);
      const directiveArgs = [];
      if (directiveName.length < 1) {
        throwError(state, "directive name must not be less than one character in length");
      }
      while (ch !== 0) {
        while (isWhiteSpace(ch)) {
          ch = state.input.charCodeAt(++state.position);
        }
        if (ch === 35) {
          do {
            ch = state.input.charCodeAt(++state.position);
          } while (ch !== 0 && !isEol(ch));
          break;
        }
        if (isEol(ch)) break;
        _position = state.position;
        while (ch !== 0 && !isWsOrEol(ch)) {
          ch = state.input.charCodeAt(++state.position);
        }
        directiveArgs.push(state.input.slice(_position, state.position));
      }
      if (ch !== 0) readLineBreak(state);
      if (_hasOwnProperty.call(directiveHandlers, directiveName)) {
        directiveHandlers[directiveName](state, directiveName, directiveArgs);
      } else {
        throwWarning(state, 'unknown document directive "' + directiveName + '"');
      }
    }
    skipSeparationSpace(state, true, -1);
    if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45) {
      state.position += 3;
      skipSeparationSpace(state, true, -1);
    } else if (hasDirectives) {
      throwError(state, "directives end mark is expected");
    }
    composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
    skipSeparationSpace(state, true, -1);
    if (state.checkLineBreaks && PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
      throwWarning(state, "non-ASCII line breaks are interpreted as content");
    }
    state.documents.push(state.result);
    if (state.position === state.lineStart && testDocumentSeparator(state)) {
      if (state.input.charCodeAt(state.position) === 46) {
        state.position += 3;
        skipSeparationSpace(state, true, -1);
      }
      return;
    }
    if (state.position < state.length - 1) {
      throwError(state, "end of the stream or a document separator is expected");
    }
  }
  function loadDocuments(input, options) {
    input = String(input);
    options = options || {};
    if (input.length !== 0) {
      if (input.charCodeAt(input.length - 1) !== 10 && input.charCodeAt(input.length - 1) !== 13) {
        input += "\n";
      }
      if (input.charCodeAt(0) === 65279) {
        input = input.slice(1);
      }
    }
    const state = new State(input, options);
    const nullpos = input.indexOf("\0");
    if (nullpos !== -1) {
      state.position = nullpos;
      throwError(state, "null byte is not allowed in input");
    }
    state.input += "\0";
    while (state.input.charCodeAt(state.position) === 32) {
      state.lineIndent += 1;
      state.position += 1;
    }
    while (state.position < state.length - 1) {
      readDocument(state);
    }
    return state.documents;
  }
  function loadAll2(input, iterator, options) {
    if (iterator !== null && typeof iterator === "object" && typeof options === "undefined") {
      options = iterator;
      iterator = null;
    }
    const documents = loadDocuments(input, options);
    if (typeof iterator !== "function") {
      return documents;
    }
    for (let index = 0, length = documents.length; index < length; index += 1) {
      iterator(documents[index]);
    }
  }
  function load2(input, options) {
    const documents = loadDocuments(input, options);
    if (documents.length === 0) {
      return void 0;
    } else if (documents.length === 1) {
      return documents[0];
    }
    throw new YAMLException2("expected a single document in the stream, but found more");
  }
  loader.loadAll = loadAll2;
  loader.load = load2;
  return loader;
}
var dumper = {};
var hasRequiredDumper;
function requireDumper() {
  if (hasRequiredDumper) return dumper;
  hasRequiredDumper = 1;
  const common2 = requireCommon();
  const YAMLException2 = requireException();
  const DEFAULT_SCHEMA2 = require_default();
  const _toString = Object.prototype.toString;
  const _hasOwnProperty = Object.prototype.hasOwnProperty;
  const CHAR_BOM = 65279;
  const CHAR_TAB = 9;
  const CHAR_LINE_FEED = 10;
  const CHAR_CARRIAGE_RETURN = 13;
  const CHAR_SPACE = 32;
  const CHAR_EXCLAMATION = 33;
  const CHAR_DOUBLE_QUOTE = 34;
  const CHAR_SHARP = 35;
  const CHAR_PERCENT = 37;
  const CHAR_AMPERSAND = 38;
  const CHAR_SINGLE_QUOTE = 39;
  const CHAR_ASTERISK = 42;
  const CHAR_COMMA = 44;
  const CHAR_MINUS = 45;
  const CHAR_COLON = 58;
  const CHAR_EQUALS = 61;
  const CHAR_GREATER_THAN = 62;
  const CHAR_QUESTION = 63;
  const CHAR_COMMERCIAL_AT = 64;
  const CHAR_LEFT_SQUARE_BRACKET = 91;
  const CHAR_RIGHT_SQUARE_BRACKET = 93;
  const CHAR_GRAVE_ACCENT = 96;
  const CHAR_LEFT_CURLY_BRACKET = 123;
  const CHAR_VERTICAL_LINE = 124;
  const CHAR_RIGHT_CURLY_BRACKET = 125;
  const ESCAPE_SEQUENCES = {};
  ESCAPE_SEQUENCES[0] = "\\0";
  ESCAPE_SEQUENCES[7] = "\\a";
  ESCAPE_SEQUENCES[8] = "\\b";
  ESCAPE_SEQUENCES[9] = "\\t";
  ESCAPE_SEQUENCES[10] = "\\n";
  ESCAPE_SEQUENCES[11] = "\\v";
  ESCAPE_SEQUENCES[12] = "\\f";
  ESCAPE_SEQUENCES[13] = "\\r";
  ESCAPE_SEQUENCES[27] = "\\e";
  ESCAPE_SEQUENCES[34] = '\\"';
  ESCAPE_SEQUENCES[92] = "\\\\";
  ESCAPE_SEQUENCES[133] = "\\N";
  ESCAPE_SEQUENCES[160] = "\\_";
  ESCAPE_SEQUENCES[8232] = "\\L";
  ESCAPE_SEQUENCES[8233] = "\\P";
  const DEPRECATED_BOOLEANS_SYNTAX = [
    "y",
    "Y",
    "yes",
    "Yes",
    "YES",
    "on",
    "On",
    "ON",
    "n",
    "N",
    "no",
    "No",
    "NO",
    "off",
    "Off",
    "OFF"
  ];
  const DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;
  function compileStyleMap(schema2, map2) {
    if (map2 === null) return {};
    const result = {};
    const keys = Object.keys(map2);
    for (let index = 0, length = keys.length; index < length; index += 1) {
      let tag = keys[index];
      let style = String(map2[tag]);
      if (tag.slice(0, 2) === "!!") {
        tag = "tag:yaml.org,2002:" + tag.slice(2);
      }
      const type2 = schema2.compiledTypeMap["fallback"][tag];
      if (type2 && _hasOwnProperty.call(type2.styleAliases, style)) {
        style = type2.styleAliases[style];
      }
      result[tag] = style;
    }
    return result;
  }
  function encodeHex(character) {
    let handle;
    let length;
    const string = character.toString(16).toUpperCase();
    if (character <= 255) {
      handle = "x";
      length = 2;
    } else if (character <= 65535) {
      handle = "u";
      length = 4;
    } else if (character <= 4294967295) {
      handle = "U";
      length = 8;
    } else {
      throw new YAMLException2("code point within a string may not be greater than 0xFFFFFFFF");
    }
    return "\\" + handle + common2.repeat("0", length - string.length) + string;
  }
  const QUOTING_TYPE_SINGLE = 1;
  const QUOTING_TYPE_DOUBLE = 2;
  function State(options) {
    this.schema = options["schema"] || DEFAULT_SCHEMA2;
    this.indent = Math.max(1, options["indent"] || 2);
    this.noArrayIndent = options["noArrayIndent"] || false;
    this.skipInvalid = options["skipInvalid"] || false;
    this.flowLevel = common2.isNothing(options["flowLevel"]) ? -1 : options["flowLevel"];
    this.styleMap = compileStyleMap(this.schema, options["styles"] || null);
    this.sortKeys = options["sortKeys"] || false;
    this.lineWidth = options["lineWidth"] || 80;
    this.noRefs = options["noRefs"] || false;
    this.noCompatMode = options["noCompatMode"] || false;
    this.condenseFlow = options["condenseFlow"] || false;
    this.quotingType = options["quotingType"] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE;
    this.forceQuotes = options["forceQuotes"] || false;
    this.replacer = typeof options["replacer"] === "function" ? options["replacer"] : null;
    this.implicitTypes = this.schema.compiledImplicit;
    this.explicitTypes = this.schema.compiledExplicit;
    this.tag = null;
    this.result = "";
    this.duplicates = [];
    this.usedDuplicates = null;
  }
  function indentString(string, spaces) {
    const ind = common2.repeat(" ", spaces);
    let position = 0;
    let result = "";
    const length = string.length;
    while (position < length) {
      let line;
      const next = string.indexOf("\n", position);
      if (next === -1) {
        line = string.slice(position);
        position = length;
      } else {
        line = string.slice(position, next + 1);
        position = next + 1;
      }
      if (line.length && line !== "\n") result += ind;
      result += line;
    }
    return result;
  }
  function generateNextLine(state, level) {
    return "\n" + common2.repeat(" ", state.indent * level);
  }
  function testImplicitResolving(state, str2) {
    for (let index = 0, length = state.implicitTypes.length; index < length; index += 1) {
      const type2 = state.implicitTypes[index];
      if (type2.resolve(str2)) {
        return true;
      }
    }
    return false;
  }
  function isWhitespace(c) {
    return c === CHAR_SPACE || c === CHAR_TAB;
  }
  function isPrintable(c) {
    return c >= 32 && c <= 126 || c >= 161 && c <= 55295 && c !== 8232 && c !== 8233 || c >= 57344 && c <= 65533 && c !== CHAR_BOM || c >= 65536 && c <= 1114111;
  }
  function isNsCharOrWhitespace(c) {
    return isPrintable(c) && c !== CHAR_BOM && // - b-char
    c !== CHAR_CARRIAGE_RETURN && c !== CHAR_LINE_FEED;
  }
  function isPlainSafe(c, prev, inblock) {
    const cIsNsCharOrWhitespace = isNsCharOrWhitespace(c);
    const cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c);
    return (
      // ns-plain-safe
      (inblock ? cIsNsCharOrWhitespace : cIsNsCharOrWhitespace && // - c-flow-indicator
      c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET) && // ns-plain-char
      c !== CHAR_SHARP && // false on '#'
      !(prev === CHAR_COLON && !cIsNsChar) || // false on ': '
      isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP || // change to true on '[^ ]#'
      prev === CHAR_COLON && cIsNsChar
    );
  }
  function isPlainSafeFirst(c) {
    return isPrintable(c) && c !== CHAR_BOM && !isWhitespace(c) && // - s-white
    // - (c-indicator ::=
    // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
    c !== CHAR_MINUS && c !== CHAR_QUESTION && c !== CHAR_COLON && c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET && // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"”
    c !== CHAR_SHARP && c !== CHAR_AMPERSAND && c !== CHAR_ASTERISK && c !== CHAR_EXCLAMATION && c !== CHAR_VERTICAL_LINE && c !== CHAR_EQUALS && c !== CHAR_GREATER_THAN && c !== CHAR_SINGLE_QUOTE && c !== CHAR_DOUBLE_QUOTE && // | “%” | “@” | “`”)
    c !== CHAR_PERCENT && c !== CHAR_COMMERCIAL_AT && c !== CHAR_GRAVE_ACCENT;
  }
  function isPlainSafeLast(c) {
    return !isWhitespace(c) && c !== CHAR_COLON;
  }
  function codePointAt(string, pos) {
    const first = string.charCodeAt(pos);
    let second;
    if (first >= 55296 && first <= 56319 && pos + 1 < string.length) {
      second = string.charCodeAt(pos + 1);
      if (second >= 56320 && second <= 57343) {
        return (first - 55296) * 1024 + second - 56320 + 65536;
      }
    }
    return first;
  }
  function needIndentIndicator(string) {
    const leadingSpaceRe = /^\n* /;
    return leadingSpaceRe.test(string);
  }
  const STYLE_PLAIN = 1;
  const STYLE_SINGLE = 2;
  const STYLE_LITERAL = 3;
  const STYLE_FOLDED = 4;
  const STYLE_DOUBLE = 5;
  function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType, quotingType, forceQuotes, inblock) {
    let i;
    let char = 0;
    let prevChar = null;
    let hasLineBreak = false;
    let hasFoldableLine = false;
    const shouldTrackWidth = lineWidth !== -1;
    let previousLineBreak = -1;
    let plain = isPlainSafeFirst(codePointAt(string, 0)) && isPlainSafeLast(codePointAt(string, string.length - 1));
    if (singleLineOnly || forceQuotes) {
      for (i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
        char = codePointAt(string, i);
        if (!isPrintable(char)) {
          return STYLE_DOUBLE;
        }
        plain = plain && isPlainSafe(char, prevChar, inblock);
        prevChar = char;
      }
    } else {
      for (i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
        char = codePointAt(string, i);
        if (char === CHAR_LINE_FEED) {
          hasLineBreak = true;
          if (shouldTrackWidth) {
            hasFoldableLine = hasFoldableLine || // Foldable line = too long, and not more-indented.
            i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ";
            previousLineBreak = i;
          }
        } else if (!isPrintable(char)) {
          return STYLE_DOUBLE;
        }
        plain = plain && isPlainSafe(char, prevChar, inblock);
        prevChar = char;
      }
      hasFoldableLine = hasFoldableLine || shouldTrackWidth && (i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ");
    }
    if (!hasLineBreak && !hasFoldableLine) {
      if (plain && !forceQuotes && !testAmbiguousType(string)) {
        return STYLE_PLAIN;
      }
      return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
    }
    if (indentPerLevel > 9 && needIndentIndicator(string)) {
      return STYLE_DOUBLE;
    }
    if (!forceQuotes) {
      return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
    }
    return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
  }
  function writeScalar(state, string, level, iskey, inblock) {
    state.dump = (function() {
      if (string.length === 0) {
        return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''";
      }
      if (!state.noCompatMode) {
        if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {
          return state.quotingType === QUOTING_TYPE_DOUBLE ? '"' + string + '"' : "'" + string + "'";
        }
      }
      const indent = state.indent * Math.max(1, level);
      const lineWidth = state.lineWidth === -1 ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
      const singleLineOnly = iskey || // No block styles in flow mode.
      state.flowLevel > -1 && level >= state.flowLevel;
      function testAmbiguity(string2) {
        return testImplicitResolving(state, string2);
      }
      switch (chooseScalarStyle(
        string,
        singleLineOnly,
        state.indent,
        lineWidth,
        testAmbiguity,
        state.quotingType,
        state.forceQuotes && !iskey,
        inblock
      )) {
        case STYLE_PLAIN:
          return string;
        case STYLE_SINGLE:
          return "'" + string.replace(/'/g, "''") + "'";
        case STYLE_LITERAL:
          return "|" + blockHeader(string, state.indent) + dropEndingNewline(indentString(string, indent));
        case STYLE_FOLDED:
          return ">" + blockHeader(string, state.indent) + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
        case STYLE_DOUBLE:
          return '"' + escapeString(string) + '"';
        default:
          throw new YAMLException2("impossible error: invalid scalar style");
      }
    })();
  }
  function blockHeader(string, indentPerLevel) {
    const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : "";
    const clip = string[string.length - 1] === "\n";
    const keep = clip && (string[string.length - 2] === "\n" || string === "\n");
    const chomp = keep ? "+" : clip ? "" : "-";
    return indentIndicator + chomp + "\n";
  }
  function dropEndingNewline(string) {
    return string[string.length - 1] === "\n" ? string.slice(0, -1) : string;
  }
  function foldString(string, width) {
    const lineRe = /(\n+)([^\n]*)/g;
    let result = (function() {
      let nextLF = string.indexOf("\n");
      nextLF = nextLF !== -1 ? nextLF : string.length;
      lineRe.lastIndex = nextLF;
      return foldLine(string.slice(0, nextLF), width);
    })();
    let prevMoreIndented = string[0] === "\n" || string[0] === " ";
    let moreIndented;
    let match;
    while (match = lineRe.exec(string)) {
      const prefix = match[1];
      const line = match[2];
      moreIndented = line[0] === " ";
      result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width);
      prevMoreIndented = moreIndented;
    }
    return result;
  }
  function foldLine(line, width) {
    if (line === "" || line[0] === " ") return line;
    const breakRe = / [^ ]/g;
    let match;
    let start = 0;
    let end;
    let curr = 0;
    let next = 0;
    let result = "";
    while (match = breakRe.exec(line)) {
      next = match.index;
      if (next - start > width) {
        end = curr > start ? curr : next;
        result += "\n" + line.slice(start, end);
        start = end + 1;
      }
      curr = next;
    }
    result += "\n";
    if (line.length - start > width && curr > start) {
      result += line.slice(start, curr) + "\n" + line.slice(curr + 1);
    } else {
      result += line.slice(start);
    }
    return result.slice(1);
  }
  function escapeString(string) {
    let result = "";
    let char = 0;
    for (let i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
      char = codePointAt(string, i);
      const escapeSeq = ESCAPE_SEQUENCES[char];
      if (!escapeSeq && isPrintable(char)) {
        result += string[i];
        if (char >= 65536) result += string[i + 1];
      } else {
        result += escapeSeq || encodeHex(char);
      }
    }
    return result;
  }
  function writeFlowSequence(state, level, object) {
    let _result = "";
    const _tag = state.tag;
    for (let index = 0, length = object.length; index < length; index += 1) {
      let value = object[index];
      if (state.replacer) {
        value = state.replacer.call(object, String(index), value);
      }
      if (writeNode(state, level, value, false, false) || typeof value === "undefined" && writeNode(state, level, null, false, false)) {
        if (_result !== "") _result += "," + (!state.condenseFlow ? " " : "");
        _result += state.dump;
      }
    }
    state.tag = _tag;
    state.dump = "[" + _result + "]";
  }
  function writeBlockSequence(state, level, object, compact) {
    let _result = "";
    const _tag = state.tag;
    for (let index = 0, length = object.length; index < length; index += 1) {
      let value = object[index];
      if (state.replacer) {
        value = state.replacer.call(object, String(index), value);
      }
      if (writeNode(state, level + 1, value, true, true, false, true) || typeof value === "undefined" && writeNode(state, level + 1, null, true, true, false, true)) {
        if (!compact || _result !== "") {
          _result += generateNextLine(state, level);
        }
        if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
          _result += "-";
        } else {
          _result += "- ";
        }
        _result += state.dump;
      }
    }
    state.tag = _tag;
    state.dump = _result || "[]";
  }
  function writeFlowMapping(state, level, object) {
    let _result = "";
    const _tag = state.tag;
    const objectKeyList = Object.keys(object);
    for (let index = 0, length = objectKeyList.length; index < length; index += 1) {
      let pairBuffer = "";
      if (_result !== "") pairBuffer += ", ";
      if (state.condenseFlow) pairBuffer += '"';
      const objectKey = objectKeyList[index];
      let objectValue = object[objectKey];
      if (state.replacer) {
        objectValue = state.replacer.call(object, objectKey, objectValue);
      }
      if (!writeNode(state, level, objectKey, false, false)) {
        continue;
      }
      if (state.dump.length > 1024) pairBuffer += "? ";
      pairBuffer += state.dump + (state.condenseFlow ? '"' : "") + ":" + (state.condenseFlow ? "" : " ");
      if (!writeNode(state, level, objectValue, false, false)) {
        continue;
      }
      pairBuffer += state.dump;
      _result += pairBuffer;
    }
    state.tag = _tag;
    state.dump = "{" + _result + "}";
  }
  function writeBlockMapping(state, level, object, compact) {
    let _result = "";
    const _tag = state.tag;
    const objectKeyList = Object.keys(object);
    if (state.sortKeys === true) {
      objectKeyList.sort();
    } else if (typeof state.sortKeys === "function") {
      objectKeyList.sort(state.sortKeys);
    } else if (state.sortKeys) {
      throw new YAMLException2("sortKeys must be a boolean or a function");
    }
    for (let index = 0, length = objectKeyList.length; index < length; index += 1) {
      let pairBuffer = "";
      if (!compact || _result !== "") {
        pairBuffer += generateNextLine(state, level);
      }
      const objectKey = objectKeyList[index];
      let objectValue = object[objectKey];
      if (state.replacer) {
        objectValue = state.replacer.call(object, objectKey, objectValue);
      }
      if (!writeNode(state, level + 1, objectKey, true, true, true)) {
        continue;
      }
      const explicitPair = state.tag !== null && state.tag !== "?" || state.dump && state.dump.length > 1024;
      if (explicitPair) {
        if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
          pairBuffer += "?";
        } else {
          pairBuffer += "? ";
        }
      }
      pairBuffer += state.dump;
      if (explicitPair) {
        pairBuffer += generateNextLine(state, level);
      }
      if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
        continue;
      }
      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
        pairBuffer += ":";
      } else {
        pairBuffer += ": ";
      }
      pairBuffer += state.dump;
      _result += pairBuffer;
    }
    state.tag = _tag;
    state.dump = _result || "{}";
  }
  function detectType(state, object, explicit) {
    const typeList = explicit ? state.explicitTypes : state.implicitTypes;
    for (let index = 0, length = typeList.length; index < length; index += 1) {
      const type2 = typeList[index];
      if ((type2.instanceOf || type2.predicate) && (!type2.instanceOf || typeof object === "object" && object instanceof type2.instanceOf) && (!type2.predicate || type2.predicate(object))) {
        if (explicit) {
          if (type2.multi && type2.representName) {
            state.tag = type2.representName(object);
          } else {
            state.tag = type2.tag;
          }
        } else {
          state.tag = "?";
        }
        if (type2.represent) {
          const style = state.styleMap[type2.tag] || type2.defaultStyle;
          let _result;
          if (_toString.call(type2.represent) === "[object Function]") {
            _result = type2.represent(object, style);
          } else if (_hasOwnProperty.call(type2.represent, style)) {
            _result = type2.represent[style](object, style);
          } else {
            throw new YAMLException2("!<" + type2.tag + '> tag resolver accepts not "' + style + '" style');
          }
          state.dump = _result;
        }
        return true;
      }
    }
    return false;
  }
  function writeNode(state, level, object, block, compact, iskey, isblockseq) {
    state.tag = null;
    state.dump = object;
    if (!detectType(state, object, false)) {
      detectType(state, object, true);
    }
    const type2 = _toString.call(state.dump);
    const inblock = block;
    if (block) {
      block = state.flowLevel < 0 || state.flowLevel > level;
    }
    const objectOrArray = type2 === "[object Object]" || type2 === "[object Array]";
    let duplicateIndex;
    let duplicate;
    if (objectOrArray) {
      duplicateIndex = state.duplicates.indexOf(object);
      duplicate = duplicateIndex !== -1;
    }
    if (state.tag !== null && state.tag !== "?" || duplicate || state.indent !== 2 && level > 0) {
      compact = false;
    }
    if (duplicate && state.usedDuplicates[duplicateIndex]) {
      state.dump = "*ref_" + duplicateIndex;
    } else {
      if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
        state.usedDuplicates[duplicateIndex] = true;
      }
      if (type2 === "[object Object]") {
        if (block && Object.keys(state.dump).length !== 0) {
          writeBlockMapping(state, level, state.dump, compact);
          if (duplicate) {
            state.dump = "&ref_" + duplicateIndex + state.dump;
          }
        } else {
          writeFlowMapping(state, level, state.dump);
          if (duplicate) {
            state.dump = "&ref_" + duplicateIndex + " " + state.dump;
          }
        }
      } else if (type2 === "[object Array]") {
        if (block && state.dump.length !== 0) {
          if (state.noArrayIndent && !isblockseq && level > 0) {
            writeBlockSequence(state, level - 1, state.dump, compact);
          } else {
            writeBlockSequence(state, level, state.dump, compact);
          }
          if (duplicate) {
            state.dump = "&ref_" + duplicateIndex + state.dump;
          }
        } else {
          writeFlowSequence(state, level, state.dump);
          if (duplicate) {
            state.dump = "&ref_" + duplicateIndex + " " + state.dump;
          }
        }
      } else if (type2 === "[object String]") {
        if (state.tag !== "?") {
          writeScalar(state, state.dump, level, iskey, inblock);
        }
      } else if (type2 === "[object Undefined]") {
        return false;
      } else {
        if (state.skipInvalid) return false;
        throw new YAMLException2("unacceptable kind of an object to dump " + type2);
      }
      if (state.tag !== null && state.tag !== "?") {
        let tagStr = encodeURI(
          state.tag[0] === "!" ? state.tag.slice(1) : state.tag
        ).replace(/!/g, "%21");
        if (state.tag[0] === "!") {
          tagStr = "!" + tagStr;
        } else if (tagStr.slice(0, 18) === "tag:yaml.org,2002:") {
          tagStr = "!!" + tagStr.slice(18);
        } else {
          tagStr = "!<" + tagStr + ">";
        }
        state.dump = tagStr + " " + state.dump;
      }
    }
    return true;
  }
  function getDuplicateReferences(object, state) {
    const objects = [];
    const duplicatesIndexes = [];
    inspectNode(object, objects, duplicatesIndexes);
    const length = duplicatesIndexes.length;
    for (let index = 0; index < length; index += 1) {
      state.duplicates.push(objects[duplicatesIndexes[index]]);
    }
    state.usedDuplicates = new Array(length);
  }
  function inspectNode(object, objects, duplicatesIndexes) {
    if (object !== null && typeof object === "object") {
      const index = objects.indexOf(object);
      if (index !== -1) {
        if (duplicatesIndexes.indexOf(index) === -1) {
          duplicatesIndexes.push(index);
        }
      } else {
        objects.push(object);
        if (Array.isArray(object)) {
          for (let i = 0, length = object.length; i < length; i += 1) {
            inspectNode(object[i], objects, duplicatesIndexes);
          }
        } else {
          const objectKeyList = Object.keys(object);
          for (let i = 0, length = objectKeyList.length; i < length; i += 1) {
            inspectNode(object[objectKeyList[i]], objects, duplicatesIndexes);
          }
        }
      }
    }
  }
  function dump2(input, options) {
    options = options || {};
    const state = new State(options);
    if (!state.noRefs) getDuplicateReferences(input, state);
    let value = input;
    if (state.replacer) {
      value = state.replacer.call({ "": value }, "", value);
    }
    if (writeNode(state, 0, value, true, true)) return state.dump + "\n";
    return "";
  }
  dumper.dump = dump2;
  return dumper;
}
var hasRequiredJsYaml;
function requireJsYaml() {
  if (hasRequiredJsYaml) return jsYaml;
  hasRequiredJsYaml = 1;
  const loader2 = requireLoader();
  const dumper2 = requireDumper();
  function renamed(from, to) {
    return function() {
      throw new Error("Function yaml." + from + " is removed in js-yaml 4. Use yaml." + to + " instead, which is now safe by default.");
    };
  }
  jsYaml.Type = requireType();
  jsYaml.Schema = requireSchema();
  jsYaml.FAILSAFE_SCHEMA = requireFailsafe();
  jsYaml.JSON_SCHEMA = requireJson();
  jsYaml.CORE_SCHEMA = requireCore();
  jsYaml.DEFAULT_SCHEMA = require_default();
  jsYaml.load = loader2.load;
  jsYaml.loadAll = loader2.loadAll;
  jsYaml.dump = dumper2.dump;
  jsYaml.YAMLException = requireException();
  jsYaml.types = {
    binary: requireBinary(),
    float: requireFloat(),
    map: requireMap(),
    null: require_null(),
    pairs: requirePairs(),
    set: requireSet(),
    timestamp: requireTimestamp(),
    bool: requireBool(),
    int: requireInt(),
    merge: requireMerge(),
    omap: requireOmap(),
    seq: requireSeq(),
    str: requireStr()
  };
  jsYaml.safeLoad = renamed("safeLoad", "load");
  jsYaml.safeLoadAll = renamed("safeLoadAll", "loadAll");
  jsYaml.safeDump = renamed("safeDump", "dump");
  return jsYaml;
}
var jsYamlExports = requireJsYaml();
const yaml = /* @__PURE__ */ getDefaultExportFromCjs(jsYamlExports);
const {
  Type,
  Schema,
  FAILSAFE_SCHEMA,
  JSON_SCHEMA,
  CORE_SCHEMA,
  DEFAULT_SCHEMA,
  load,
  loadAll,
  dump,
  YAMLException,
  types,
  safeLoad,
  safeLoadAll,
  safeDump
} = yaml;
export {
  CORE_SCHEMA,
  DEFAULT_SCHEMA,
  FAILSAFE_SCHEMA,
  JSON_SCHEMA,
  Schema,
  Type,
  YAMLException,
  yaml as default,
  dump,
  load,
  loadAll,
  safeDump,
  safeLoad,
  safeLoadAll,
  types
};
//# sourceMappingURL=js-yaml.mjs.map
{"version":3,"file":"js-yaml.mjs","sources":["../lib/common.js","../lib/exception.js","../lib/snippet.js","../lib/type.js","../lib/schema.js","../lib/type/str.js","../lib/type/seq.js","../lib/type/map.js","../lib/schema/failsafe.js","../lib/type/null.js","../lib/type/bool.js","../lib/type/int.js","../lib/type/float.js","../lib/schema/json.js","../lib/schema/core.js","../lib/type/timestamp.js","../lib/type/merge.js","../lib/type/binary.js","../lib/type/omap.js","../lib/type/pairs.js","../lib/type/set.js","../lib/schema/default.js","../lib/loader.js","../lib/dumper.js","../index.js","../lib/index_vite_proxy.tmp.mjs"],"sourcesContent":["'use strict'\n\nfunction isNothing (subject) {\n  return (typeof subject === 'undefined') || (subject === null)\n}\n\nfunction isObject (subject) {\n  return (typeof subject === 'object') && (subject !== null)\n}\n\nfunction toArray (sequence) {\n  if (Array.isArray(sequence)) return sequence\n  else if (isNothing(sequence)) return []\n\n  return [sequence]\n}\n\nfunction extend (target, source) {\n  if (source) {\n    const sourceKeys = Object.keys(source)\n\n    for (let index = 0, length = sourceKeys.length; index < length; index += 1) {\n      const key = sourceKeys[index]\n      target[key] = source[key]\n    }\n  }\n\n  return target\n}\n\nfunction repeat (string, count) {\n  let result = ''\n\n  for (let cycle = 0; cycle < count; cycle += 1) {\n    result += string\n  }\n\n  return result\n}\n\nfunction isNegativeZero (number) {\n  return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number)\n}\n\nmodule.exports.isNothing = isNothing\nmodule.exports.isObject = isObject\nmodule.exports.toArray = toArray\nmodule.exports.repeat = repeat\nmodule.exports.isNegativeZero = isNegativeZero\nmodule.exports.extend = extend\n","// YAML error class. http://stackoverflow.com/questions/8458984\n//\n'use strict'\n\nfunction formatError (exception, compact) {\n  let where = ''\n  const message = exception.reason || '(unknown reason)'\n\n  if (!exception.mark) return message\n\n  if (exception.mark.name) {\n    where += 'in \"' + exception.mark.name + '\" '\n  }\n\n  where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')'\n\n  if (!compact && exception.mark.snippet) {\n    where += '\\n\\n' + exception.mark.snippet\n  }\n\n  return message + ' ' + where\n}\n\nfunction YAMLException (reason, mark) {\n  // Super constructor\n  Error.call(this)\n\n  this.name = 'YAMLException'\n  this.reason = reason\n  this.mark = mark\n  this.message = formatError(this, false)\n\n  // Include stack trace in error object\n  if (Error.captureStackTrace) {\n    // Chrome and NodeJS\n    Error.captureStackTrace(this, this.constructor)\n  } else {\n    // FF, IE 10+ and Safari 6+. Fallback for others\n    this.stack = (new Error()).stack || ''\n  }\n}\n\n// Inherit from Error\nYAMLException.prototype = Object.create(Error.prototype)\nYAMLException.prototype.constructor = YAMLException\n\nYAMLException.prototype.toString = function toString (compact) {\n  return this.name + ': ' + formatError(this, compact)\n}\n\nmodule.exports = YAMLException\n","'use strict'\n\nconst common = require('./common')\n\n// get snippet for a single line, respecting maxLength\nfunction getLine (buffer, lineStart, lineEnd, position, maxLineLength) {\n  let head = ''\n  let tail = ''\n  const maxHalfLength = Math.floor(maxLineLength / 2) - 1\n\n  if (position - lineStart > maxHalfLength) {\n    head = ' ... '\n    lineStart = position - maxHalfLength + head.length\n  }\n\n  if (lineEnd - position > maxHalfLength) {\n    tail = ' ...'\n    lineEnd = position + maxHalfLength - tail.length\n  }\n\n  return {\n    str: head + buffer.slice(lineStart, lineEnd).replace(/\\t/g, '→') + tail,\n    pos: position - lineStart + head.length // relative position\n  }\n}\n\nfunction padStart (string, max) {\n  return common.repeat(' ', max - string.length) + string\n}\n\nfunction makeSnippet (mark, options) {\n  options = Object.create(options || null)\n\n  if (!mark.buffer) return null\n\n  if (!options.maxLength) options.maxLength = 79\n  if (typeof options.indent !== 'number') options.indent = 1\n  if (typeof options.linesBefore !== 'number') options.linesBefore = 3\n  if (typeof options.linesAfter !== 'number') options.linesAfter = 2\n\n  const re = /\\r?\\n|\\r|\\0/g\n  const lineStarts = [0]\n  const lineEnds = []\n  let match\n  let foundLineNo = -1\n\n  while ((match = re.exec(mark.buffer))) {\n    lineEnds.push(match.index)\n    lineStarts.push(match.index + match[0].length)\n\n    if (mark.position <= match.index && foundLineNo < 0) {\n      foundLineNo = lineStarts.length - 2\n    }\n  }\n\n  if (foundLineNo < 0) foundLineNo = lineStarts.length - 1\n\n  let result = ''\n  const lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length\n  const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3)\n\n  for (let i = 1; i <= options.linesBefore; i++) {\n    if (foundLineNo - i < 0) break\n    const line = getLine(\n      mark.buffer,\n      lineStarts[foundLineNo - i],\n      lineEnds[foundLineNo - i],\n      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),\n      maxLineLength\n    )\n    result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) +\n      ' | ' + line.str + '\\n' + result\n  }\n\n  const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength)\n  result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) +\n    ' | ' + line.str + '\\n'\n  result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\\n'\n\n  for (let i = 1; i <= options.linesAfter; i++) {\n    if (foundLineNo + i >= lineEnds.length) break\n    const line = getLine(\n      mark.buffer,\n      lineStarts[foundLineNo + i],\n      lineEnds[foundLineNo + i],\n      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),\n      maxLineLength\n    )\n    result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) +\n      ' | ' + line.str + '\\n'\n  }\n\n  return result.replace(/\\n$/, '')\n}\n\nmodule.exports = makeSnippet\n","'use strict'\n\nconst YAMLException = require('./exception')\n\nconst TYPE_CONSTRUCTOR_OPTIONS = [\n  'kind',\n  'multi',\n  'resolve',\n  'construct',\n  'instanceOf',\n  'predicate',\n  'represent',\n  'representName',\n  'defaultStyle',\n  'styleAliases'\n]\n\nconst YAML_NODE_KINDS = [\n  'scalar',\n  'sequence',\n  'mapping'\n]\n\nfunction compileStyleAliases (map) {\n  const result = {}\n\n  if (map !== null) {\n    Object.keys(map).forEach(function (style) {\n      map[style].forEach(function (alias) {\n        result[String(alias)] = style\n      })\n    })\n  }\n\n  return result\n}\n\nfunction Type (tag, options) {\n  options = options || {}\n\n  Object.keys(options).forEach(function (name) {\n    if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {\n      throw new YAMLException('Unknown option \"' + name + '\" is met in definition of \"' + tag + '\" YAML type.')\n    }\n  })\n\n  // TODO: Add tag format check.\n  this.options = options // keep original options in case user wants to extend this type later\n  this.tag = tag\n  this.kind = options['kind'] || null\n  this.resolve = options['resolve'] || function () { return true }\n  this.construct = options['construct'] || function (data) { return data }\n  this.instanceOf = options['instanceOf'] || null\n  this.predicate = options['predicate'] || null\n  this.represent = options['represent'] || null\n  this.representName = options['representName'] || null\n  this.defaultStyle = options['defaultStyle'] || null\n  this.multi = options['multi'] || false\n  this.styleAliases = compileStyleAliases(options['styleAliases'] || null)\n\n  if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {\n    throw new YAMLException('Unknown kind \"' + this.kind + '\" is specified for \"' + tag + '\" YAML type.')\n  }\n}\n\nmodule.exports = Type\n","'use strict'\n\nconst YAMLException = require('./exception')\nconst Type = require('./type')\n\nfunction compileList (schema, name) {\n  const result = []\n\n  schema[name].forEach(function (currentType) {\n    let newIndex = result.length\n\n    result.forEach(function (previousType, previousIndex) {\n      if (previousType.tag === currentType.tag &&\n          previousType.kind === currentType.kind &&\n          previousType.multi === currentType.multi) {\n        newIndex = previousIndex\n      }\n    })\n\n    result[newIndex] = currentType\n  })\n\n  return result\n}\n\nfunction compileMap (/* lists... */) {\n  const result = {\n    scalar: {},\n    sequence: {},\n    mapping: {},\n    fallback: {},\n    multi: {\n      scalar: [],\n      sequence: [],\n      mapping: [],\n      fallback: []\n    }\n  }\n  function collectType (type) {\n    if (type.multi) {\n      result.multi[type.kind].push(type)\n      result.multi['fallback'].push(type)\n    } else {\n      result[type.kind][type.tag] = result['fallback'][type.tag] = type\n    }\n  }\n\n  for (let index = 0, length = arguments.length; index < length; index += 1) {\n    arguments[index].forEach(collectType)\n  }\n  return result\n}\n\nfunction Schema (definition) {\n  return this.extend(definition)\n}\n\nSchema.prototype.extend = function extend (definition) {\n  let implicit = []\n  let explicit = []\n\n  if (definition instanceof Type) {\n    // Schema.extend(type)\n    explicit.push(definition)\n  } else if (Array.isArray(definition)) {\n    // Schema.extend([ type1, type2, ... ])\n    explicit = explicit.concat(definition)\n  } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {\n    // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] })\n    if (definition.implicit) implicit = implicit.concat(definition.implicit)\n    if (definition.explicit) explicit = explicit.concat(definition.explicit)\n  } else {\n    throw new YAMLException('Schema.extend argument should be a Type, [ Type ], ' +\n      'or a schema definition ({ implicit: [...], explicit: [...] })')\n  }\n\n  implicit.forEach(function (type) {\n    if (!(type instanceof Type)) {\n      throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')\n    }\n\n    if (type.loadKind && type.loadKind !== 'scalar') {\n      throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.')\n    }\n\n    if (type.multi) {\n      throw new YAMLException('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.')\n    }\n  })\n\n  explicit.forEach(function (type) {\n    if (!(type instanceof Type)) {\n      throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.')\n    }\n  })\n\n  const result = Object.create(Schema.prototype)\n\n  result.implicit = (this.implicit || []).concat(implicit)\n  result.explicit = (this.explicit || []).concat(explicit)\n\n  result.compiledImplicit = compileList(result, 'implicit')\n  result.compiledExplicit = compileList(result, 'explicit')\n  result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit)\n\n  return result\n}\n\nmodule.exports = Schema\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:str', {\n  kind: 'scalar',\n  construct: function (data) { return data !== null ? data : '' }\n})\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:seq', {\n  kind: 'sequence',\n  construct: function (data) { return data !== null ? data : [] }\n})\n","'use strict'\n\nconst Type = require('../type')\n\nmodule.exports = new Type('tag:yaml.org,2002:map', {\n  kind: 'mapping',\n  construct: function (data) { return data !== null ? data : {} }\n})\n","// Standard YAML's Failsafe schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2802346\n\n'use strict'\n\nconst Schema = require('../schema')\n\nmodule.exports = new Schema({\n  explicit: [\n    require('../type/str'),\n    require('../type/seq'),\n    require('../type/map')\n  ]\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlNull (data) {\n  if (data === null) return true\n\n  const max = data.length\n\n  return (max === 1 && data === '~') ||\n         (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'))\n}\n\nfunction constructYamlNull () {\n  return null\n}\n\nfunction isNull (object) {\n  return object === null\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:null', {\n  kind: 'scalar',\n  resolve: resolveYamlNull,\n  construct: constructYamlNull,\n  predicate: isNull,\n  represent: {\n    canonical: function () { return '~' },\n    lowercase: function () { return 'null' },\n    uppercase: function () { return 'NULL' },\n    camelcase: function () { return 'Null' },\n    empty: function () { return '' }\n  },\n  defaultStyle: 'lowercase'\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlBoolean (data) {\n  if (data === null) return false\n\n  const max = data.length\n\n  return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||\n         (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'))\n}\n\nfunction constructYamlBoolean (data) {\n  return data === 'true' ||\n         data === 'True' ||\n         data === 'TRUE'\n}\n\nfunction isBoolean (object) {\n  return Object.prototype.toString.call(object) === '[object Boolean]'\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:bool', {\n  kind: 'scalar',\n  resolve: resolveYamlBoolean,\n  construct: constructYamlBoolean,\n  predicate: isBoolean,\n  represent: {\n    lowercase: function (object) { return object ? 'true' : 'false' },\n    uppercase: function (object) { return object ? 'TRUE' : 'FALSE' },\n    camelcase: function (object) { return object ? 'True' : 'False' }\n  },\n  defaultStyle: 'lowercase'\n})\n","'use strict'\n\nconst common = require('../common')\nconst Type = require('../type')\n\nfunction isHexCode (c) {\n  return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) ||\n         ((c >= 0x41/* A */) && (c <= 0x46/* F */)) ||\n         ((c >= 0x61/* a */) && (c <= 0x66/* f */))\n}\n\nfunction isOctCode (c) {\n  return ((c >= 0x30/* 0 */) && (c <= 0x37/* 7 */))\n}\n\nfunction isDecCode (c) {\n  return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */))\n}\n\nfunction resolveYamlInteger (data) {\n  if (data === null) return false\n\n  const max = data.length\n  let index = 0\n  let hasDigits = false\n\n  if (!max) return false\n\n  let ch = data[index]\n\n  // sign\n  if (ch === '-' || ch === '+') {\n    ch = data[++index]\n  }\n\n  if (ch === '0') {\n    // 0\n    if (index + 1 === max) return true\n    ch = data[++index]\n\n    // base 2, base 8, base 16\n\n    if (ch === 'b') {\n      // base 2\n      index++\n\n      for (; index < max; index++) {\n        ch = data[index]\n        if (ch !== '0' && ch !== '1') return false\n        hasDigits = true\n      }\n      return hasDigits && isFinite(parseYamlInteger(data))\n    }\n\n    if (ch === 'x') {\n      // base 16\n      index++\n\n      for (; index < max; index++) {\n        if (!isHexCode(data.charCodeAt(index))) return false\n        hasDigits = true\n      }\n      return hasDigits && isFinite(parseYamlInteger(data))\n    }\n\n    if (ch === 'o') {\n      // base 8\n      index++\n\n      for (; index < max; index++) {\n        if (!isOctCode(data.charCodeAt(index))) return false\n        hasDigits = true\n      }\n      return hasDigits && isFinite(parseYamlInteger(data))\n    }\n  }\n\n  // base 10 (except 0)\n\n  for (; index < max; index++) {\n    if (!isDecCode(data.charCodeAt(index))) {\n      return false\n    }\n    hasDigits = true\n  }\n\n  if (!hasDigits) return false\n\n  return isFinite(parseYamlInteger(data))\n}\n\nfunction parseYamlInteger (data) {\n  let value = data\n  let sign = 1\n\n  let ch = value[0]\n\n  if (ch === '-' || ch === '+') {\n    if (ch === '-') sign = -1\n    value = value.slice(1)\n    ch = value[0]\n  }\n\n  if (value === '0') return 0\n\n  if (ch === '0') {\n    if (value[1] === 'b') return sign * parseInt(value.slice(2), 2)\n    if (value[1] === 'x') return sign * parseInt(value.slice(2), 16)\n    if (value[1] === 'o') return sign * parseInt(value.slice(2), 8)\n  }\n\n  return sign * parseInt(value, 10)\n}\n\nfunction constructYamlInteger (data) {\n  return parseYamlInteger(data)\n}\n\nfunction isInteger (object) {\n  return (Object.prototype.toString.call(object)) === '[object Number]' &&\n         (object % 1 === 0 && !common.isNegativeZero(object))\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:int', {\n  kind: 'scalar',\n  resolve: resolveYamlInteger,\n  construct: constructYamlInteger,\n  predicate: isInteger,\n  represent: {\n    binary: function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1) },\n    octal: function (obj) { return obj >= 0 ? '0o' + obj.toString(8) : '-0o' + obj.toString(8).slice(1) },\n    decimal: function (obj) { return obj.toString(10) },\n    hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() : '-0x' + obj.toString(16).toUpperCase().slice(1) }\n  },\n  defaultStyle: 'decimal',\n  styleAliases: {\n    binary: [2, 'bin'],\n    octal: [8, 'oct'],\n    decimal: [10, 'dec'],\n    hexadecimal: [16, 'hex']\n  }\n})\n","'use strict'\n\nconst common = require('../common')\nconst Type = require('../type')\n\nconst YAML_FLOAT_PATTERN = new RegExp(\n  // 2.5e4, 2.5 and integers\n  '^(?:[-+]?(?:[0-9]+)(?:\\\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?' +\n  // .2e4, .2\n  // special case, seems not from spec\n  '|\\\\.[0-9]+(?:[eE][-+]?[0-9]+)?' +\n  // .inf\n  '|[-+]?\\\\.(?:inf|Inf|INF)' +\n  // .nan\n  '|\\\\.(?:nan|NaN|NAN))$')\n\nconst YAML_FLOAT_SPECIAL_PATTERN = new RegExp(\n  '^(?:' +\n  // .inf\n  '[-+]?\\\\.(?:inf|Inf|INF)' +\n  // .nan\n  '|\\\\.(?:nan|NaN|NAN))$')\n\nfunction resolveYamlFloat (data) {\n  if (data === null) return false\n\n  if (!YAML_FLOAT_PATTERN.test(data)) {\n    return false\n  }\n\n  if (isFinite(parseFloat(data, 10))) {\n    return true\n  }\n\n  return YAML_FLOAT_SPECIAL_PATTERN.test(data)\n}\n\nfunction constructYamlFloat (data) {\n  let value = data.toLowerCase()\n  const sign = value[0] === '-' ? -1 : 1\n\n  if ('+-'.indexOf(value[0]) >= 0) {\n    value = value.slice(1)\n  }\n\n  if (value === '.inf') {\n    return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY\n  } else if (value === '.nan') {\n    return NaN\n  }\n  return sign * parseFloat(value, 10)\n}\n\nconst SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/\n\nfunction representYamlFloat (object, style) {\n  if (isNaN(object)) {\n    switch (style) {\n      case 'lowercase': return '.nan'\n      case 'uppercase': return '.NAN'\n      case 'camelcase': return '.NaN'\n    }\n  } else if (Number.POSITIVE_INFINITY === object) {\n    switch (style) {\n      case 'lowercase': return '.inf'\n      case 'uppercase': return '.INF'\n      case 'camelcase': return '.Inf'\n    }\n  } else if (Number.NEGATIVE_INFINITY === object) {\n    switch (style) {\n      case 'lowercase': return '-.inf'\n      case 'uppercase': return '-.INF'\n      case 'camelcase': return '-.Inf'\n    }\n  } else if (common.isNegativeZero(object)) {\n    return '-0.0'\n  }\n\n  const res = object.toString(10)\n\n  // JS stringifier can build scientific format without dots: 5e-100,\n  // while YAML requres dot: 5.e-100. Fix it with simple hack\n\n  return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res\n}\n\nfunction isFloat (object) {\n  return (Object.prototype.toString.call(object) === '[object Number]') &&\n         (object % 1 !== 0 || common.isNegativeZero(object))\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:float', {\n  kind: 'scalar',\n  resolve: resolveYamlFloat,\n  construct: constructYamlFloat,\n  predicate: isFloat,\n  represent: representYamlFloat,\n  defaultStyle: 'lowercase'\n})\n","// Standard YAML's JSON schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2803231\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, this schema is not such strict as defined in the YAML specification.\n// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.\n\n'use strict'\n\nmodule.exports = require('./failsafe').extend({\n  implicit: [\n    require('../type/null'),\n    require('../type/bool'),\n    require('../type/int'),\n    require('../type/float')\n  ]\n})\n","// Standard YAML's Core schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2804923\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, Core schema has no distinctions from JSON schema is JS-YAML.\n\n'use strict'\n\nmodule.exports = require('./json')\n","'use strict'\n\nconst Type = require('../type')\n\nconst YAML_DATE_REGEXP = new RegExp(\n  '^([0-9][0-9][0-9][0-9])' + // [1] year\n  '-([0-9][0-9])' + // [2] month\n  '-([0-9][0-9])$')                   // [3] day\n\nconst YAML_TIMESTAMP_REGEXP = new RegExp(\n  '^([0-9][0-9][0-9][0-9])' + // [1] year\n  '-([0-9][0-9]?)' + // [2] month\n  '-([0-9][0-9]?)' + // [3] day\n  '(?:[Tt]|[ \\\\t]+)' + // ...\n  '([0-9][0-9]?)' + // [4] hour\n  ':([0-9][0-9])' + // [5] minute\n  ':([0-9][0-9])' + // [6] second\n  '(?:\\\\.([0-9]*))?' + // [7] fraction\n  '(?:[ \\\\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tzHour\n  '(?::([0-9][0-9]))?))?$')           // [11] tzMinute\n\nfunction resolveYamlTimestamp (data) {\n  if (data === null) return false\n  if (YAML_DATE_REGEXP.exec(data) !== null) return true\n  if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true\n  return false\n}\n\nfunction constructYamlTimestamp (data) {\n  let fraction = 0\n  let delta = null\n\n  let match = YAML_DATE_REGEXP.exec(data)\n  if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data)\n\n  if (match === null) throw new Error('Date resolve error')\n\n  // match: [1] year [2] month [3] day\n\n  const year = +(match[1])\n  const month = +(match[2]) - 1 // JS month starts with 0\n  const day = +(match[3])\n\n  if (!match[4]) { // no hour\n    return new Date(Date.UTC(year, month, day))\n  }\n\n  // match: [4] hour [5] minute [6] second [7] fraction\n\n  const hour = +(match[4])\n  const minute = +(match[5])\n  const second = +(match[6])\n\n  if (match[7]) {\n    fraction = match[7].slice(0, 3)\n    while (fraction.length < 3) { // milli-seconds\n      fraction += '0'\n    }\n    fraction = +fraction\n  }\n\n  // match: [8] tz [9] tz_sign [10] tzHour [11] tzMinute\n\n  if (match[9]) {\n    const tzHour = +(match[10])\n    const tzMinute = +(match[11] || 0)\n    delta = (tzHour * 60 + tzMinute) * 60000 // delta in mili-seconds\n    if (match[9] === '-') delta = -delta\n  }\n\n  const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction))\n\n  if (delta) date.setTime(date.getTime() - delta)\n\n  return date\n}\n\nfunction representYamlTimestamp (object /*, style */) {\n  return object.toISOString()\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:timestamp', {\n  kind: 'scalar',\n  resolve: resolveYamlTimestamp,\n  construct: constructYamlTimestamp,\n  instanceOf: Date,\n  represent: representYamlTimestamp\n})\n","'use strict'\n\nconst Type = require('../type')\n\nfunction resolveYamlMerge (data) {\n  return data === '<<' || data === null\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:merge', {\n  kind: 'scalar',\n  resolve: resolveYamlMerge\n})\n","'use strict'\n\nconst Type = require('../type')\n\n// [ 64, 65, 66 ] -> [ padding, CR, LF ]\nconst BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\\n\\r'\n\nfunction resolveYamlBinary (data) {\n  if (data === null) return false\n\n  let bitlen = 0\n  const max = data.length\n  const map = BASE64_MAP\n\n  // Convert one by one.\n  for (let idx = 0; idx < max; idx++) {\n    const code = map.indexOf(data.charAt(idx))\n\n    // Skip CR/LF\n    if (code > 64) continue\n\n    // Fail on illegal characters\n    if (code < 0) return false\n\n    bitlen += 6\n  }\n\n  // If there are any bits left, source was corrupted\n  return (bitlen % 8) === 0\n}\n\nfunction constructYamlBinary (data) {\n  const input = data.replace(/[\\r\\n=]/g, '') // remove CR/LF & padding to simplify scan\n  const max = input.length\n  const map = BASE64_MAP\n  let bits = 0\n  const result = []\n\n  // Collect by 6*4 bits (3 bytes)\n\n  for (let idx = 0; idx < max; idx++) {\n    if ((idx % 4 === 0) && idx) {\n      result.push((bits >> 16) & 0xFF)\n      result.push((bits >> 8) & 0xFF)\n      result.push(bits & 0xFF)\n    }\n\n    bits = (bits << 6) | map.indexOf(input.charAt(idx))\n  }\n\n  // Dump tail\n\n  const tailbits = (max % 4) * 6\n\n  if (tailbits === 0) {\n    result.push((bits >> 16) & 0xFF)\n    result.push((bits >> 8) & 0xFF)\n    result.push(bits & 0xFF)\n  } else if (tailbits === 18) {\n    result.push((bits >> 10) & 0xFF)\n    result.push((bits >> 2) & 0xFF)\n  } else if (tailbits === 12) {\n    result.push((bits >> 4) & 0xFF)\n  }\n\n  return new Uint8Array(result)\n}\n\nfunction representYamlBinary (object /*, style */) {\n  let result = ''\n  let bits = 0\n  const max = object.length\n  const map = BASE64_MAP\n\n  // Convert every three bytes to 4 ASCII characters.\n\n  for (let idx = 0; idx < max; idx++) {\n    if ((idx % 3 === 0) && idx) {\n      result += map[(bits >> 18) & 0x3F]\n      result += map[(bits >> 12) & 0x3F]\n      result += map[(bits >> 6) & 0x3F]\n      result += map[bits & 0x3F]\n    }\n\n    bits = (bits << 8) + object[idx]\n  }\n\n  // Dump tail\n\n  const tail = max % 3\n\n  if (tail === 0) {\n    result += map[(bits >> 18) & 0x3F]\n    result += map[(bits >> 12) & 0x3F]\n    result += map[(bits >> 6) & 0x3F]\n    result += map[bits & 0x3F]\n  } else if (tail === 2) {\n    result += map[(bits >> 10) & 0x3F]\n    result += map[(bits >> 4) & 0x3F]\n    result += map[(bits << 2) & 0x3F]\n    result += map[64]\n  } else if (tail === 1) {\n    result += map[(bits >> 2) & 0x3F]\n    result += map[(bits << 4) & 0x3F]\n    result += map[64]\n    result += map[64]\n  }\n\n  return result\n}\n\nfunction isBinary (obj) {\n  return Object.prototype.toString.call(obj) === '[object Uint8Array]'\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:binary', {\n  kind: 'scalar',\n  resolve: resolveYamlBinary,\n  construct: constructYamlBinary,\n  predicate: isBinary,\n  represent: representYamlBinary\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\nconst _toString = Object.prototype.toString\n\nfunction resolveYamlOmap (data) {\n  if (data === null) return true\n\n  const objectKeys = {}\n  const object = data\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    const pair = object[index]\n    let pairHasKey = false\n\n    if (_toString.call(pair) !== '[object Object]') return false\n\n    let pairKey\n    for (pairKey in pair) {\n      if (_hasOwnProperty.call(pair, pairKey)) {\n        if (!pairHasKey) pairHasKey = true\n        else return false\n      }\n    }\n\n    if (!pairHasKey) return false\n\n    if (_hasOwnProperty.call(objectKeys, pairKey)) return false\n    Object.defineProperty(objectKeys, pairKey, { value: true })\n  }\n\n  return true\n}\n\nfunction constructYamlOmap (data) {\n  return data !== null ? data : []\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:omap', {\n  kind: 'sequence',\n  resolve: resolveYamlOmap,\n  construct: constructYamlOmap\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _toString = Object.prototype.toString\n\nfunction resolveYamlPairs (data) {\n  if (data === null) return true\n\n  const object = data\n\n  const result = new Array(object.length)\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    const pair = object[index]\n\n    if (_toString.call(pair) !== '[object Object]') return false\n\n    const keys = Object.keys(pair)\n\n    if (keys.length !== 1) return false\n\n    result[index] = [keys[0], pair[keys[0]]]\n  }\n\n  return true\n}\n\nfunction constructYamlPairs (data) {\n  if (data === null) return []\n\n  const object = data\n  const result = new Array(object.length)\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    const pair = object[index]\n\n    const keys = Object.keys(pair)\n\n    result[index] = [keys[0], pair[keys[0]]]\n  }\n\n  return result\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:pairs', {\n  kind: 'sequence',\n  resolve: resolveYamlPairs,\n  construct: constructYamlPairs\n})\n","'use strict'\n\nconst Type = require('../type')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nfunction resolveYamlSet (data) {\n  if (data === null) return true\n\n  const object = data\n\n  for (const key in object) {\n    if (_hasOwnProperty.call(object, key)) {\n      if (object[key] !== null) return false\n    }\n  }\n\n  return true\n}\n\nfunction constructYamlSet (data) {\n  return data !== null ? data : {}\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:set', {\n  kind: 'mapping',\n  resolve: resolveYamlSet,\n  construct: constructYamlSet\n})\n","// JS-YAML's default schema for `safeLoad` function.\n// It is not described in the YAML specification.\n//\n// This schema is based on standard YAML's Core schema and includes most of\n// extra types described at YAML tag repository. (http://yaml.org/type/)\n\n'use strict'\n\nmodule.exports = require('./core').extend({\n  implicit: [\n    require('../type/timestamp'),\n    require('../type/merge')\n  ],\n  explicit: [\n    require('../type/binary'),\n    require('../type/omap'),\n    require('../type/pairs'),\n    require('../type/set')\n  ]\n})\n","'use strict'\n\nconst common = require('./common')\nconst YAMLException = require('./exception')\nconst makeSnippet = require('./snippet')\nconst DEFAULT_SCHEMA = require('./schema/default')\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nconst CONTEXT_FLOW_IN = 1\nconst CONTEXT_FLOW_OUT = 2\nconst CONTEXT_BLOCK_IN = 3\nconst CONTEXT_BLOCK_OUT = 4\n\nconst CHOMPING_CLIP = 1\nconst CHOMPING_STRIP = 2\nconst CHOMPING_KEEP = 3\n\n// eslint-disable-next-line no-control-regex\nconst PATTERN_NON_PRINTABLE = /[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x84\\x86-\\x9F\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/\nconst PATTERN_NON_ASCII_LINE_BREAKS = /[\\x85\\u2028\\u2029]/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_FLOW_INDICATORS = /[,\\[\\]{}]/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/\n// eslint-disable-next-line no-useless-escape\nconst PATTERN_TAG_URI = /^(?:!|[^,\\[\\]{}])(?:%[0-9a-f]{2}|[0-9a-z\\-#;/?:@&=+$,_.!~*'()\\[\\]])*$/i\n\nfunction _class (obj) { return Object.prototype.toString.call(obj) }\n\nfunction isEol (c) {\n  return (c === 0x0A/* LF */) || (c === 0x0D/* CR */)\n}\n\nfunction isWhiteSpace (c) {\n  return (c === 0x09/* Tab */) || (c === 0x20/* Space */)\n}\n\nfunction isWsOrEol (c) {\n  return (c === 0x09/* Tab */) ||\n         (c === 0x20/* Space */) ||\n         (c === 0x0A/* LF */) ||\n         (c === 0x0D/* CR */)\n}\n\nfunction isFlowIndicator (c) {\n  return c === 0x2C/* , */ ||\n         c === 0x5B/* [ */ ||\n         c === 0x5D/* ] */ ||\n         c === 0x7B/* { */ ||\n         c === 0x7D/* } */\n}\n\nfunction fromHexCode (c) {\n  if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {\n    return c - 0x30\n  }\n\n  const lc = c | 0x20\n\n  if ((lc >= 0x61/* a */) && (lc <= 0x66/* f */)) {\n    return lc - 0x61 + 10\n  }\n\n  return -1\n}\n\nfunction escapedHexLen (c) {\n  if (c === 0x78/* x */) { return 2 }\n  if (c === 0x75/* u */) { return 4 }\n  if (c === 0x55/* U */) { return 8 }\n  return 0\n}\n\nfunction fromDecimalCode (c) {\n  if ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) {\n    return c - 0x30\n  }\n\n  return -1\n}\n\nfunction simpleEscapeSequence (c) {\n  switch (c) {\n    case 0x30/* 0 */: return '\\x00'\n    case 0x61/* a */: return '\\x07'\n    case 0x62/* b */: return '\\x08'\n    case 0x74/* t */: return '\\x09'\n    case 0x09/* Tab */: return '\\x09'\n    case 0x6E/* n */: return '\\x0A'\n    case 0x76/* v */: return '\\x0B'\n    case 0x66/* f */: return '\\x0C'\n    case 0x72/* r */: return '\\x0D'\n    case 0x65/* e */: return '\\x1B'\n    case 0x20/* Space */: return ' '\n    case 0x22/* \" */: return '\\x22'\n    case 0x2F/* / */: return '/'\n    case 0x5C/* \\ */: return '\\x5C'\n    case 0x4E/* N */: return '\\x85'\n    case 0x5F/* _ */: return '\\xA0'\n    case 0x4C/* L */: return '\\u2028'\n    case 0x50/* P */: return '\\u2029'\n    default: return ''\n  }\n}\n\nfunction charFromCodepoint (c) {\n  if (c <= 0xFFFF) {\n    return String.fromCharCode(c)\n  }\n  // Encode UTF-16 surrogate pair\n  // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF\n  return String.fromCharCode(\n    ((c - 0x010000) >> 10) + 0xD800,\n    ((c - 0x010000) & 0x03FF) + 0xDC00\n  )\n}\n\n// set a property of a literal object, while protecting against prototype pollution,\n// see https://github.com/nodeca/js-yaml/issues/164 for more details\nfunction setProperty (object, key, value) {\n  // used for this specific key only because Object.defineProperty is slow\n  if (key === '__proto__') {\n    Object.defineProperty(object, key, {\n      configurable: true,\n      enumerable: true,\n      writable: true,\n      value: value\n    })\n  } else {\n    object[key] = value\n  }\n}\n\nconst simpleEscapeCheck = new Array(256) // integer, for fast access\nconst simpleEscapeMap = new Array(256)\nfor (let i = 0; i < 256; i++) {\n  simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0\n  simpleEscapeMap[i] = simpleEscapeSequence(i)\n}\n\nfunction State (input, options) {\n  this.input = input\n\n  this.filename = options['filename'] || null\n  this.schema = options['schema'] || DEFAULT_SCHEMA\n  this.onWarning = options['onWarning'] || null\n  // (Hidden) Remove? makes the loader to expect YAML 1.1 documents\n  // if such documents have no explicit %YAML directive\n  this.legacy = options['legacy'] || false\n\n  this.json = options['json'] || false\n  this.listener = options['listener'] || null\n  this.maxDepth = typeof options['maxDepth'] === 'number' ? options['maxDepth'] : 100\n  this.maxTotalMergeKeys = typeof options['maxTotalMergeKeys'] === 'number' ? options['maxTotalMergeKeys'] : 10000\n\n  this.implicitTypes = this.schema.compiledImplicit\n  this.typeMap = this.schema.compiledTypeMap\n\n  this.length = input.length\n  this.position = 0\n  this.line = 0\n  this.lineStart = 0\n  this.lineIndent = 0\n  this.depth = 0\n  this.totalMergeKeys = 0\n\n  // position of first leading tab in the current line,\n  // used to make sure there are no tabs in the indentation\n  this.firstTabInLine = -1\n\n  this.documents = []\n  this.anchorMapTransactions = []\n\n  /*\n  this.version;\n  this.checkLineBreaks;\n  this.tagMap;\n  this.anchorMap;\n  this.tag;\n  this.anchor;\n  this.kind;\n  this.result; */\n}\n\nfunction generateError (state, message) {\n  const mark = {\n    name: state.filename,\n    buffer: state.input.slice(0, -1), // omit trailing \\0\n    position: state.position,\n    line: state.line,\n    column: state.position - state.lineStart\n  }\n\n  mark.snippet = makeSnippet(mark)\n\n  return new YAMLException(message, mark)\n}\n\nfunction throwError (state, message) {\n  throw generateError(state, message)\n}\n\nfunction throwWarning (state, message) {\n  if (state.onWarning) {\n    state.onWarning.call(null, generateError(state, message))\n  }\n}\n\nfunction storeAnchor (state, name, value) {\n  const transactions = state.anchorMapTransactions\n\n  if (transactions.length !== 0) {\n    const transaction = transactions[transactions.length - 1]\n\n    if (!_hasOwnProperty.call(transaction, name)) {\n      transaction[name] = {\n        existed: _hasOwnProperty.call(state.anchorMap, name),\n        value: state.anchorMap[name]\n      }\n    }\n  }\n\n  state.anchorMap[name] = value\n}\n\nfunction beginAnchorTransaction (state) {\n  state.anchorMapTransactions.push(Object.create(null))\n}\n\nfunction commitAnchorTransaction (state) {\n  const transaction = state.anchorMapTransactions.pop()\n  const transactions = state.anchorMapTransactions\n\n  if (transactions.length === 0) return\n\n  const parent = transactions[transactions.length - 1]\n  const names = Object.keys(transaction)\n\n  for (let index = 0, length = names.length; index < length; index += 1) {\n    const name = names[index]\n\n    if (!_hasOwnProperty.call(parent, name)) {\n      parent[name] = transaction[name]\n    }\n  }\n}\n\nfunction rollbackAnchorTransaction (state) {\n  const transaction = state.anchorMapTransactions.pop()\n  const names = Object.keys(transaction)\n\n  for (let index = names.length - 1; index >= 0; index -= 1) {\n    const entry = transaction[names[index]]\n\n    if (entry.existed) {\n      state.anchorMap[names[index]] = entry.value\n    } else {\n      delete state.anchorMap[names[index]]\n    }\n  }\n}\n\nfunction snapshotState (state) {\n  return {\n    position: state.position,\n    line: state.line,\n    lineStart: state.lineStart,\n    lineIndent: state.lineIndent,\n    firstTabInLine: state.firstTabInLine,\n    tag: state.tag,\n    anchor: state.anchor,\n    kind: state.kind,\n    result: state.result\n  }\n}\n\nfunction restoreState (state, snapshot) {\n  state.position = snapshot.position\n  state.line = snapshot.line\n  state.lineStart = snapshot.lineStart\n  state.lineIndent = snapshot.lineIndent\n  state.firstTabInLine = snapshot.firstTabInLine\n  state.tag = snapshot.tag\n  state.anchor = snapshot.anchor\n  state.kind = snapshot.kind\n  state.result = snapshot.result\n}\n\nconst directiveHandlers = {\n\n  YAML: function handleYamlDirective (state, name, args) {\n    if (state.version !== null) {\n      throwError(state, 'duplication of %YAML directive')\n    }\n\n    if (args.length !== 1) {\n      throwError(state, 'YAML directive accepts exactly one argument')\n    }\n\n    const match = /^([0-9]+)\\.([0-9]+)$/.exec(args[0])\n\n    if (match === null) {\n      throwError(state, 'ill-formed argument of the YAML directive')\n    }\n\n    const major = parseInt(match[1], 10)\n    const minor = parseInt(match[2], 10)\n\n    if (major !== 1) {\n      throwError(state, 'unacceptable YAML version of the document')\n    }\n\n    state.version = args[0]\n    state.checkLineBreaks = (minor < 2)\n\n    if (minor !== 1 && minor !== 2) {\n      throwWarning(state, 'unsupported YAML version of the document')\n    }\n  },\n\n  TAG: function handleTagDirective (state, name, args) {\n    let prefix\n\n    if (args.length !== 2) {\n      throwError(state, 'TAG directive accepts exactly two arguments')\n    }\n\n    const handle = args[0]\n    prefix = args[1]\n\n    if (!PATTERN_TAG_HANDLE.test(handle)) {\n      throwError(state, 'ill-formed tag handle (first argument) of the TAG directive')\n    }\n\n    if (_hasOwnProperty.call(state.tagMap, handle)) {\n      throwError(state, 'there is a previously declared suffix for \"' + handle + '\" tag handle')\n    }\n\n    if (!PATTERN_TAG_URI.test(prefix)) {\n      throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive')\n    }\n\n    try {\n      prefix = decodeURIComponent(prefix)\n    } catch (err) {\n      throwError(state, 'tag prefix is malformed: ' + prefix)\n    }\n\n    state.tagMap[handle] = prefix\n  }\n}\n\nfunction captureSegment (state, start, end, checkJson) {\n  if (start < end) {\n    const _result = state.input.slice(start, end)\n\n    if (checkJson) {\n      for (let _position = 0, _length = _result.length; _position < _length; _position += 1) {\n        const _character = _result.charCodeAt(_position)\n        if (!(_character === 0x09 ||\n              (_character >= 0x20 && _character <= 0x10FFFF))) {\n          throwError(state, 'expected valid JSON character')\n        }\n      }\n    } else if (PATTERN_NON_PRINTABLE.test(_result)) {\n      throwError(state, 'the stream contains non-printable characters')\n    }\n\n    state.result += _result\n  }\n}\n\nfunction mergeMappings (state, destination, source, overridableKeys) {\n  if (!common.isObject(source)) {\n    throwError(state, 'cannot merge mappings; the provided source object is unacceptable')\n  }\n\n  const sourceKeys = Object.keys(source)\n\n  for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {\n    const key = sourceKeys[index]\n\n    if (state.maxTotalMergeKeys !== -1 && ++state.totalMergeKeys > state.maxTotalMergeKeys) {\n      throwError(state, 'merge keys exceeded maxTotalMergeKeys (' + state.maxTotalMergeKeys + ')')\n    }\n\n    if (!_hasOwnProperty.call(destination, key)) {\n      setProperty(destination, key, source[key])\n      overridableKeys[key] = true\n    }\n  }\n}\n\nfunction storeMappingPair (state, _result, overridableKeys, keyTag, keyNode, valueNode,\n  startLine, startLineStart, startPos) {\n  // The output is a plain object here, so keys can only be strings.\n  // We need to convert keyNode to a string, but doing so can hang the process\n  // (deeply nested arrays that explode exponentially using aliases).\n  if (Array.isArray(keyNode)) {\n    keyNode = Array.prototype.slice.call(keyNode)\n\n    for (let index = 0, quantity = keyNode.length; index < quantity; index += 1) {\n      if (Array.isArray(keyNode[index])) {\n        throwError(state, 'nested arrays are not supported inside keys')\n      }\n\n      if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {\n        keyNode[index] = '[object Object]'\n      }\n    }\n  }\n\n  // Avoid code execution in load() via toString property\n  // (still use its own toString for arrays, timestamps,\n  // and whatever user schema extensions happen to have @@toStringTag)\n  if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {\n    keyNode = '[object Object]'\n  }\n\n  keyNode = String(keyNode)\n\n  if (_result === null) {\n    _result = {}\n  }\n\n  if (keyTag === 'tag:yaml.org,2002:merge') {\n    if (Array.isArray(valueNode)) {\n      for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {\n        mergeMappings(state, _result, valueNode[index], overridableKeys)\n      }\n    } else {\n      mergeMappings(state, _result, valueNode, overridableKeys)\n    }\n  } else {\n    if (!state.json &&\n        !_hasOwnProperty.call(overridableKeys, keyNode) &&\n        _hasOwnProperty.call(_result, keyNode)) {\n      state.line = startLine || state.line\n      state.lineStart = startLineStart || state.lineStart\n      state.position = startPos || state.position\n      throwError(state, 'duplicated mapping key')\n    }\n\n    setProperty(_result, keyNode, valueNode)\n    delete overridableKeys[keyNode]\n  }\n\n  return _result\n}\n\nfunction readLineBreak (state) {\n  const ch = state.input.charCodeAt(state.position)\n\n  if (ch === 0x0A/* LF */) {\n    state.position++\n  } else if (ch === 0x0D/* CR */) {\n    state.position++\n    if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {\n      state.position++\n    }\n  } else {\n    throwError(state, 'a line break is expected')\n  }\n\n  state.line += 1\n  state.lineStart = state.position\n  state.firstTabInLine = -1\n}\n\nfunction skipSeparationSpace (state, allowComments, checkIndent) {\n  let lineBreaks = 0\n  let ch = state.input.charCodeAt(state.position)\n\n  while (ch !== 0) {\n    while (isWhiteSpace(ch)) {\n      if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) {\n        state.firstTabInLine = state.position\n      }\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    if (allowComments && ch === 0x23/* # */) {\n      do {\n        ch = state.input.charCodeAt(++state.position)\n      } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0)\n    }\n\n    if (isEol(ch)) {\n      readLineBreak(state)\n\n      ch = state.input.charCodeAt(state.position)\n      lineBreaks++\n      state.lineIndent = 0\n\n      while (ch === 0x20/* Space */) {\n        state.lineIndent++\n        ch = state.input.charCodeAt(++state.position)\n      }\n    } else {\n      break\n    }\n  }\n\n  if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {\n    throwWarning(state, 'deficient indentation')\n  }\n\n  return lineBreaks\n}\n\nfunction testDocumentSeparator (state) {\n  let _position = state.position\n  let ch = state.input.charCodeAt(_position)\n\n  // Condition state.position === state.lineStart is tested\n  // in parent on each call, for efficiency. No needs to test here again.\n  if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&\n      ch === state.input.charCodeAt(_position + 1) &&\n      ch === state.input.charCodeAt(_position + 2)) {\n    _position += 3\n\n    ch = state.input.charCodeAt(_position)\n\n    if (ch === 0 || isWsOrEol(ch)) {\n      return true\n    }\n  }\n\n  return false\n}\n\nfunction writeFoldedLines (state, count) {\n  if (count === 1) {\n    state.result += ' '\n  } else if (count > 1) {\n    state.result += common.repeat('\\n', count - 1)\n  }\n}\n\nfunction readPlainScalar (state, nodeIndent, withinFlowCollection) {\n  let captureStart\n  let captureEnd\n  let hasPendingContent\n  let _line\n  let _lineStart\n  let _lineIndent\n  const _kind = state.kind\n  const _result = state.result\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (isWsOrEol(ch) ||\n      isFlowIndicator(ch) ||\n      ch === 0x23/* # */ ||\n      ch === 0x26/* & */ ||\n      ch === 0x2A/* * */ ||\n      ch === 0x21/* ! */ ||\n      ch === 0x7C/* | */ ||\n      ch === 0x3E/* > */ ||\n      ch === 0x27/* ' */ ||\n      ch === 0x22/* \" */ ||\n      ch === 0x25/* % */ ||\n      ch === 0x40/* @ */ ||\n      ch === 0x60/* ` */) {\n    return false\n  }\n\n  if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {\n    const following = state.input.charCodeAt(state.position + 1)\n\n    if (isWsOrEol(following) ||\n        (withinFlowCollection && isFlowIndicator(following))) {\n      return false\n    }\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n  captureStart = captureEnd = state.position\n  hasPendingContent = false\n\n  while (ch !== 0) {\n    if (ch === 0x3A/* : */) {\n      const following = state.input.charCodeAt(state.position + 1)\n\n      if (isWsOrEol(following) ||\n          (withinFlowCollection && isFlowIndicator(following))) {\n        break\n      }\n    } else if (ch === 0x23/* # */) {\n      const preceding = state.input.charCodeAt(state.position - 1)\n\n      if (isWsOrEol(preceding)) {\n        break\n      }\n    } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||\n               (withinFlowCollection && isFlowIndicator(ch))) {\n      break\n    } else if (isEol(ch)) {\n      _line = state.line\n      _lineStart = state.lineStart\n      _lineIndent = state.lineIndent\n      skipSeparationSpace(state, false, -1)\n\n      if (state.lineIndent >= nodeIndent) {\n        hasPendingContent = true\n        ch = state.input.charCodeAt(state.position)\n        continue\n      } else {\n        state.position = captureEnd\n        state.line = _line\n        state.lineStart = _lineStart\n        state.lineIndent = _lineIndent\n        break\n      }\n    }\n\n    if (hasPendingContent) {\n      captureSegment(state, captureStart, captureEnd, false)\n      writeFoldedLines(state, state.line - _line)\n      captureStart = captureEnd = state.position\n      hasPendingContent = false\n    }\n\n    if (!isWhiteSpace(ch)) {\n      captureEnd = state.position + 1\n    }\n\n    ch = state.input.charCodeAt(++state.position)\n  }\n\n  captureSegment(state, captureStart, captureEnd, false)\n\n  if (state.result) {\n    return true\n  }\n\n  state.kind = _kind\n  state.result = _result\n  return false\n}\n\nfunction readSingleQuotedScalar (state, nodeIndent) {\n  let captureStart\n  let captureEnd\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x27/* ' */) {\n    return false\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n  state.position++\n  captureStart = captureEnd = state.position\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    if (ch === 0x27/* ' */) {\n      captureSegment(state, captureStart, state.position, true)\n      ch = state.input.charCodeAt(++state.position)\n\n      if (ch === 0x27/* ' */) {\n        captureStart = state.position\n        state.position++\n        captureEnd = state.position\n      } else {\n        return true\n      }\n    } else if (isEol(ch)) {\n      captureSegment(state, captureStart, captureEnd, true)\n      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))\n      captureStart = captureEnd = state.position\n    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n      throwError(state, 'unexpected end of the document within a single quoted scalar')\n    } else {\n      state.position++\n      if (!isWhiteSpace(ch)) {\n        captureEnd = state.position\n      }\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a single quoted scalar')\n}\n\nfunction readDoubleQuotedScalar (state, nodeIndent) {\n  let captureStart\n  let captureEnd\n  let tmp\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x22/* \" */) {\n    return false\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n  state.position++\n  captureStart = captureEnd = state.position\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    if (ch === 0x22/* \" */) {\n      captureSegment(state, captureStart, state.position, true)\n      state.position++\n      return true\n    } else if (ch === 0x5C/* \\ */) {\n      captureSegment(state, captureStart, state.position, true)\n      ch = state.input.charCodeAt(++state.position)\n\n      if (isEol(ch)) {\n        skipSeparationSpace(state, false, nodeIndent)\n\n        // TODO: rework to inline fn with no type cast?\n      } else if (ch < 256 && simpleEscapeCheck[ch]) {\n        state.result += simpleEscapeMap[ch]\n        state.position++\n      } else if ((tmp = escapedHexLen(ch)) > 0) {\n        let hexLength = tmp\n        let hexResult = 0\n\n        for (; hexLength > 0; hexLength--) {\n          ch = state.input.charCodeAt(++state.position)\n\n          if ((tmp = fromHexCode(ch)) >= 0) {\n            hexResult = (hexResult << 4) + tmp\n          } else {\n            throwError(state, 'expected hexadecimal character')\n          }\n        }\n\n        state.result += charFromCodepoint(hexResult)\n\n        state.position++\n      } else {\n        throwError(state, 'unknown escape sequence')\n      }\n\n      captureStart = captureEnd = state.position\n    } else if (isEol(ch)) {\n      captureSegment(state, captureStart, captureEnd, true)\n      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent))\n      captureStart = captureEnd = state.position\n    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n      throwError(state, 'unexpected end of the document within a double quoted scalar')\n    } else {\n      state.position++\n      if (!isWhiteSpace(ch)) {\n        captureEnd = state.position\n      }\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a double quoted scalar')\n}\n\nfunction readFlowCollection (state, nodeIndent) {\n  let readNext = true\n  let _line\n  let _lineStart\n  let _pos\n  const _tag = state.tag\n  let _result\n  const _anchor = state.anchor\n  let terminator\n  let isPair\n  let isExplicitPair\n  let isMapping\n  const overridableKeys = Object.create(null)\n  let keyNode\n  let keyTag\n  let valueNode\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch === 0x5B/* [ */) {\n    terminator = 0x5D/* ] */\n    isMapping = false\n    _result = []\n  } else if (ch === 0x7B/* { */) {\n    terminator = 0x7D/* } */\n    isMapping = true\n    _result = {}\n  } else {\n    return false\n  }\n\n  if (state.anchor !== null) {\n    storeAnchor(state, state.anchor, _result)\n  }\n\n  ch = state.input.charCodeAt(++state.position)\n\n  while (ch !== 0) {\n    skipSeparationSpace(state, true, nodeIndent)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if (ch === terminator) {\n      state.position++\n      state.tag = _tag\n      state.anchor = _anchor\n      state.kind = isMapping ? 'mapping' : 'sequence'\n      state.result = _result\n      return true\n    } else if (!readNext) {\n      throwError(state, 'missed comma between flow collection entries')\n    } else if (ch === 0x2C/* , */) {\n      // \"flow collection entries can never be completely empty\", as per YAML 1.2, section 7.4\n      throwError(state, \"expected the node content, but found ','\")\n    }\n\n    keyTag = keyNode = valueNode = null\n    isPair = isExplicitPair = false\n\n    if (ch === 0x3F/* ? */) {\n      const following = state.input.charCodeAt(state.position + 1)\n\n      if (isWsOrEol(following)) {\n        isPair = isExplicitPair = true\n        state.position++\n        skipSeparationSpace(state, true, nodeIndent)\n      }\n    }\n\n    _line = state.line // Save the current line.\n    _lineStart = state.lineStart\n    _pos = state.position\n    composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)\n    keyTag = state.tag\n    keyNode = state.result\n    skipSeparationSpace(state, true, nodeIndent)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {\n      isPair = true\n      ch = state.input.charCodeAt(++state.position)\n      skipSeparationSpace(state, true, nodeIndent)\n      composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true)\n      valueNode = state.result\n    }\n\n    if (isMapping) {\n      storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos)\n    } else if (isPair) {\n      _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos))\n    } else {\n      _result.push(keyNode)\n    }\n\n    skipSeparationSpace(state, true, nodeIndent)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if (ch === 0x2C/* , */) {\n      readNext = true\n      ch = state.input.charCodeAt(++state.position)\n    } else {\n      readNext = false\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a flow collection')\n}\n\nfunction readBlockScalar (state, nodeIndent) {\n  let folding\n  let chomping = CHOMPING_CLIP\n  let didReadContent = false\n  let detectedIndent = false\n  let textIndent = nodeIndent\n  let emptyLines = 0\n  let atMoreIndented = false\n  let tmp\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch === 0x7C/* | */) {\n    folding = false\n  } else if (ch === 0x3E/* > */) {\n    folding = true\n  } else {\n    return false\n  }\n\n  state.kind = 'scalar'\n  state.result = ''\n\n  while (ch !== 0) {\n    ch = state.input.charCodeAt(++state.position)\n\n    if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {\n      if (CHOMPING_CLIP === chomping) {\n        chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP\n      } else {\n        throwError(state, 'repeat of a chomping mode identifier')\n      }\n    } else if ((tmp = fromDecimalCode(ch)) >= 0) {\n      if (tmp === 0) {\n        throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one')\n      } else if (!detectedIndent) {\n        textIndent = nodeIndent + tmp - 1\n        detectedIndent = true\n      } else {\n        throwError(state, 'repeat of an indentation width identifier')\n      }\n    } else {\n      break\n    }\n  }\n\n  if (isWhiteSpace(ch)) {\n    do { ch = state.input.charCodeAt(++state.position) }\n    while (isWhiteSpace(ch))\n\n    if (ch === 0x23/* # */) {\n      do { ch = state.input.charCodeAt(++state.position) }\n      while (!isEol(ch) && (ch !== 0))\n    }\n  }\n\n  while (ch !== 0) {\n    readLineBreak(state)\n    state.lineIndent = 0\n\n    ch = state.input.charCodeAt(state.position)\n\n    // eslint-disable-next-line no-unmodified-loop-condition\n    while ((!detectedIndent || state.lineIndent < textIndent) &&\n           (ch === 0x20/* Space */)) {\n      state.lineIndent++\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    if (!detectedIndent && state.lineIndent > textIndent) {\n      textIndent = state.lineIndent\n    }\n\n    if (isEol(ch)) {\n      emptyLines++\n      continue\n    }\n\n    if (!detectedIndent && textIndent === 0) {\n      throwError(state, 'missing indentation for block scalar')\n    }\n\n    // End of the scalar.\n    if (state.lineIndent < textIndent) {\n      // Perform the chomping.\n      if (chomping === CHOMPING_KEEP) {\n        state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n      } else if (chomping === CHOMPING_CLIP) {\n        if (didReadContent) { // i.e. only if the scalar is not empty.\n          state.result += '\\n'\n        }\n      }\n\n      // Break this `while` cycle and go to the funciton's epilogue.\n      break\n    }\n\n    // Folded style: use fancy rules to handle line breaks.\n    if (folding) {\n      // Lines starting with white space characters (more-indented lines) are not folded.\n      if (isWhiteSpace(ch)) {\n        atMoreIndented = true\n        // except for the first content line (cf. Example 8.1)\n        state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n\n      // End of more-indented block.\n      } else if (atMoreIndented) {\n        atMoreIndented = false\n        state.result += common.repeat('\\n', emptyLines + 1)\n\n      // Just one line break - perceive as the same line.\n      } else if (emptyLines === 0) {\n        if (didReadContent) { // i.e. only if we have already read some scalar content.\n          state.result += ' '\n        }\n\n      // Several line breaks - perceive as different lines.\n      } else {\n        state.result += common.repeat('\\n', emptyLines)\n      }\n\n    // Literal style: just add exact number of line breaks between content lines.\n    } else {\n      // Keep all line breaks except the header line break.\n      state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines)\n    }\n\n    didReadContent = true\n    detectedIndent = true\n    emptyLines = 0\n    const captureStart = state.position\n\n    while (!isEol(ch) && (ch !== 0)) {\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    captureSegment(state, captureStart, state.position, false)\n  }\n\n  return true\n}\n\nfunction readBlockSequence (state, nodeIndent) {\n  const _tag = state.tag\n  const _anchor = state.anchor\n  const _result = []\n  let detected = false\n\n  // there is a leading tab before this token, so it can't be a block sequence/mapping;\n  // it can still be flow sequence/mapping or a scalar\n  if (state.firstTabInLine !== -1) return false\n\n  if (state.anchor !== null) {\n    storeAnchor(state, state.anchor, _result)\n  }\n\n  let ch = state.input.charCodeAt(state.position)\n\n  while (ch !== 0) {\n    if (state.firstTabInLine !== -1) {\n      state.position = state.firstTabInLine\n      throwError(state, 'tab characters must not be used in indentation')\n    }\n\n    if (ch !== 0x2D/* - */) {\n      break\n    }\n\n    const following = state.input.charCodeAt(state.position + 1)\n\n    if (!isWsOrEol(following)) {\n      break\n    }\n\n    detected = true\n    state.position++\n\n    if (skipSeparationSpace(state, true, -1)) {\n      if (state.lineIndent <= nodeIndent) {\n        _result.push(null)\n        ch = state.input.charCodeAt(state.position)\n        continue\n      }\n    }\n\n    const _line = state.line\n    composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true)\n    _result.push(state.result)\n    skipSeparationSpace(state, true, -1)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n      throwError(state, 'bad indentation of a sequence entry')\n    } else if (state.lineIndent < nodeIndent) {\n      break\n    }\n  }\n\n  if (detected) {\n    state.tag = _tag\n    state.anchor = _anchor\n    state.kind = 'sequence'\n    state.result = _result\n    return true\n  }\n  return false\n}\n\nfunction readBlockMapping (state, nodeIndent, flowIndent) {\n  let allowCompact\n  let _keyLine\n  let _keyLineStart\n  let _keyPos\n  const _tag = state.tag\n  const _anchor = state.anchor\n  const _result = {}\n  const overridableKeys = Object.create(null)\n  let keyTag = null\n  let keyNode = null\n  let valueNode = null\n  let atExplicitKey = false\n  let detected = false\n\n  // there is a leading tab before this token, so it can't be a block sequence/mapping;\n  // it can still be flow sequence/mapping or a scalar\n  if (state.firstTabInLine !== -1) return false\n\n  if (state.anchor !== null) {\n    storeAnchor(state, state.anchor, _result)\n  }\n\n  let ch = state.input.charCodeAt(state.position)\n\n  while (ch !== 0) {\n    if (!atExplicitKey && state.firstTabInLine !== -1) {\n      state.position = state.firstTabInLine\n      throwError(state, 'tab characters must not be used in indentation')\n    }\n\n    const following = state.input.charCodeAt(state.position + 1)\n    const _line = state.line // Save the current line.\n\n    //\n    // Explicit notation case. There are two separate blocks:\n    // first for the key (denoted by \"?\") and second for the value (denoted by \":\")\n    //\n    if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && isWsOrEol(following)) {\n      if (ch === 0x3F/* ? */) {\n        if (atExplicitKey) {\n          storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n          keyTag = keyNode = valueNode = null\n        }\n\n        detected = true\n        atExplicitKey = true\n        allowCompact = true\n      } else if (atExplicitKey) {\n        // i.e. 0x3A/* : */ === character after the explicit key.\n        atExplicitKey = false\n        allowCompact = true\n      } else {\n        throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line')\n      }\n\n      state.position += 1\n      ch = following\n\n    //\n    // Implicit notation case. Flow-style node as the key first, then \":\", and the value.\n    //\n    } else {\n      _keyLine = state.line\n      _keyLineStart = state.lineStart\n      _keyPos = state.position\n\n      if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {\n        // Neither implicit nor explicit notation.\n        // Reading is done. Go to the epilogue.\n        break\n      }\n\n      if (state.line === _line) {\n        ch = state.input.charCodeAt(state.position)\n\n        while (isWhiteSpace(ch)) {\n          ch = state.input.charCodeAt(++state.position)\n        }\n\n        if (ch === 0x3A/* : */) {\n          ch = state.input.charCodeAt(++state.position)\n\n          if (!isWsOrEol(ch)) {\n            throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping')\n          }\n\n          if (atExplicitKey) {\n            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n            keyTag = keyNode = valueNode = null\n          }\n\n          detected = true\n          atExplicitKey = false\n          allowCompact = false\n          keyTag = state.tag\n          keyNode = state.result\n        } else if (detected) {\n          throwError(state, 'can not read an implicit mapping pair; a colon is missed')\n        } else {\n          state.tag = _tag\n          state.anchor = _anchor\n          return true // Keep the result of `composeNode`.\n        }\n      } else if (detected) {\n        throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key')\n      } else {\n        state.tag = _tag\n        state.anchor = _anchor\n        return true // Keep the result of `composeNode`.\n      }\n    }\n\n    //\n    // Common reading code for both explicit and implicit notations.\n    //\n    if (state.line === _line || state.lineIndent > nodeIndent) {\n      if (atExplicitKey) {\n        _keyLine = state.line\n        _keyLineStart = state.lineStart\n        _keyPos = state.position\n      }\n\n      if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {\n        if (atExplicitKey) {\n          keyNode = state.result\n        } else {\n          valueNode = state.result\n        }\n      }\n\n      if (!atExplicitKey) {\n        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos)\n        keyTag = keyNode = valueNode = null\n      }\n\n      skipSeparationSpace(state, true, -1)\n      ch = state.input.charCodeAt(state.position)\n    }\n\n    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n      throwError(state, 'bad indentation of a mapping entry')\n    } else if (state.lineIndent < nodeIndent) {\n      break\n    }\n  }\n\n  //\n  // Epilogue.\n  //\n\n  // Special case: last mapping's node contains only the key in explicit notation.\n  if (atExplicitKey) {\n    storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos)\n  }\n\n  // Expose the resulting mapping.\n  if (detected) {\n    state.tag = _tag\n    state.anchor = _anchor\n    state.kind = 'mapping'\n    state.result = _result\n  }\n\n  return detected\n}\n\nfunction readTagProperty (state) {\n  let isVerbatim = false\n  let isNamed = false\n  let tagHandle\n  let tagName\n\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x21/* ! */) return false\n\n  if (state.tag !== null) {\n    throwError(state, 'duplication of a tag property')\n  }\n\n  ch = state.input.charCodeAt(++state.position)\n\n  if (ch === 0x3C/* < */) {\n    isVerbatim = true\n    ch = state.input.charCodeAt(++state.position)\n  } else if (ch === 0x21/* ! */) {\n    isNamed = true\n    tagHandle = '!!'\n    ch = state.input.charCodeAt(++state.position)\n  } else {\n    tagHandle = '!'\n  }\n\n  let _position = state.position\n\n  if (isVerbatim) {\n    do { ch = state.input.charCodeAt(++state.position) }\n    while (ch !== 0 && ch !== 0x3E/* > */)\n\n    if (state.position < state.length) {\n      tagName = state.input.slice(_position, state.position)\n      ch = state.input.charCodeAt(++state.position)\n    } else {\n      throwError(state, 'unexpected end of the stream within a verbatim tag')\n    }\n  } else {\n    while (ch !== 0 && !isWsOrEol(ch)) {\n      if (ch === 0x21/* ! */) {\n        if (!isNamed) {\n          tagHandle = state.input.slice(_position - 1, state.position + 1)\n\n          if (!PATTERN_TAG_HANDLE.test(tagHandle)) {\n            throwError(state, 'named tag handle cannot contain such characters')\n          }\n\n          isNamed = true\n          _position = state.position + 1\n        } else {\n          throwError(state, 'tag suffix cannot contain exclamation marks')\n        }\n      }\n\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    tagName = state.input.slice(_position, state.position)\n\n    if (PATTERN_FLOW_INDICATORS.test(tagName)) {\n      throwError(state, 'tag suffix cannot contain flow indicator characters')\n    }\n  }\n\n  if (tagName && !PATTERN_TAG_URI.test(tagName)) {\n    throwError(state, 'tag name cannot contain such characters: ' + tagName)\n  }\n\n  try {\n    tagName = decodeURIComponent(tagName)\n  } catch (err) {\n    throwError(state, 'tag name is malformed: ' + tagName)\n  }\n\n  if (isVerbatim) {\n    state.tag = tagName\n  } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {\n    state.tag = state.tagMap[tagHandle] + tagName\n  } else if (tagHandle === '!') {\n    state.tag = '!' + tagName\n  } else if (tagHandle === '!!') {\n    state.tag = 'tag:yaml.org,2002:' + tagName\n  } else {\n    throwError(state, 'undeclared tag handle \"' + tagHandle + '\"')\n  }\n\n  return true\n}\n\nfunction readAnchorProperty (state) {\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x26/* & */) return false\n\n  if (state.anchor !== null) {\n    throwError(state, 'duplication of an anchor property')\n  }\n\n  ch = state.input.charCodeAt(++state.position)\n  const _position = state.position\n\n  while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {\n    ch = state.input.charCodeAt(++state.position)\n  }\n\n  if (state.position === _position) {\n    throwError(state, 'name of an anchor node must contain at least one character')\n  }\n\n  state.anchor = state.input.slice(_position, state.position)\n  return true\n}\n\nfunction readAlias (state) {\n  let ch = state.input.charCodeAt(state.position)\n\n  if (ch !== 0x2A/* * */) return false\n\n  ch = state.input.charCodeAt(++state.position)\n  const _position = state.position\n\n  while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {\n    ch = state.input.charCodeAt(++state.position)\n  }\n\n  if (state.position === _position) {\n    throwError(state, 'name of an alias node must contain at least one character')\n  }\n\n  const alias = state.input.slice(_position, state.position)\n\n  if (!_hasOwnProperty.call(state.anchorMap, alias)) {\n    throwError(state, 'unidentified alias \"' + alias + '\"')\n  }\n\n  state.result = state.anchorMap[alias]\n  skipSeparationSpace(state, true, -1)\n  return true\n}\n\nfunction tryReadBlockMappingFromProperty (state, propertyStart, nodeIndent, flowIndent) {\n  const fallbackState = snapshotState(state)\n\n  beginAnchorTransaction(state)\n  restoreState(state, propertyStart)\n\n  // Re-read the leading properties as part of the first implicit key, not as\n  // properties of the current node.\n  state.tag = null\n  state.anchor = null\n  state.kind = null\n  state.result = null\n\n  if (readBlockMapping(state, nodeIndent, flowIndent) && state.kind === 'mapping') {\n    commitAnchorTransaction(state)\n    return true\n  }\n\n  rollbackAnchorTransaction(state)\n  restoreState(state, fallbackState)\n  return false\n}\n\nfunction composeNode (state, parentIndent, nodeContext, allowToSeek, allowCompact) {\n  let allowBlockScalars\n  let allowBlockCollections\n  let indentStatus = 1 // 1: this>parent, 0: this=parent, -1: this<parent\n  let atNewLine = false\n  let hasContent = false\n  let propertyStart = null\n  let type\n  let flowIndent\n  let blockIndent\n\n  if (state.depth >= state.maxDepth) {\n    throwError(state, 'nesting exceeded maxDepth (' + state.maxDepth + ')')\n  }\n\n  state.depth += 1\n\n  if (state.listener !== null) {\n    state.listener('open', state)\n  }\n\n  state.tag = null\n  state.anchor = null\n  state.kind = null\n  state.result = null\n\n  const allowBlockStyles = allowBlockScalars = allowBlockCollections =\n    CONTEXT_BLOCK_OUT === nodeContext ||\n    CONTEXT_BLOCK_IN === nodeContext\n\n  if (allowToSeek) {\n    if (skipSeparationSpace(state, true, -1)) {\n      atNewLine = true\n\n      if (state.lineIndent > parentIndent) {\n        indentStatus = 1\n      } else if (state.lineIndent === parentIndent) {\n        indentStatus = 0\n      } else if (state.lineIndent < parentIndent) {\n        indentStatus = -1\n      }\n    }\n  }\n\n  if (indentStatus === 1) {\n    while (true) {\n      const ch = state.input.charCodeAt(state.position)\n      const propertyState = snapshotState(state)\n\n      // A duplicate property token after a line break can be the first key of\n      // a nested block mapping, e.g. `!!map\\n  !!str key: value`.\n      if (atNewLine &&\n          ((ch === 0x21/* ! */ && state.tag !== null) ||\n           (ch === 0x26/* & */ && state.anchor !== null))) {\n        break\n      }\n\n      if (!readTagProperty(state) && !readAnchorProperty(state)) {\n        break\n      }\n\n      if (propertyStart === null) {\n        propertyStart = propertyState\n      }\n\n      if (skipSeparationSpace(state, true, -1)) {\n        atNewLine = true\n        allowBlockCollections = allowBlockStyles\n\n        if (state.lineIndent > parentIndent) {\n          indentStatus = 1\n        } else if (state.lineIndent === parentIndent) {\n          indentStatus = 0\n        } else if (state.lineIndent < parentIndent) {\n          indentStatus = -1\n        }\n      } else {\n        allowBlockCollections = false\n      }\n    }\n  }\n\n  if (allowBlockCollections) {\n    allowBlockCollections = atNewLine || allowCompact\n  }\n\n  if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {\n    if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {\n      flowIndent = parentIndent\n    } else {\n      flowIndent = parentIndent + 1\n    }\n\n    blockIndent = state.position - state.lineStart\n\n    if (indentStatus === 1) {\n      if ((allowBlockCollections &&\n          (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent))) ||\n          readFlowCollection(state, flowIndent)) {\n        hasContent = true\n      } else {\n        const ch = state.input.charCodeAt(state.position)\n\n        if (propertyStart !== null && allowBlockStyles && !allowBlockCollections &&\n            ch !== 0x7C/* | */ && ch !== 0x3E/* > */ &&\n            tryReadBlockMappingFromProperty(\n              state,\n              propertyStart,\n              propertyStart.position - propertyStart.lineStart,\n              flowIndent\n            )) {\n          hasContent = true\n        } else if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||\n            readSingleQuotedScalar(state, flowIndent) ||\n            readDoubleQuotedScalar(state, flowIndent)) {\n          hasContent = true\n        } else if (readAlias(state)) {\n          hasContent = true\n\n          if (state.tag !== null || state.anchor !== null) {\n            throwError(state, 'alias node should not have any properties')\n          }\n        } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {\n          hasContent = true\n\n          if (state.tag === null) {\n            state.tag = '?'\n          }\n        }\n\n        if (state.anchor !== null) {\n          storeAnchor(state, state.anchor, state.result)\n        }\n      }\n    } else if (indentStatus === 0) {\n      // Special case: block sequences are allowed to have same indentation level as the parent.\n      // http://www.yaml.org/spec/1.2/spec.html#id2799784\n      hasContent = allowBlockCollections && readBlockSequence(state, blockIndent)\n    }\n  }\n\n  if (state.tag === null) {\n    if (state.anchor !== null) {\n      storeAnchor(state, state.anchor, state.result)\n    }\n  } else if (state.tag === '?') {\n    // Implicit resolving is not allowed for non-scalar types, and '?'\n    // non-specific tag is only automatically assigned to plain scalars.\n    //\n    // We only need to check kind conformity in case user explicitly assigns '?'\n    // tag, for example like this: \"!<?> [0]\"\n    //\n    if (state.result !== null && state.kind !== 'scalar') {\n      throwError(state, 'unacceptable node kind for !<?> tag; it should be \"scalar\", not \"' + state.kind + '\"')\n    }\n\n    for (let typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {\n      type = state.implicitTypes[typeIndex]\n\n      if (type.resolve(state.result)) { // `state.result` updated in resolver if matched\n        state.result = type.construct(state.result)\n        state.tag = type.tag\n        if (state.anchor !== null) {\n          storeAnchor(state, state.anchor, state.result)\n        }\n        break\n      }\n    }\n  } else if (state.tag !== '!') {\n    if (_hasOwnProperty.call(state.typeMap[state.kind || 'fallback'], state.tag)) {\n      type = state.typeMap[state.kind || 'fallback'][state.tag]\n    } else {\n      // looking for multi type\n      type = null\n      const typeList = state.typeMap.multi[state.kind || 'fallback']\n\n      for (let typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {\n        if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {\n          type = typeList[typeIndex]\n          break\n        }\n      }\n    }\n\n    if (!type) {\n      throwError(state, 'unknown tag !<' + state.tag + '>')\n    }\n\n    if (state.result !== null && type.kind !== state.kind) {\n      throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be \"' + type.kind + '\", not \"' + state.kind + '\"')\n    }\n\n    if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched\n      throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag')\n    } else {\n      state.result = type.construct(state.result, state.tag)\n      if (state.anchor !== null) {\n        storeAnchor(state, state.anchor, state.result)\n      }\n    }\n  }\n\n  if (state.listener !== null) {\n    state.listener('close', state)\n  }\n\n  state.depth -= 1\n  return state.tag !== null || state.anchor !== null || hasContent\n}\n\nfunction readDocument (state) {\n  const documentStart = state.position\n  let hasDirectives = false\n  let ch\n\n  state.version = null\n  state.checkLineBreaks = state.legacy\n  state.tagMap = Object.create(null)\n  state.anchorMap = Object.create(null)\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    skipSeparationSpace(state, true, -1)\n\n    ch = state.input.charCodeAt(state.position)\n\n    if (state.lineIndent > 0 || ch !== 0x25/* % */) {\n      break\n    }\n\n    hasDirectives = true\n    ch = state.input.charCodeAt(++state.position)\n    let _position = state.position\n\n    while (ch !== 0 && !isWsOrEol(ch)) {\n      ch = state.input.charCodeAt(++state.position)\n    }\n\n    const directiveName = state.input.slice(_position, state.position)\n    const directiveArgs = []\n\n    if (directiveName.length < 1) {\n      throwError(state, 'directive name must not be less than one character in length')\n    }\n\n    while (ch !== 0) {\n      while (isWhiteSpace(ch)) {\n        ch = state.input.charCodeAt(++state.position)\n      }\n\n      if (ch === 0x23/* # */) {\n        do { ch = state.input.charCodeAt(++state.position) }\n        while (ch !== 0 && !isEol(ch))\n        break\n      }\n\n      if (isEol(ch)) break\n\n      _position = state.position\n\n      while (ch !== 0 && !isWsOrEol(ch)) {\n        ch = state.input.charCodeAt(++state.position)\n      }\n\n      directiveArgs.push(state.input.slice(_position, state.position))\n    }\n\n    if (ch !== 0) readLineBreak(state)\n\n    if (_hasOwnProperty.call(directiveHandlers, directiveName)) {\n      directiveHandlers[directiveName](state, directiveName, directiveArgs)\n    } else {\n      throwWarning(state, 'unknown document directive \"' + directiveName + '\"')\n    }\n  }\n\n  skipSeparationSpace(state, true, -1)\n\n  if (state.lineIndent === 0 &&\n      state.input.charCodeAt(state.position) === 0x2D/* - */ &&\n      state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&\n      state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {\n    state.position += 3\n    skipSeparationSpace(state, true, -1)\n  } else if (hasDirectives) {\n    throwError(state, 'directives end mark is expected')\n  }\n\n  composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true)\n  skipSeparationSpace(state, true, -1)\n\n  if (state.checkLineBreaks &&\n      PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {\n    throwWarning(state, 'non-ASCII line breaks are interpreted as content')\n  }\n\n  state.documents.push(state.result)\n\n  if (state.position === state.lineStart && testDocumentSeparator(state)) {\n    if (state.input.charCodeAt(state.position) === 0x2E/* . */) {\n      state.position += 3\n      skipSeparationSpace(state, true, -1)\n    }\n    return\n  }\n\n  if (state.position < (state.length - 1)) {\n    throwError(state, 'end of the stream or a document separator is expected')\n  }\n}\n\nfunction loadDocuments (input, options) {\n  input = String(input)\n  options = options || {}\n\n  if (input.length !== 0) {\n    // Add tailing `\\n` if not exists\n    if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&\n        input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {\n      input += '\\n'\n    }\n\n    // Strip BOM\n    if (input.charCodeAt(0) === 0xFEFF) {\n      input = input.slice(1)\n    }\n  }\n\n  const state = new State(input, options)\n\n  const nullpos = input.indexOf('\\0')\n\n  if (nullpos !== -1) {\n    state.position = nullpos\n    throwError(state, 'null byte is not allowed in input')\n  }\n\n  // Use 0 as string terminator. That significantly simplifies bounds check.\n  state.input += '\\0'\n\n  while (state.input.charCodeAt(state.position) === 0x20/* Space */) {\n    state.lineIndent += 1\n    state.position += 1\n  }\n\n  while (state.position < (state.length - 1)) {\n    readDocument(state)\n  }\n\n  return state.documents\n}\n\nfunction loadAll (input, iterator, options) {\n  if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {\n    options = iterator\n    iterator = null\n  }\n\n  const documents = loadDocuments(input, options)\n\n  if (typeof iterator !== 'function') {\n    return documents\n  }\n\n  for (let index = 0, length = documents.length; index < length; index += 1) {\n    iterator(documents[index])\n  }\n}\n\nfunction load (input, options) {\n  const documents = loadDocuments(input, options)\n\n  if (documents.length === 0) {\n    return undefined\n  } else if (documents.length === 1) {\n    return documents[0]\n  }\n  throw new YAMLException('expected a single document in the stream, but found more')\n}\n\nmodule.exports.loadAll = loadAll\nmodule.exports.load = load\n","'use strict'\n\nconst common = require('./common')\nconst YAMLException = require('./exception')\nconst DEFAULT_SCHEMA = require('./schema/default')\n\nconst _toString = Object.prototype.toString\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nconst CHAR_BOM = 0xFEFF\nconst CHAR_TAB = 0x09 /* Tab */\nconst CHAR_LINE_FEED = 0x0A /* LF */\nconst CHAR_CARRIAGE_RETURN = 0x0D /* CR */\nconst CHAR_SPACE = 0x20 /* Space */\nconst CHAR_EXCLAMATION = 0x21 /* ! */\nconst CHAR_DOUBLE_QUOTE = 0x22 /* \" */\nconst CHAR_SHARP = 0x23 /* # */\nconst CHAR_PERCENT = 0x25 /* % */\nconst CHAR_AMPERSAND = 0x26 /* & */\nconst CHAR_SINGLE_QUOTE = 0x27 /* ' */\nconst CHAR_ASTERISK = 0x2A /* * */\nconst CHAR_COMMA = 0x2C /* , */\nconst CHAR_MINUS = 0x2D /* - */\nconst CHAR_COLON = 0x3A /* : */\nconst CHAR_EQUALS = 0x3D /* = */\nconst CHAR_GREATER_THAN = 0x3E /* > */\nconst CHAR_QUESTION = 0x3F /* ? */\nconst CHAR_COMMERCIAL_AT = 0x40 /* @ */\nconst CHAR_LEFT_SQUARE_BRACKET = 0x5B /* [ */\nconst CHAR_RIGHT_SQUARE_BRACKET = 0x5D /* ] */\nconst CHAR_GRAVE_ACCENT = 0x60 /* ` */\nconst CHAR_LEFT_CURLY_BRACKET = 0x7B /* { */\nconst CHAR_VERTICAL_LINE = 0x7C /* | */\nconst CHAR_RIGHT_CURLY_BRACKET = 0x7D /* } */\n\nconst ESCAPE_SEQUENCES = {}\n\nESCAPE_SEQUENCES[0x00] = '\\\\0'\nESCAPE_SEQUENCES[0x07] = '\\\\a'\nESCAPE_SEQUENCES[0x08] = '\\\\b'\nESCAPE_SEQUENCES[0x09] = '\\\\t'\nESCAPE_SEQUENCES[0x0A] = '\\\\n'\nESCAPE_SEQUENCES[0x0B] = '\\\\v'\nESCAPE_SEQUENCES[0x0C] = '\\\\f'\nESCAPE_SEQUENCES[0x0D] = '\\\\r'\nESCAPE_SEQUENCES[0x1B] = '\\\\e'\nESCAPE_SEQUENCES[0x22] = '\\\\\"'\nESCAPE_SEQUENCES[0x5C] = '\\\\\\\\'\nESCAPE_SEQUENCES[0x85] = '\\\\N'\nESCAPE_SEQUENCES[0xA0] = '\\\\_'\nESCAPE_SEQUENCES[0x2028] = '\\\\L'\nESCAPE_SEQUENCES[0x2029] = '\\\\P'\n\nconst DEPRECATED_BOOLEANS_SYNTAX = [\n  'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',\n  'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'\n]\n\nconst DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\\.[0-9_]*)?$/\n\nfunction compileStyleMap (schema, map) {\n  if (map === null) return {}\n\n  const result = {}\n  const keys = Object.keys(map)\n\n  for (let index = 0, length = keys.length; index < length; index += 1) {\n    let tag = keys[index]\n    let style = String(map[tag])\n\n    if (tag.slice(0, 2) === '!!') {\n      tag = 'tag:yaml.org,2002:' + tag.slice(2)\n    }\n    const type = schema.compiledTypeMap['fallback'][tag]\n\n    if (type && _hasOwnProperty.call(type.styleAliases, style)) {\n      style = type.styleAliases[style]\n    }\n\n    result[tag] = style\n  }\n\n  return result\n}\n\nfunction encodeHex (character) {\n  let handle\n  let length\n\n  const string = character.toString(16).toUpperCase()\n\n  if (character <= 0xFF) {\n    handle = 'x'\n    length = 2\n  } else if (character <= 0xFFFF) {\n    handle = 'u'\n    length = 4\n  } else if (character <= 0xFFFFFFFF) {\n    handle = 'U'\n    length = 8\n  } else {\n    throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF')\n  }\n\n  return '\\\\' + handle + common.repeat('0', length - string.length) + string\n}\n\nconst QUOTING_TYPE_SINGLE = 1\nconst QUOTING_TYPE_DOUBLE = 2\n\nfunction State (options) {\n  this.schema = options['schema'] || DEFAULT_SCHEMA\n  this.indent = Math.max(1, (options['indent'] || 2))\n  this.noArrayIndent = options['noArrayIndent'] || false\n  this.skipInvalid = options['skipInvalid'] || false\n  this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel'])\n  this.styleMap = compileStyleMap(this.schema, options['styles'] || null)\n  this.sortKeys = options['sortKeys'] || false\n  this.lineWidth = options['lineWidth'] || 80\n  this.noRefs = options['noRefs'] || false\n  this.noCompatMode = options['noCompatMode'] || false\n  this.condenseFlow = options['condenseFlow'] || false\n  this.quotingType = options['quotingType'] === '\"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE\n  this.forceQuotes = options['forceQuotes'] || false\n  this.replacer = typeof options['replacer'] === 'function' ? options['replacer'] : null\n\n  this.implicitTypes = this.schema.compiledImplicit\n  this.explicitTypes = this.schema.compiledExplicit\n\n  this.tag = null\n  this.result = ''\n\n  this.duplicates = []\n  this.usedDuplicates = null\n}\n\n// Indents every line in a string. Empty lines (\\n only) are not indented.\nfunction indentString (string, spaces) {\n  const ind = common.repeat(' ', spaces)\n  let position = 0\n  let result = ''\n  const length = string.length\n\n  while (position < length) {\n    let line\n    const next = string.indexOf('\\n', position)\n    if (next === -1) {\n      line = string.slice(position)\n      position = length\n    } else {\n      line = string.slice(position, next + 1)\n      position = next + 1\n    }\n\n    if (line.length && line !== '\\n') result += ind\n\n    result += line\n  }\n\n  return result\n}\n\nfunction generateNextLine (state, level) {\n  return '\\n' + common.repeat(' ', state.indent * level)\n}\n\nfunction testImplicitResolving (state, str) {\n  for (let index = 0, length = state.implicitTypes.length; index < length; index += 1) {\n    const type = state.implicitTypes[index]\n\n    if (type.resolve(str)) {\n      return true\n    }\n  }\n\n  return false\n}\n\n// [33] s-white ::= s-space | s-tab\nfunction isWhitespace (c) {\n  return c === CHAR_SPACE || c === CHAR_TAB\n}\n\n// Returns true if the character can be printed without escaping.\n// From YAML 1.2: \"any allowed characters known to be non-printable\n// should also be escaped. [However,] This isn’t mandatory\"\n// Derived from nb-char - \\t - #x85 - #xA0 - #x2028 - #x2029.\nfunction isPrintable (c) {\n  return (c >= 0x00020 && c <= 0x00007E) ||\n    ((c >= 0x000A1 && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029) ||\n    ((c >= 0x0E000 && c <= 0x00FFFD) && c !== CHAR_BOM) ||\n    (c >= 0x10000 && c <= 0x10FFFF)\n}\n\n// [34] ns-char ::= nb-char - s-white\n// [27] nb-char ::= c-printable - b-char - c-byte-order-mark\n// [26] b-char  ::= b-line-feed | b-carriage-return\n// Including s-white (for some reason, examples doesn't match specs in this aspect)\n// ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark\nfunction isNsCharOrWhitespace (c) {\n  return isPrintable(c) &&\n    c !== CHAR_BOM &&\n    // - b-char\n    c !== CHAR_CARRIAGE_RETURN &&\n    c !== CHAR_LINE_FEED\n}\n\n// [127]  ns-plain-safe(c) ::= c = flow-out  ⇒ ns-plain-safe-out\n//                             c = flow-in   ⇒ ns-plain-safe-in\n//                             c = block-key ⇒ ns-plain-safe-out\n//                             c = flow-key  ⇒ ns-plain-safe-in\n// [128] ns-plain-safe-out ::= ns-char\n// [129]  ns-plain-safe-in ::= ns-char - c-flow-indicator\n// [130]  ns-plain-char(c) ::=  ( ns-plain-safe(c) - “:” - “#” )\n//                            | ( /* An ns-char preceding */ “#” )\n//                            | ( “:” /* Followed by an ns-plain-safe(c) */ )\nfunction isPlainSafe (c, prev, inblock) {\n  const cIsNsCharOrWhitespace = isNsCharOrWhitespace(c)\n  const cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c)\n  return (\n    (\n      // ns-plain-safe\n      inblock // c = flow-in\n        ? cIsNsCharOrWhitespace\n        : cIsNsCharOrWhitespace &&\n          // - c-flow-indicator\n          c !== CHAR_COMMA &&\n          c !== CHAR_LEFT_SQUARE_BRACKET &&\n          c !== CHAR_RIGHT_SQUARE_BRACKET &&\n          c !== CHAR_LEFT_CURLY_BRACKET &&\n          c !== CHAR_RIGHT_CURLY_BRACKET\n    ) &&\n    // ns-plain-char\n    c !== CHAR_SHARP && // false on '#'\n    !(prev === CHAR_COLON && !cIsNsChar)\n  ) || // false on ': '\n  (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP) || // change to true on '[^ ]#'\n  (prev === CHAR_COLON && cIsNsChar) // change to true on ':[^ ]'\n}\n\n// Simplified test for values allowed as the first character in plain style.\nfunction isPlainSafeFirst (c) {\n  // Uses a subset of ns-char - c-indicator\n  // where ns-char = nb-char - s-white.\n  // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part\n  return isPrintable(c) &&\n    c !== CHAR_BOM &&\n    !isWhitespace(c) && // - s-white\n    // - (c-indicator ::=\n    // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”\n    c !== CHAR_MINUS &&\n    c !== CHAR_QUESTION &&\n    c !== CHAR_COLON &&\n    c !== CHAR_COMMA &&\n    c !== CHAR_LEFT_SQUARE_BRACKET &&\n    c !== CHAR_RIGHT_SQUARE_BRACKET &&\n    c !== CHAR_LEFT_CURLY_BRACKET &&\n    c !== CHAR_RIGHT_CURLY_BRACKET &&\n    // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “\"”\n    c !== CHAR_SHARP &&\n    c !== CHAR_AMPERSAND &&\n    c !== CHAR_ASTERISK &&\n    c !== CHAR_EXCLAMATION &&\n    c !== CHAR_VERTICAL_LINE &&\n    c !== CHAR_EQUALS &&\n    c !== CHAR_GREATER_THAN &&\n    c !== CHAR_SINGLE_QUOTE &&\n    c !== CHAR_DOUBLE_QUOTE &&\n    // | “%” | “@” | “`”)\n    c !== CHAR_PERCENT &&\n    c !== CHAR_COMMERCIAL_AT &&\n    c !== CHAR_GRAVE_ACCENT\n}\n\n// Simplified test for values allowed as the last character in plain style.\nfunction isPlainSafeLast (c) {\n  // just not whitespace or colon, it will be checked to be plain character later\n  return !isWhitespace(c) && c !== CHAR_COLON\n}\n\n// Same as 'string'.codePointAt(pos), but works in older browsers.\nfunction codePointAt (string, pos) {\n  const first = string.charCodeAt(pos)\n  let second\n\n  if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) {\n    second = string.charCodeAt(pos + 1)\n    if (second >= 0xDC00 && second <= 0xDFFF) {\n      // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae\n      return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000\n    }\n  }\n  return first\n}\n\n// Determines whether block indentation indicator is required.\nfunction needIndentIndicator (string) {\n  const leadingSpaceRe = /^\\n* /\n  return leadingSpaceRe.test(string)\n}\n\nconst STYLE_PLAIN = 1\nconst STYLE_SINGLE = 2\nconst STYLE_LITERAL = 3\nconst STYLE_FOLDED = 4\nconst STYLE_DOUBLE = 5\n\n// Determines which scalar styles are possible and returns the preferred style.\n// lineWidth = -1 => no limit.\n// Pre-conditions: str.length > 0.\n// Post-conditions:\n//    STYLE_PLAIN or STYLE_SINGLE => no \\n are in the string.\n//    STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).\n//    STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).\nfunction chooseScalarStyle (string, singleLineOnly, indentPerLevel, lineWidth,\n  testAmbiguousType, quotingType, forceQuotes, inblock) {\n  let i\n  let char = 0\n  let prevChar = null\n  let hasLineBreak = false\n  let hasFoldableLine = false // only checked if shouldTrackWidth\n  const shouldTrackWidth = lineWidth !== -1\n  let previousLineBreak = -1 // count the first line correctly\n  let plain = isPlainSafeFirst(codePointAt(string, 0)) &&\n    isPlainSafeLast(codePointAt(string, string.length - 1))\n\n  if (singleLineOnly || forceQuotes) {\n    // Case: no block styles.\n    // Check for disallowed characters to rule out plain and single.\n    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n      char = codePointAt(string, i)\n      if (!isPrintable(char)) {\n        return STYLE_DOUBLE\n      }\n      plain = plain && isPlainSafe(char, prevChar, inblock)\n      prevChar = char\n    }\n  } else {\n    // Case: block styles permitted.\n    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n      char = codePointAt(string, i)\n      if (char === CHAR_LINE_FEED) {\n        hasLineBreak = true\n        // Check if any line can be folded.\n        if (shouldTrackWidth) {\n          hasFoldableLine = hasFoldableLine ||\n            // Foldable line = too long, and not more-indented.\n            (i - previousLineBreak - 1 > lineWidth &&\n             string[previousLineBreak + 1] !== ' ')\n          previousLineBreak = i\n        }\n      } else if (!isPrintable(char)) {\n        return STYLE_DOUBLE\n      }\n      plain = plain && isPlainSafe(char, prevChar, inblock)\n      prevChar = char\n    }\n    // in case the end is missing a \\n\n    hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&\n      (i - previousLineBreak - 1 > lineWidth &&\n       string[previousLineBreak + 1] !== ' '))\n  }\n  // Although every style can represent \\n without escaping, prefer block styles\n  // for multiline, since they're more readable and they don't add empty lines.\n  // Also prefer folding a super-long line.\n  if (!hasLineBreak && !hasFoldableLine) {\n    // Strings interpretable as another type have to be quoted;\n    // e.g. the string 'true' vs. the boolean true.\n    if (plain && !forceQuotes && !testAmbiguousType(string)) {\n      return STYLE_PLAIN\n    }\n    return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE\n  }\n  // Edge case: block indentation indicator can only have one digit.\n  if (indentPerLevel > 9 && needIndentIndicator(string)) {\n    return STYLE_DOUBLE\n  }\n  // At this point we know block styles are valid.\n  // Prefer literal style unless we want to fold.\n  if (!forceQuotes) {\n    return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL\n  }\n  return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE\n}\n\n// Note: line breaking/folding is implemented for only the folded style.\n// NB. We drop the last trailing newline (if any) of a returned block scalar\n//  since the dumper adds its own newline. This always works:\n//    • No ending newline => unaffected; already using strip \"-\" chomping.\n//    • Ending newline    => removed then restored.\n//  Importantly, this keeps the \"+\" chomp indicator from gaining an extra line.\nfunction writeScalar (state, string, level, iskey, inblock) {\n  state.dump = (function () {\n    if (string.length === 0) {\n      return state.quotingType === QUOTING_TYPE_DOUBLE ? '\"\"' : \"''\"\n    }\n    if (!state.noCompatMode) {\n      if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {\n        return state.quotingType === QUOTING_TYPE_DOUBLE ? ('\"' + string + '\"') : (\"'\" + string + \"'\")\n      }\n    }\n\n    const indent = state.indent * Math.max(1, level) // no 0-indent scalars\n    // As indentation gets deeper, let the width decrease monotonically\n    // to the lower bound min(state.lineWidth, 40).\n    // Note that this implies\n    //  state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.\n    //  state.lineWidth > 40 + state.indent: width decreases until the lower bound.\n    // This behaves better than a constant minimum width which disallows narrower options,\n    // or an indent threshold which causes the width to suddenly increase.\n    const lineWidth = (state.lineWidth === -1)\n      ? -1\n      : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent)\n\n    // Without knowing if keys are implicit/explicit, assume implicit for safety.\n    const singleLineOnly = iskey ||\n      // No block styles in flow mode.\n      (state.flowLevel > -1 && level >= state.flowLevel)\n    function testAmbiguity (string) {\n      return testImplicitResolving(state, string)\n    }\n\n    switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth,\n      testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {\n      case STYLE_PLAIN:\n        return string\n      case STYLE_SINGLE:\n        return \"'\" + string.replace(/'/g, \"''\") + \"'\"\n      case STYLE_LITERAL:\n        return '|' + blockHeader(string, state.indent) +\n          dropEndingNewline(indentString(string, indent))\n      case STYLE_FOLDED:\n        return '>' + blockHeader(string, state.indent) +\n          dropEndingNewline(indentString(foldString(string, lineWidth), indent))\n      case STYLE_DOUBLE:\n        return '\"' + escapeString(string, lineWidth) + '\"'\n      default:\n        throw new YAMLException('impossible error: invalid scalar style')\n    }\n  }())\n}\n\n// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.\nfunction blockHeader (string, indentPerLevel) {\n  const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : ''\n\n  // note the special case: the string '\\n' counts as a \"trailing\" empty line.\n  const clip = string[string.length - 1] === '\\n'\n  const keep = clip && (string[string.length - 2] === '\\n' || string === '\\n')\n  const chomp = keep ? '+' : (clip ? '' : '-')\n\n  return indentIndicator + chomp + '\\n'\n}\n\n// (See the note for writeScalar.)\nfunction dropEndingNewline (string) {\n  return string[string.length - 1] === '\\n' ? string.slice(0, -1) : string\n}\n\n// Note: a long line without a suitable break point will exceed the width limit.\n// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.\nfunction foldString (string, width) {\n  // In folded style, $k$ consecutive newlines output as $k+1$ newlines—\n  // unless they're before or after a more-indented line, or at the very\n  // beginning or end, in which case $k$ maps to $k$.\n  // Therefore, parse each chunk as newline(s) followed by a content line.\n  const lineRe = /(\\n+)([^\\n]*)/g\n\n  // first line (possibly an empty line)\n  let result = (function () {\n    let nextLF = string.indexOf('\\n')\n    nextLF = nextLF !== -1 ? nextLF : string.length\n    lineRe.lastIndex = nextLF\n    return foldLine(string.slice(0, nextLF), width)\n  }())\n  // If we haven't reached the first content line yet, don't add an extra \\n.\n  let prevMoreIndented = string[0] === '\\n' || string[0] === ' '\n  let moreIndented\n\n  // rest of the lines\n  let match\n  while ((match = lineRe.exec(string))) {\n    const prefix = match[1]\n    const line = match[2]\n\n    moreIndented = (line[0] === ' ')\n    result += prefix +\n      ((!prevMoreIndented && !moreIndented && line !== '') ? '\\n' : '') +\n      foldLine(line, width)\n    prevMoreIndented = moreIndented\n  }\n\n  return result\n}\n\n// Greedy line breaking.\n// Picks the longest line under the limit each time,\n// otherwise settles for the shortest line over the limit.\n// NB. More-indented lines *cannot* be folded, as that would add an extra \\n.\nfunction foldLine (line, width) {\n  if (line === '' || line[0] === ' ') return line\n\n  // Since a more-indented line adds a \\n, breaks can't be followed by a space.\n  const breakRe = / [^ ]/g // note: the match index will always be <= length-2.\n  let match\n  // start is an inclusive index. end, curr, and next are exclusive.\n  let start = 0\n  let end\n  let curr = 0\n  let next = 0\n  let result = ''\n\n  // Invariants: 0 <= start <= length-1.\n  //   0 <= curr <= next <= max(0, length-2). curr - start <= width.\n  // Inside the loop:\n  //   A match implies length >= 2, so curr and next are <= length-2.\n  while ((match = breakRe.exec(line))) {\n    next = match.index\n    // maintain invariant: curr - start <= width\n    if (next - start > width) {\n      end = (curr > start) ? curr : next // derive end <= length-2\n      result += '\\n' + line.slice(start, end)\n      // skip the space that was output as \\n\n      start = end + 1                    // derive start <= length-1\n    }\n    curr = next\n  }\n\n  // By the invariants, start <= length-1, so there is something left over.\n  // It is either the whole string or a part starting from non-whitespace.\n  result += '\\n'\n  // Insert a break if the remainder is too long and there is a break available.\n  if (line.length - start > width && curr > start) {\n    result += line.slice(start, curr) + '\\n' + line.slice(curr + 1)\n  } else {\n    result += line.slice(start)\n  }\n\n  return result.slice(1) // drop extra \\n joiner\n}\n\n// Escapes a double-quoted string.\nfunction escapeString (string) {\n  let result = ''\n  let char = 0\n\n  for (let i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {\n    char = codePointAt(string, i)\n    const escapeSeq = ESCAPE_SEQUENCES[char]\n\n    if (!escapeSeq && isPrintable(char)) {\n      result += string[i]\n      if (char >= 0x10000) result += string[i + 1]\n    } else {\n      result += escapeSeq || encodeHex(char)\n    }\n  }\n\n  return result\n}\n\nfunction writeFlowSequence (state, level, object) {\n  let _result = ''\n  const _tag = state.tag\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    let value = object[index]\n\n    if (state.replacer) {\n      value = state.replacer.call(object, String(index), value)\n    }\n\n    // Write only valid elements, put null instead of invalid elements.\n    if (writeNode(state, level, value, false, false) ||\n        (typeof value === 'undefined' &&\n         writeNode(state, level, null, false, false))) {\n      if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : '')\n      _result += state.dump\n    }\n  }\n\n  state.tag = _tag\n  state.dump = '[' + _result + ']'\n}\n\nfunction writeBlockSequence (state, level, object, compact) {\n  let _result = ''\n  const _tag = state.tag\n\n  for (let index = 0, length = object.length; index < length; index += 1) {\n    let value = object[index]\n\n    if (state.replacer) {\n      value = state.replacer.call(object, String(index), value)\n    }\n\n    // Write only valid elements, put null instead of invalid elements.\n    if (writeNode(state, level + 1, value, true, true, false, true) ||\n        (typeof value === 'undefined' &&\n         writeNode(state, level + 1, null, true, true, false, true))) {\n      if (!compact || _result !== '') {\n        _result += generateNextLine(state, level)\n      }\n\n      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n        _result += '-'\n      } else {\n        _result += '- '\n      }\n\n      _result += state.dump\n    }\n  }\n\n  state.tag = _tag\n  state.dump = _result || '[]' // Empty sequence if no valid values.\n}\n\nfunction writeFlowMapping (state, level, object) {\n  let _result = ''\n  const _tag = state.tag\n  const objectKeyList = Object.keys(object)\n\n  for (let index = 0, length = objectKeyList.length; index < length; index += 1) {\n    let pairBuffer = ''\n    if (_result !== '') pairBuffer += ', '\n\n    if (state.condenseFlow) pairBuffer += '\"'\n\n    const objectKey = objectKeyList[index]\n    let objectValue = object[objectKey]\n\n    if (state.replacer) {\n      objectValue = state.replacer.call(object, objectKey, objectValue)\n    }\n\n    if (!writeNode(state, level, objectKey, false, false)) {\n      continue // Skip this pair because of invalid key;\n    }\n\n    if (state.dump.length > 1024) pairBuffer += '? '\n\n    pairBuffer += state.dump + (state.condenseFlow ? '\"' : '') + ':' + (state.condenseFlow ? '' : ' ')\n\n    if (!writeNode(state, level, objectValue, false, false)) {\n      continue // Skip this pair because of invalid value.\n    }\n\n    pairBuffer += state.dump\n\n    // Both key and value are valid.\n    _result += pairBuffer\n  }\n\n  state.tag = _tag\n  state.dump = '{' + _result + '}'\n}\n\nfunction writeBlockMapping (state, level, object, compact) {\n  let _result = ''\n  const _tag = state.tag\n  const objectKeyList = Object.keys(object)\n\n  // Allow sorting keys so that the output file is deterministic\n  if (state.sortKeys === true) {\n    // Default sorting\n    objectKeyList.sort()\n  } else if (typeof state.sortKeys === 'function') {\n    // Custom sort function\n    objectKeyList.sort(state.sortKeys)\n  } else if (state.sortKeys) {\n    // Something is wrong\n    throw new YAMLException('sortKeys must be a boolean or a function')\n  }\n\n  for (let index = 0, length = objectKeyList.length; index < length; index += 1) {\n    let pairBuffer = ''\n\n    if (!compact || _result !== '') {\n      pairBuffer += generateNextLine(state, level)\n    }\n\n    const objectKey = objectKeyList[index]\n    let objectValue = object[objectKey]\n\n    if (state.replacer) {\n      objectValue = state.replacer.call(object, objectKey, objectValue)\n    }\n\n    if (!writeNode(state, level + 1, objectKey, true, true, true)) {\n      continue // Skip this pair because of invalid key.\n    }\n\n    const explicitPair = (state.tag !== null && state.tag !== '?') ||\n                   (state.dump && state.dump.length > 1024)\n\n    if (explicitPair) {\n      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n        pairBuffer += '?'\n      } else {\n        pairBuffer += '? '\n      }\n    }\n\n    pairBuffer += state.dump\n\n    if (explicitPair) {\n      pairBuffer += generateNextLine(state, level)\n    }\n\n    if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {\n      continue // Skip this pair because of invalid value.\n    }\n\n    if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n      pairBuffer += ':'\n    } else {\n      pairBuffer += ': '\n    }\n\n    pairBuffer += state.dump\n\n    // Both key and value are valid.\n    _result += pairBuffer\n  }\n\n  state.tag = _tag\n  state.dump = _result || '{}' // Empty mapping if no valid pairs.\n}\n\nfunction detectType (state, object, explicit) {\n  const typeList = explicit ? state.explicitTypes : state.implicitTypes\n\n  for (let index = 0, length = typeList.length; index < length; index += 1) {\n    const type = typeList[index]\n\n    if ((type.instanceOf || type.predicate) &&\n        (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&\n        (!type.predicate || type.predicate(object))) {\n      if (explicit) {\n        if (type.multi && type.representName) {\n          state.tag = type.representName(object)\n        } else {\n          state.tag = type.tag\n        }\n      } else {\n        state.tag = '?'\n      }\n\n      if (type.represent) {\n        const style = state.styleMap[type.tag] || type.defaultStyle\n\n        let _result\n        if (_toString.call(type.represent) === '[object Function]') {\n          _result = type.represent(object, style)\n        } else if (_hasOwnProperty.call(type.represent, style)) {\n          _result = type.represent[style](object, style)\n        } else {\n          throw new YAMLException('!<' + type.tag + '> tag resolver accepts not \"' + style + '\" style')\n        }\n\n        state.dump = _result\n      }\n\n      return true\n    }\n  }\n\n  return false\n}\n\n// Serializes `object` and writes it to global `result`.\n// Returns true on success, or false on invalid object.\n//\nfunction writeNode (state, level, object, block, compact, iskey, isblockseq) {\n  state.tag = null\n  state.dump = object\n\n  if (!detectType(state, object, false)) {\n    detectType(state, object, true)\n  }\n\n  const type = _toString.call(state.dump)\n  const inblock = block\n\n  if (block) {\n    block = (state.flowLevel < 0 || state.flowLevel > level)\n  }\n\n  const objectOrArray = type === '[object Object]' || type === '[object Array]'\n  let duplicateIndex\n  let duplicate\n\n  if (objectOrArray) {\n    duplicateIndex = state.duplicates.indexOf(object)\n    duplicate = duplicateIndex !== -1\n  }\n\n  if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {\n    compact = false\n  }\n\n  if (duplicate && state.usedDuplicates[duplicateIndex]) {\n    state.dump = '*ref_' + duplicateIndex\n  } else {\n    if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {\n      state.usedDuplicates[duplicateIndex] = true\n    }\n    if (type === '[object Object]') {\n      if (block && (Object.keys(state.dump).length !== 0)) {\n        writeBlockMapping(state, level, state.dump, compact)\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + state.dump\n        }\n      } else {\n        writeFlowMapping(state, level, state.dump)\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump\n        }\n      }\n    } else if (type === '[object Array]') {\n      if (block && (state.dump.length !== 0)) {\n        if (state.noArrayIndent && !isblockseq && level > 0) {\n          writeBlockSequence(state, level - 1, state.dump, compact)\n        } else {\n          writeBlockSequence(state, level, state.dump, compact)\n        }\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + state.dump\n        }\n      } else {\n        writeFlowSequence(state, level, state.dump)\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump\n        }\n      }\n    } else if (type === '[object String]') {\n      if (state.tag !== '?') {\n        writeScalar(state, state.dump, level, iskey, inblock)\n      }\n    } else if (type === '[object Undefined]') {\n      return false\n    } else {\n      if (state.skipInvalid) return false\n      throw new YAMLException('unacceptable kind of an object to dump ' + type)\n    }\n\n    if (state.tag !== null && state.tag !== '?') {\n      // Need to encode all characters except those allowed by the spec:\n      //\n      // [35] ns-dec-digit    ::=  [#x30-#x39] /* 0-9 */\n      // [36] ns-hex-digit    ::=  ns-dec-digit\n      //                         | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */\n      // [37] ns-ascii-letter ::=  [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */\n      // [38] ns-word-char    ::=  ns-dec-digit | ns-ascii-letter | “-”\n      // [39] ns-uri-char     ::=  “%” ns-hex-digit ns-hex-digit | ns-word-char | “#”\n      //                         | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,”\n      //                         | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]”\n      //\n      // Also need to encode '!' because it has special meaning (end of tag prefix).\n      //\n      let tagStr = encodeURI(\n        state.tag[0] === '!' ? state.tag.slice(1) : state.tag\n      ).replace(/!/g, '%21')\n\n      if (state.tag[0] === '!') {\n        tagStr = '!' + tagStr\n      } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') {\n        tagStr = '!!' + tagStr.slice(18)\n      } else {\n        tagStr = '!<' + tagStr + '>'\n      }\n\n      state.dump = tagStr + ' ' + state.dump\n    }\n  }\n\n  return true\n}\n\nfunction getDuplicateReferences (object, state) {\n  const objects = []\n  const duplicatesIndexes = []\n\n  inspectNode(object, objects, duplicatesIndexes)\n\n  const length = duplicatesIndexes.length\n  for (let index = 0; index < length; index += 1) {\n    state.duplicates.push(objects[duplicatesIndexes[index]])\n  }\n  state.usedDuplicates = new Array(length)\n}\n\nfunction inspectNode (object, objects, duplicatesIndexes) {\n  if (object !== null && typeof object === 'object') {\n    const index = objects.indexOf(object)\n    if (index !== -1) {\n      if (duplicatesIndexes.indexOf(index) === -1) {\n        duplicatesIndexes.push(index)\n      }\n    } else {\n      objects.push(object)\n\n      if (Array.isArray(object)) {\n        for (let i = 0, length = object.length; i < length; i += 1) {\n          inspectNode(object[i], objects, duplicatesIndexes)\n        }\n      } else {\n        const objectKeyList = Object.keys(object)\n\n        for (let i = 0, length = objectKeyList.length; i < length; i += 1) {\n          inspectNode(object[objectKeyList[i]], objects, duplicatesIndexes)\n        }\n      }\n    }\n  }\n}\n\nfunction dump (input, options) {\n  options = options || {}\n\n  const state = new State(options)\n\n  if (!state.noRefs) getDuplicateReferences(input, state)\n\n  let value = input\n\n  if (state.replacer) {\n    value = state.replacer.call({ '': value }, '', value)\n  }\n\n  if (writeNode(state, 0, value, true, true)) return state.dump + '\\n'\n\n  return ''\n}\n\nmodule.exports.dump = dump\n","'use strict'\n\nconst loader = require('./lib/loader')\nconst dumper = require('./lib/dumper')\n\nfunction renamed (from, to) {\n  return function () {\n    throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' +\n      'Use yaml.' + to + ' instead, which is now safe by default.')\n  }\n}\n\nmodule.exports.Type = require('./lib/type')\nmodule.exports.Schema = require('./lib/schema')\nmodule.exports.FAILSAFE_SCHEMA = require('./lib/schema/failsafe')\nmodule.exports.JSON_SCHEMA = require('./lib/schema/json')\nmodule.exports.CORE_SCHEMA = require('./lib/schema/core')\nmodule.exports.DEFAULT_SCHEMA = require('./lib/schema/default')\nmodule.exports.load = loader.load\nmodule.exports.loadAll = loader.loadAll\nmodule.exports.dump = dumper.dump\nmodule.exports.YAMLException = require('./lib/exception')\n\n// Re-export all types in case user wants to create custom schema\nmodule.exports.types = {\n  binary: require('./lib/type/binary'),\n  float: require('./lib/type/float'),\n  map: require('./lib/type/map'),\n  null: require('./lib/type/null'),\n  pairs: require('./lib/type/pairs'),\n  set: require('./lib/type/set'),\n  timestamp: require('./lib/type/timestamp'),\n  bool: require('./lib/type/bool'),\n  int: require('./lib/type/int'),\n  merge: require('./lib/type/merge'),\n  omap: require('./lib/type/omap'),\n  seq: require('./lib/type/seq'),\n  str: require('./lib/type/str')\n}\n\n// Removed functions from JS-YAML 3.0.x\nmodule.exports.safeLoad = renamed('safeLoad', 'load')\nmodule.exports.safeLoadAll = renamed('safeLoadAll', 'loadAll')\nmodule.exports.safeDump = renamed('safeDump', 'dump')\n","import yaml from '../index.js'\n\nconst {\n  Type,\n  Schema,\n  FAILSAFE_SCHEMA,\n  JSON_SCHEMA,\n  CORE_SCHEMA,\n  DEFAULT_SCHEMA,\n  load,\n  loadAll,\n  dump,\n  YAMLException,\n  types,\n  safeLoad,\n  safeLoadAll,\n  safeDump\n} = yaml\n\nexport {\n  Type,\n  Schema,\n  FAILSAFE_SCHEMA,\n  JSON_SCHEMA,\n  CORE_SCHEMA,\n  DEFAULT_SCHEMA,\n  load,\n  loadAll,\n  dump,\n  YAMLException,\n  types,\n  safeLoad,\n  safeLoadAll,\n  safeDump\n}\n\nexport default yaml\n"],"names":["exception","YAMLException","common","require$$0","line","map","Type","require$$1","schema","type","Schema","require$$2","require$$3","require$$4","require$$5","require$$6","DEFAULT_SCHEMA","loadAll","load","str","string","dump","loader","dumper","require$$7","require$$8","require$$9","require$$10","require$$11","require$$12","require$$13","require$$14","require$$15","require$$16","require$$17","require$$18","require$$19","require$$20","require$$21"],"mappings":"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"}#!/usr/bin/env node

'use strict'

const fs = require('fs')
const argparse = require('argparse')
const yaml = require('..')

/// /////////////////////////////////////////////////////////////////////////////

const cli = new argparse.ArgumentParser({
  prog: 'js-yaml',
  add_help: true
})

cli.add_argument('-v', '--version', {
  action: 'version',
  version: require('../package.json').version
})

cli.add_argument('-c', '--compact', {
  help: 'Display errors in compact mode',
  action: 'store_true'
})

// deprecated (not needed after we removed output colors)
// option suppressed, but not completely removed for compatibility
cli.add_argument('-j', '--to-json', {
  help: argparse.SUPPRESS,
  dest: 'json',
  action: 'store_true'
})

cli.add_argument('-t', '--trace', {
  help: 'Show stack trace on error',
  action: 'store_true'
})

cli.add_argument('file', {
  help: 'File to read, utf-8 encoded without BOM',
  nargs: '?',
  default: '-'
})

/// /////////////////////////////////////////////////////////////////////////////

const options = cli.parse_args()

/// /////////////////////////////////////////////////////////////////////////////

function readFile (filename, encoding, callback) {
  if (options.file === '-') {
    // read from stdin

    const chunks = []

    process.stdin.on('data', function (chunk) {
      chunks.push(chunk)
    })

    process.stdin.on('end', function () {
      return callback(null, Buffer.concat(chunks).toString(encoding))
    })
  } else {
    fs.readFile(filename, encoding, callback)
  }
}

readFile(options.file, 'utf8', function (error, input) {
  let output
  let isYaml

  if (error) {
    if (error.code === 'ENOENT') {
      console.error('File not found: ' + options.file)
      process.exit(2)
    }

    console.error(
      (options.trace && error.stack) ||
      error.message ||
      String(error))

    process.exit(1)
  }

  try {
    output = JSON.parse(input)
    isYaml = false
  } catch (err) {
    if (err instanceof SyntaxError) {
      try {
        output = []
        yaml.loadAll(input, function (doc) { output.push(doc) }, {})
        isYaml = true

        if (output.length === 0) output = null
        else if (output.length === 1) output = output[0]
      } catch (e) {
        if (options.trace && err.stack) console.error(e.stack)
        else console.error(e.toString(options.compact))

        process.exit(1)
      }
    } else {
      console.error(
        (options.trace && err.stack) ||
        err.message ||
        String(err))

      process.exit(1)
    }
  }

  if (isYaml) console.log(JSON.stringify(output, null, '  '))
  else console.log(yaml.dump(output))
})
{
  "name": "lazy-val",
  "version": "1.0.5",
  "main": "out/main.js",
  "author": "Vladimir Krivosheev",
  "license": "MIT",
  "repository": "develar/lazy-val",
  "homepage": "https://github.com/develar/lazy-val",
  "files": [
    "out"
  ],
  "devDependencies": {
    "typescript": "^4.2.4"
  },
  "typings": "./out/main.d.ts"
}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Lazy = void 0;
class Lazy {
    constructor(creator) {
        this._value = null;
        this.creator = creator;
    }
    get hasValue() {
        return this.creator == null;
    }
    get value() {
        if (this.creator == null) {
            return this._value;
        }
        const result = this.creator();
        this.value = result;
        return result;
    }
    set value(value) {
        this._value = value;
        this.creator = null;
    }
}
exports.Lazy = Lazy;
//# sourceMappingURL=main.js.map{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;AAAA,MAAa,IAAI;IAIf,YAAY,OAAyB;QAH7B,WAAM,GAAsB,IAAI,CAAA;QAItC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAA;IAC7B,CAAC;IAED,IAAI,KAAK;QACP,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE;YACxB,OAAO,IAAI,CAAC,MAAQ,CAAA;SACrB;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAA;QAC7B,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;QACnB,OAAO,MAAM,CAAA;IACf,CAAC;IAED,IAAI,KAAK,CAAC,KAAiB;QACzB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;IACrB,CAAC;CACF;AA1BD,oBA0BC","sourcesContent":["export class Lazy<T> {\n  private _value: Promise<T> | null = null\n  private creator: (() => Promise<T>) | null\n\n  constructor(creator: () => Promise<T>) {\n    this.creator = creator\n  }\n\n  get hasValue() {\n    return this.creator == null\n  }\n\n  get value(): Promise<T> {\n    if (this.creator == null) {\n      return this._value!!\n    }\n\n    const result = this.creator()\n    this.value = result\n    return result\n  }\n\n  set value(value: Promise<T>) {\n    this._value = value\n    this.creator = null\n  }\n}"]}Copyright jQuery Foundation and other contributors <https://jquery.org/>

Based on Underscore.js, copyright Jeremy Ashkenas,
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>

This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
available at https://github.com/lodash/lodash

The following license applies to all parts of this software except as
documented below:

====

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

====

Copyright and related rights for sample code are waived via CC0. Sample
code is defined as all source code displayed within the prose of the
documentation.

CC0: http://creativecommons.org/publicdomain/zero/1.0/

====

Files located in the node_modules and vendor directories are externally
maintained libraries used by this software which have their own
licenses; we recommend you read them, as their terms may differ from the
terms above.
/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0;

/** `Object#toString` result references. */
var symbolTag = '[object Symbol]';

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
    reHasRegExpChar = RegExp(reRegExpChar.source);

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/** Used for built-in method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Built-in value references. */
var Symbol = root.Symbol;

/** Used to convert symbols to primitives and strings. */
var symbolProto = Symbol ? Symbol.prototype : undefined,
    symbolToString = symbolProto ? symbolProto.toString : undefined;

/**
 * The base implementation of `_.toString` which doesn't convert nullish
 * values to empty strings.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 */
function baseToString(value) {
  // Exit early for strings to avoid a performance hit in some environments.
  if (typeof value == 'string') {
    return value;
  }
  if (isSymbol(value)) {
    return symbolToString ? symbolToString.call(value) : '';
  }
  var result = (value + '');
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

/**
 * Checks if `value` is classified as a `Symbol` primitive or object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
 * @example
 *
 * _.isSymbol(Symbol.iterator);
 * // => true
 *
 * _.isSymbol('abc');
 * // => false
 */
function isSymbol(value) {
  return typeof value == 'symbol' ||
    (isObjectLike(value) && objectToString.call(value) == symbolTag);
}

/**
 * Converts `value` to a string. An empty string is returned for `null`
 * and `undefined` values. The sign of `-0` is preserved.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 * @example
 *
 * _.toString(null);
 * // => ''
 *
 * _.toString(-0);
 * // => '-0'
 *
 * _.toString([1, 2, 3]);
 * // => '1,2,3'
 */
function toString(value) {
  return value == null ? '' : baseToString(value);
}

/**
 * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
 * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category String
 * @param {string} [string=''] The string to escape.
 * @returns {string} Returns the escaped string.
 * @example
 *
 * _.escapeRegExp('[lodash](https://lodash.com/)');
 * // => '\[lodash\]\(https://lodash\.com/\)'
 */
function escapeRegExp(string) {
  string = toString(string);
  return (string && reHasRegExpChar.test(string))
    ? string.replace(reRegExpChar, '\\$&')
    : string;
}

module.exports = escapeRegExp;
{
  "name": "lodash.escaperegexp",
  "version": "4.1.2",
  "description": "The lodash method `_.escapeRegExp` exported as a module.",
  "homepage": "https://lodash.com/",
  "icon": "https://lodash.com/icon.svg",
  "license": "MIT",
  "author": "John-David Dalton <john.david.dalton@gmail.com> (http://allyoucanleet.com/)",
  "repository": "lodash/lodash"
}Copyright JS Foundation and other contributors <https://js.foundation/>

Based on Underscore.js, copyright Jeremy Ashkenas,
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>

This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
available at https://github.com/lodash/lodash

The following license applies to all parts of this software except as
documented below:

====

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

====

Copyright and related rights for sample code are waived via CC0. Sample
code is defined as all source code displayed within the prose of the
documentation.

CC0: http://creativecommons.org/publicdomain/zero/1.0/

====

Files located in the node_modules and vendor directories are externally
maintained libraries used by this software which have their own
licenses; we recommend you read them, as their terms may differ from the
terms above.
/**
 * Lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright JS Foundation and other contributors <https://js.foundation/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1,
    COMPARE_UNORDERED_FLAG = 2;

/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    asyncTag = '[object AsyncFunction]',
    boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    nullTag = '[object Null]',
    objectTag = '[object Object]',
    promiseTag = '[object Promise]',
    proxyTag = '[object Proxy]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    symbolTag = '[object Symbol]',
    undefinedTag = '[object Undefined]',
    weakMapTag = '[object WeakMap]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;

/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
typedArrayTags[errorTag] = typedArrayTags[funcTag] =
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
typedArrayTags[setTag] = typedArrayTags[stringTag] =
typedArrayTags[weakMapTag] = false;

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/** Detect free variable `exports`. */
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Detect free variable `process` from Node.js. */
var freeProcess = moduleExports && freeGlobal.process;

/** Used to access faster Node.js helpers. */
var nodeUtil = (function() {
  try {
    return freeProcess && freeProcess.binding && freeProcess.binding('util');
  } catch (e) {}
}());

/* Node.js helper references. */
var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;

/**
 * A specialized version of `_.filter` for arrays without support for
 * iteratee shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {Array} Returns the new filtered array.
 */
function arrayFilter(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length,
      resIndex = 0,
      result = [];

  while (++index < length) {
    var value = array[index];
    if (predicate(value, index, array)) {
      result[resIndex++] = value;
    }
  }
  return result;
}

/**
 * Appends the elements of `values` to `array`.
 *
 * @private
 * @param {Array} array The array to modify.
 * @param {Array} values The values to append.
 * @returns {Array} Returns `array`.
 */
function arrayPush(array, values) {
  var index = -1,
      length = values.length,
      offset = array.length;

  while (++index < length) {
    array[offset + index] = values[index];
  }
  return array;
}

/**
 * A specialized version of `_.some` for arrays without support for iteratee
 * shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {boolean} Returns `true` if any element passes the predicate check,
 *  else `false`.
 */
function arraySome(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length;

  while (++index < length) {
    if (predicate(array[index], index, array)) {
      return true;
    }
  }
  return false;
}

/**
 * The base implementation of `_.times` without support for iteratee shorthands
 * or max array length checks.
 *
 * @private
 * @param {number} n The number of times to invoke `iteratee`.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the array of results.
 */
function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

/**
 * The base implementation of `_.unary` without support for storing metadata.
 *
 * @private
 * @param {Function} func The function to cap arguments for.
 * @returns {Function} Returns the new capped function.
 */
function baseUnary(func) {
  return function(value) {
    return func(value);
  };
}

/**
 * Checks if a `cache` value for `key` exists.
 *
 * @private
 * @param {Object} cache The cache to query.
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function cacheHas(cache, key) {
  return cache.has(key);
}

/**
 * Gets the value at `key` of `object`.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function getValue(object, key) {
  return object == null ? undefined : object[key];
}

/**
 * Converts `map` to its key-value pairs.
 *
 * @private
 * @param {Object} map The map to convert.
 * @returns {Array} Returns the key-value pairs.
 */
function mapToArray(map) {
  var index = -1,
      result = Array(map.size);

  map.forEach(function(value, key) {
    result[++index] = [key, value];
  });
  return result;
}

/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function(arg) {
    return func(transform(arg));
  };
}

/**
 * Converts `set` to an array of its values.
 *
 * @private
 * @param {Object} set The set to convert.
 * @returns {Array} Returns the values.
 */
function setToArray(set) {
  var index = -1,
      result = Array(set.size);

  set.forEach(function(value) {
    result[++index] = value;
  });
  return result;
}

/** Used for built-in method references. */
var arrayProto = Array.prototype,
    funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to detect overreaching core-js shims. */
var coreJsData = root['__core-js_shared__'];

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Used to detect methods masquerading as native. */
var maskSrcKey = (function() {
  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
  return uid ? ('Symbol(src)_1.' + uid) : '';
}());

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString = objectProto.toString;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);

/** Built-in value references. */
var Buffer = moduleExports ? root.Buffer : undefined,
    Symbol = root.Symbol,
    Uint8Array = root.Uint8Array,
    propertyIsEnumerable = objectProto.propertyIsEnumerable,
    splice = arrayProto.splice,
    symToStringTag = Symbol ? Symbol.toStringTag : undefined;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeGetSymbols = Object.getOwnPropertySymbols,
    nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
    nativeKeys = overArg(Object.keys, Object);

/* Built-in method references that are verified to be native. */
var DataView = getNative(root, 'DataView'),
    Map = getNative(root, 'Map'),
    Promise = getNative(root, 'Promise'),
    Set = getNative(root, 'Set'),
    WeakMap = getNative(root, 'WeakMap'),
    nativeCreate = getNative(Object, 'create');

/** Used to detect maps, sets, and weakmaps. */
var dataViewCtorString = toSource(DataView),
    mapCtorString = toSource(Map),
    promiseCtorString = toSource(Promise),
    setCtorString = toSource(Set),
    weakMapCtorString = toSource(WeakMap);

/** Used to convert symbols to primitives and strings. */
var symbolProto = Symbol ? Symbol.prototype : undefined,
    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;

/**
 * Creates a hash object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Hash(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the hash.
 *
 * @private
 * @name clear
 * @memberOf Hash
 */
function hashClear() {
  this.__data__ = nativeCreate ? nativeCreate(null) : {};
  this.size = 0;
}

/**
 * Removes `key` and its value from the hash.
 *
 * @private
 * @name delete
 * @memberOf Hash
 * @param {Object} hash The hash to modify.
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function hashDelete(key) {
  var result = this.has(key) && delete this.__data__[key];
  this.size -= result ? 1 : 0;
  return result;
}

/**
 * Gets the hash value for `key`.
 *
 * @private
 * @name get
 * @memberOf Hash
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function hashGet(key) {
  var data = this.__data__;
  if (nativeCreate) {
    var result = data[key];
    return result === HASH_UNDEFINED ? undefined : result;
  }
  return hasOwnProperty.call(data, key) ? data[key] : undefined;
}

/**
 * Checks if a hash value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Hash
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function hashHas(key) {
  var data = this.__data__;
  return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
}

/**
 * Sets the hash `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Hash
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the hash instance.
 */
function hashSet(key, value) {
  var data = this.__data__;
  this.size += this.has(key) ? 0 : 1;
  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
  return this;
}

// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;

/**
 * Creates an list cache object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function ListCache(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the list cache.
 *
 * @private
 * @name clear
 * @memberOf ListCache
 */
function listCacheClear() {
  this.__data__ = [];
  this.size = 0;
}

/**
 * Removes `key` and its value from the list cache.
 *
 * @private
 * @name delete
 * @memberOf ListCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function listCacheDelete(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    return false;
  }
  var lastIndex = data.length - 1;
  if (index == lastIndex) {
    data.pop();
  } else {
    splice.call(data, index, 1);
  }
  --this.size;
  return true;
}

/**
 * Gets the list cache value for `key`.
 *
 * @private
 * @name get
 * @memberOf ListCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function listCacheGet(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  return index < 0 ? undefined : data[index][1];
}

/**
 * Checks if a list cache value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf ListCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function listCacheHas(key) {
  return assocIndexOf(this.__data__, key) > -1;
}

/**
 * Sets the list cache `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf ListCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the list cache instance.
 */
function listCacheSet(key, value) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    ++this.size;
    data.push([key, value]);
  } else {
    data[index][1] = value;
  }
  return this;
}

// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;

/**
 * Creates a map cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function MapCache(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the map.
 *
 * @private
 * @name clear
 * @memberOf MapCache
 */
function mapCacheClear() {
  this.size = 0;
  this.__data__ = {
    'hash': new Hash,
    'map': new (Map || ListCache),
    'string': new Hash
  };
}

/**
 * Removes `key` and its value from the map.
 *
 * @private
 * @name delete
 * @memberOf MapCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function mapCacheDelete(key) {
  var result = getMapData(this, key)['delete'](key);
  this.size -= result ? 1 : 0;
  return result;
}

/**
 * Gets the map value for `key`.
 *
 * @private
 * @name get
 * @memberOf MapCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function mapCacheGet(key) {
  return getMapData(this, key).get(key);
}

/**
 * Checks if a map value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf MapCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function mapCacheHas(key) {
  return getMapData(this, key).has(key);
}

/**
 * Sets the map `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf MapCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the map cache instance.
 */
function mapCacheSet(key, value) {
  var data = getMapData(this, key),
      size = data.size;

  data.set(key, value);
  this.size += data.size == size ? 0 : 1;
  return this;
}

// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;

/**
 *
 * Creates an array cache object to store unique values.
 *
 * @private
 * @constructor
 * @param {Array} [values] The values to cache.
 */
function SetCache(values) {
  var index = -1,
      length = values == null ? 0 : values.length;

  this.__data__ = new MapCache;
  while (++index < length) {
    this.add(values[index]);
  }
}

/**
 * Adds `value` to the array cache.
 *
 * @private
 * @name add
 * @memberOf SetCache
 * @alias push
 * @param {*} value The value to cache.
 * @returns {Object} Returns the cache instance.
 */
function setCacheAdd(value) {
  this.__data__.set(value, HASH_UNDEFINED);
  return this;
}

/**
 * Checks if `value` is in the array cache.
 *
 * @private
 * @name has
 * @memberOf SetCache
 * @param {*} value The value to search for.
 * @returns {number} Returns `true` if `value` is found, else `false`.
 */
function setCacheHas(value) {
  return this.__data__.has(value);
}

// Add methods to `SetCache`.
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
SetCache.prototype.has = setCacheHas;

/**
 * Creates a stack cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Stack(entries) {
  var data = this.__data__ = new ListCache(entries);
  this.size = data.size;
}

/**
 * Removes all key-value entries from the stack.
 *
 * @private
 * @name clear
 * @memberOf Stack
 */
function stackClear() {
  this.__data__ = new ListCache;
  this.size = 0;
}

/**
 * Removes `key` and its value from the stack.
 *
 * @private
 * @name delete
 * @memberOf Stack
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function stackDelete(key) {
  var data = this.__data__,
      result = data['delete'](key);

  this.size = data.size;
  return result;
}

/**
 * Gets the stack value for `key`.
 *
 * @private
 * @name get
 * @memberOf Stack
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function stackGet(key) {
  return this.__data__.get(key);
}

/**
 * Checks if a stack value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Stack
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function stackHas(key) {
  return this.__data__.has(key);
}

/**
 * Sets the stack `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Stack
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the stack cache instance.
 */
function stackSet(key, value) {
  var data = this.__data__;
  if (data instanceof ListCache) {
    var pairs = data.__data__;
    if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
      pairs.push([key, value]);
      this.size = ++data.size;
      return this;
    }
    data = this.__data__ = new MapCache(pairs);
  }
  data.set(key, value);
  this.size = data.size;
  return this;
}

// Add methods to `Stack`.
Stack.prototype.clear = stackClear;
Stack.prototype['delete'] = stackDelete;
Stack.prototype.get = stackGet;
Stack.prototype.has = stackHas;
Stack.prototype.set = stackSet;

/**
 * Creates an array of the enumerable property names of the array-like `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @param {boolean} inherited Specify returning inherited property names.
 * @returns {Array} Returns the array of property names.
 */
function arrayLikeKeys(value, inherited) {
  var isArr = isArray(value),
      isArg = !isArr && isArguments(value),
      isBuff = !isArr && !isArg && isBuffer(value),
      isType = !isArr && !isArg && !isBuff && isTypedArray(value),
      skipIndexes = isArr || isArg || isBuff || isType,
      result = skipIndexes ? baseTimes(value.length, String) : [],
      length = result.length;

  for (var key in value) {
    if ((inherited || hasOwnProperty.call(value, key)) &&
        !(skipIndexes && (
           // Safari 9 has enumerable `arguments.length` in strict mode.
           key == 'length' ||
           // Node.js 0.10 has enumerable non-index properties on buffers.
           (isBuff && (key == 'offset' || key == 'parent')) ||
           // PhantomJS 2 has enumerable non-index properties on typed arrays.
           (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
           // Skip index properties.
           isIndex(key, length)
        ))) {
      result.push(key);
    }
  }
  return result;
}

/**
 * Gets the index at which the `key` is found in `array` of key-value pairs.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} key The key to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function assocIndexOf(array, key) {
  var length = array.length;
  while (length--) {
    if (eq(array[length][0], key)) {
      return length;
    }
  }
  return -1;
}

/**
 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
 * symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @param {Function} symbolsFunc The function to get the symbols of `object`.
 * @returns {Array} Returns the array of property names and symbols.
 */
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
  var result = keysFunc(object);
  return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
}

/**
 * The base implementation of `getTag` without fallbacks for buggy environments.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
function baseGetTag(value) {
  if (value == null) {
    return value === undefined ? undefinedTag : nullTag;
  }
  return (symToStringTag && symToStringTag in Object(value))
    ? getRawTag(value)
    : objectToString(value);
}

/**
 * The base implementation of `_.isArguments`.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 */
function baseIsArguments(value) {
  return isObjectLike(value) && baseGetTag(value) == argsTag;
}

/**
 * The base implementation of `_.isEqual` which supports partial comparisons
 * and tracks traversed objects.
 *
 * @private
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @param {boolean} bitmask The bitmask flags.
 *  1 - Unordered comparison
 *  2 - Partial comparison
 * @param {Function} [customizer] The function to customize comparisons.
 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 */
function baseIsEqual(value, other, bitmask, customizer, stack) {
  if (value === other) {
    return true;
  }
  if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
    return value !== value && other !== other;
  }
  return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
}

/**
 * A specialized version of `baseIsEqual` for arrays and objects which performs
 * deep comparisons and tracks traversed objects enabling objects with circular
 * references to be compared.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
  var objIsArr = isArray(object),
      othIsArr = isArray(other),
      objTag = objIsArr ? arrayTag : getTag(object),
      othTag = othIsArr ? arrayTag : getTag(other);

  objTag = objTag == argsTag ? objectTag : objTag;
  othTag = othTag == argsTag ? objectTag : othTag;

  var objIsObj = objTag == objectTag,
      othIsObj = othTag == objectTag,
      isSameTag = objTag == othTag;

  if (isSameTag && isBuffer(object)) {
    if (!isBuffer(other)) {
      return false;
    }
    objIsArr = true;
    objIsObj = false;
  }
  if (isSameTag && !objIsObj) {
    stack || (stack = new Stack);
    return (objIsArr || isTypedArray(object))
      ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
      : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
  }
  if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

    if (objIsWrapped || othIsWrapped) {
      var objUnwrapped = objIsWrapped ? object.value() : object,
          othUnwrapped = othIsWrapped ? other.value() : other;

      stack || (stack = new Stack);
      return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
    }
  }
  if (!isSameTag) {
    return false;
  }
  stack || (stack = new Stack);
  return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
}

/**
 * The base implementation of `_.isNative` without bad shim checks.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function,
 *  else `false`.
 */
function baseIsNative(value) {
  if (!isObject(value) || isMasked(value)) {
    return false;
  }
  var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
  return pattern.test(toSource(value));
}

/**
 * The base implementation of `_.isTypedArray` without Node.js optimizations.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 */
function baseIsTypedArray(value) {
  return isObjectLike(value) &&
    isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
}

/**
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeys(object) {
  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}

/**
 * A specialized version of `baseIsEqualDeep` for arrays with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Array} array The array to compare.
 * @param {Array} other The other array to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `array` and `other` objects.
 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
 */
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
      arrLength = array.length,
      othLength = other.length;

  if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
    return false;
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(array);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var index = -1,
      result = true,
      seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;

  stack.set(array, other);
  stack.set(other, array);

  // Ignore non-index properties.
  while (++index < arrLength) {
    var arrValue = array[index],
        othValue = other[index];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, arrValue, index, other, array, stack)
        : customizer(arrValue, othValue, index, array, other, stack);
    }
    if (compared !== undefined) {
      if (compared) {
        continue;
      }
      result = false;
      break;
    }
    // Recursively compare arrays (susceptible to call stack limits).
    if (seen) {
      if (!arraySome(other, function(othValue, othIndex) {
            if (!cacheHas(seen, othIndex) &&
                (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
              return seen.push(othIndex);
            }
          })) {
        result = false;
        break;
      }
    } else if (!(
          arrValue === othValue ||
            equalFunc(arrValue, othValue, bitmask, customizer, stack)
        )) {
      result = false;
      break;
    }
  }
  stack['delete'](array);
  stack['delete'](other);
  return result;
}

/**
 * A specialized version of `baseIsEqualDeep` for comparing objects of
 * the same `toStringTag`.
 *
 * **Note:** This function only supports comparing values with tags of
 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {string} tag The `toStringTag` of the objects to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
  switch (tag) {
    case dataViewTag:
      if ((object.byteLength != other.byteLength) ||
          (object.byteOffset != other.byteOffset)) {
        return false;
      }
      object = object.buffer;
      other = other.buffer;

    case arrayBufferTag:
      if ((object.byteLength != other.byteLength) ||
          !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
        return false;
      }
      return true;

    case boolTag:
    case dateTag:
    case numberTag:
      // Coerce booleans to `1` or `0` and dates to milliseconds.
      // Invalid dates are coerced to `NaN`.
      return eq(+object, +other);

    case errorTag:
      return object.name == other.name && object.message == other.message;

    case regexpTag:
    case stringTag:
      // Coerce regexes to strings and treat strings, primitives and objects,
      // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
      // for more details.
      return object == (other + '');

    case mapTag:
      var convert = mapToArray;

    case setTag:
      var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
      convert || (convert = setToArray);

      if (object.size != other.size && !isPartial) {
        return false;
      }
      // Assume cyclic values are equal.
      var stacked = stack.get(object);
      if (stacked) {
        return stacked == other;
      }
      bitmask |= COMPARE_UNORDERED_FLAG;

      // Recursively compare objects (susceptible to call stack limits).
      stack.set(object, other);
      var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
      stack['delete'](object);
      return result;

    case symbolTag:
      if (symbolValueOf) {
        return symbolValueOf.call(object) == symbolValueOf.call(other);
      }
  }
  return false;
}

/**
 * A specialized version of `baseIsEqualDeep` for objects with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
      objProps = getAllKeys(object),
      objLength = objProps.length,
      othProps = getAllKeys(other),
      othLength = othProps.length;

  if (objLength != othLength && !isPartial) {
    return false;
  }
  var index = objLength;
  while (index--) {
    var key = objProps[index];
    if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
      return false;
    }
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(object);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var result = true;
  stack.set(object, other);
  stack.set(other, object);

  var skipCtor = isPartial;
  while (++index < objLength) {
    key = objProps[index];
    var objValue = object[key],
        othValue = other[key];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, objValue, key, other, object, stack)
        : customizer(objValue, othValue, key, object, other, stack);
    }
    // Recursively compare objects (susceptible to call stack limits).
    if (!(compared === undefined
          ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
          : compared
        )) {
      result = false;
      break;
    }
    skipCtor || (skipCtor = key == 'constructor');
  }
  if (result && !skipCtor) {
    var objCtor = object.constructor,
        othCtor = other.constructor;

    // Non `Object` object instances with different constructors are not equal.
    if (objCtor != othCtor &&
        ('constructor' in object && 'constructor' in other) &&
        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
          typeof othCtor == 'function' && othCtor instanceof othCtor)) {
      result = false;
    }
  }
  stack['delete'](object);
  stack['delete'](other);
  return result;
}

/**
 * Creates an array of own enumerable property names and symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names and symbols.
 */
function getAllKeys(object) {
  return baseGetAllKeys(object, keys, getSymbols);
}

/**
 * Gets the data for `map`.
 *
 * @private
 * @param {Object} map The map to query.
 * @param {string} key The reference key.
 * @returns {*} Returns the map data.
 */
function getMapData(map, key) {
  var data = map.__data__;
  return isKeyable(key)
    ? data[typeof key == 'string' ? 'string' : 'hash']
    : data.map;
}

/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = getValue(object, key);
  return baseIsNative(value) ? value : undefined;
}

/**
 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the raw `toStringTag`.
 */
function getRawTag(value) {
  var isOwn = hasOwnProperty.call(value, symToStringTag),
      tag = value[symToStringTag];

  try {
    value[symToStringTag] = undefined;
    var unmasked = true;
  } catch (e) {}

  var result = nativeObjectToString.call(value);
  if (unmasked) {
    if (isOwn) {
      value[symToStringTag] = tag;
    } else {
      delete value[symToStringTag];
    }
  }
  return result;
}

/**
 * Creates an array of the own enumerable symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of symbols.
 */
var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
  if (object == null) {
    return [];
  }
  object = Object(object);
  return arrayFilter(nativeGetSymbols(object), function(symbol) {
    return propertyIsEnumerable.call(object, symbol);
  });
};

/**
 * Gets the `toStringTag` of `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
var getTag = baseGetTag;

// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
    (Map && getTag(new Map) != mapTag) ||
    (Promise && getTag(Promise.resolve()) != promiseTag) ||
    (Set && getTag(new Set) != setTag) ||
    (WeakMap && getTag(new WeakMap) != weakMapTag)) {
  getTag = function(value) {
    var result = baseGetTag(value),
        Ctor = result == objectTag ? value.constructor : undefined,
        ctorString = Ctor ? toSource(Ctor) : '';

    if (ctorString) {
      switch (ctorString) {
        case dataViewCtorString: return dataViewTag;
        case mapCtorString: return mapTag;
        case promiseCtorString: return promiseTag;
        case setCtorString: return setTag;
        case weakMapCtorString: return weakMapTag;
      }
    }
    return result;
  };
}

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  length = length == null ? MAX_SAFE_INTEGER : length;
  return !!length &&
    (typeof value == 'number' || reIsUint.test(value)) &&
    (value > -1 && value % 1 == 0 && value < length);
}

/**
 * Checks if `value` is suitable for use as unique object key.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 */
function isKeyable(value) {
  var type = typeof value;
  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
    ? (value !== '__proto__')
    : (value === null);
}

/**
 * Checks if `func` has its source masked.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
 */
function isMasked(func) {
  return !!maskSrcKey && (maskSrcKey in func);
}

/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

  return value === proto;
}

/**
 * Converts `value` to a string using `Object.prototype.toString`.
 *
 * @private
 * @param {*} value The value to convert.
 * @returns {string} Returns the converted string.
 */
function objectToString(value) {
  return nativeObjectToString.call(value);
}

/**
 * Converts `func` to its source code.
 *
 * @private
 * @param {Function} func The function to convert.
 * @returns {string} Returns the source code.
 */
function toSource(func) {
  if (func != null) {
    try {
      return funcToString.call(func);
    } catch (e) {}
    try {
      return (func + '');
    } catch (e) {}
  }
  return '';
}

/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
  return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
    !propertyIsEnumerable.call(value, 'callee');
};

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

/**
 * Checks if `value` is a buffer.
 *
 * @static
 * @memberOf _
 * @since 4.3.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
 * @example
 *
 * _.isBuffer(new Buffer(2));
 * // => true
 *
 * _.isBuffer(new Uint8Array(2));
 * // => false
 */
var isBuffer = nativeIsBuffer || stubFalse;

/**
 * Performs a deep comparison between two values to determine if they are
 * equivalent.
 *
 * **Note:** This method supports comparing arrays, array buffers, booleans,
 * date objects, error objects, maps, numbers, `Object` objects, regexes,
 * sets, strings, symbols, and typed arrays. `Object` objects are compared
 * by their own, not inherited, enumerable properties. Functions and DOM
 * nodes are compared by strict equality, i.e. `===`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.isEqual(object, other);
 * // => true
 *
 * object === other;
 * // => false
 */
function isEqual(value, other) {
  return baseIsEqual(value, other);
}

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  if (!isObject(value)) {
    return false;
  }
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 9 which returns 'object' for typed arrays and other constructors.
  var tag = baseGetTag(value);
  return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
}

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return value != null && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return value != null && typeof value == 'object';
}

/**
 * Checks if `value` is classified as a typed array.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 * @example
 *
 * _.isTypedArray(new Uint8Array);
 * // => true
 *
 * _.isTypedArray([]);
 * // => false
 */
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;

/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}

/**
 * This method returns a new empty array.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {Array} Returns the new empty array.
 * @example
 *
 * var arrays = _.times(2, _.stubArray);
 *
 * console.log(arrays);
 * // => [[], []]
 *
 * console.log(arrays[0] === arrays[1]);
 * // => false
 */
function stubArray() {
  return [];
}

/**
 * This method returns `false`.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {boolean} Returns `false`.
 * @example
 *
 * _.times(2, _.stubFalse);
 * // => [false, false]
 */
function stubFalse() {
  return false;
}

module.exports = isEqual;
{
  "name": "lodash.isequal",
  "version": "4.5.0",
  "description": "The Lodash method `_.isEqual` exported as a module.",
  "homepage": "https://lodash.com/",
  "icon": "https://lodash.com/icon.svg",
  "license": "MIT",
  "author": "John-David Dalton <john.david.dalton@gmail.com> (http://allyoucanleet.com/)",
  "repository": "lodash/lodash"
}/**
 * Helpers.
 */

var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var w = d * 7;
var y = d * 365.25;

/**
 * Parse or format the given `val`.
 *
 * Options:
 *
 *  - `long` verbose formatting [false]
 *
 * @param {String|Number} val
 * @param {Object} [options]
 * @throws {Error} throw an error if val is not a non-empty string or a number
 * @return {String|Number}
 * @api public
 */

module.exports = function (val, options) {
  options = options || {};
  var type = typeof val;
  if (type === 'string' && val.length > 0) {
    return parse(val);
  } else if (type === 'number' && isFinite(val)) {
    return options.long ? fmtLong(val) : fmtShort(val);
  }
  throw new Error(
    'val is not a non-empty string or a valid number. val=' +
      JSON.stringify(val)
  );
};

/**
 * Parse the given `str` and return milliseconds.
 *
 * @param {String} str
 * @return {Number}
 * @api private
 */

function parse(str) {
  str = String(str);
  if (str.length > 100) {
    return;
  }
  var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
    str
  );
  if (!match) {
    return;
  }
  var n = parseFloat(match[1]);
  var type = (match[2] || 'ms').toLowerCase();
  switch (type) {
    case 'years':
    case 'year':
    case 'yrs':
    case 'yr':
    case 'y':
      return n * y;
    case 'weeks':
    case 'week':
    case 'w':
      return n * w;
    case 'days':
    case 'day':
    case 'd':
      return n * d;
    case 'hours':
    case 'hour':
    case 'hrs':
    case 'hr':
    case 'h':
      return n * h;
    case 'minutes':
    case 'minute':
    case 'mins':
    case 'min':
    case 'm':
      return n * m;
    case 'seconds':
    case 'second':
    case 'secs':
    case 'sec':
    case 's':
      return n * s;
    case 'milliseconds':
    case 'millisecond':
    case 'msecs':
    case 'msec':
    case 'ms':
      return n;
    default:
      return undefined;
  }
}

/**
 * Short format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function fmtShort(ms) {
  var msAbs = Math.abs(ms);
  if (msAbs >= d) {
    return Math.round(ms / d) + 'd';
  }
  if (msAbs >= h) {
    return Math.round(ms / h) + 'h';
  }
  if (msAbs >= m) {
    return Math.round(ms / m) + 'm';
  }
  if (msAbs >= s) {
    return Math.round(ms / s) + 's';
  }
  return ms + 'ms';
}

/**
 * Long format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function fmtLong(ms) {
  var msAbs = Math.abs(ms);
  if (msAbs >= d) {
    return plural(ms, msAbs, d, 'day');
  }
  if (msAbs >= h) {
    return plural(ms, msAbs, h, 'hour');
  }
  if (msAbs >= m) {
    return plural(ms, msAbs, m, 'minute');
  }
  if (msAbs >= s) {
    return plural(ms, msAbs, s, 'second');
  }
  return ms + ' ms';
}

/**
 * Pluralization helper.
 */

function plural(ms, msAbs, n, name) {
  var isPlural = msAbs >= n * 1.5;
  return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
}
The MIT License (MIT)

Copyright (c) 2020 Vercel, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
  "name": "ms",
  "version": "2.1.3",
  "description": "Tiny millisecond conversion utility",
  "repository": "vercel/ms",
  "main": "./index",
  "files": [
    "index.js"
  ],
  "lint-staged": {
    "*.js": [
      "npm run lint",
      "prettier --single-quote --write",
      "git add"
    ]
  },
  "license": "MIT",
  "devDependencies": {
    "eslint": "4.18.2",
    "expect.js": "0.3.1",
    "husky": "0.14.3",
    "lint-staged": "5.0.0",
    "mocha": "4.0.1",
    "prettier": "2.0.5"
  }
}# Blue Oak Model License

Version 1.0.0

## Purpose

This license gives everyone as much permission to work with
this software as possible, while protecting contributors
from liability.

## Acceptance

In order to receive this license, you must agree to its
rules.  The rules of this license are both obligations
under that agreement and conditions to your license.
You must not do anything with this software that triggers
a rule that you cannot or will not follow.

## Copyright

Each contributor licenses you to do everything with this
software that would otherwise infringe that contributor's
copyright in it.

## Notices

You must ensure that everyone who gets a copy of
any part of this software from you, with or without
changes, also gets the text of this license or a link to
<https://blueoakcouncil.org/license/1.0.0>.

## Excuse

If anyone notifies you in writing that you have not
complied with [Notices](#notices), you can keep your
license by taking all practical steps to comply within 30
days after the notice.  If you do not do so, your license
ends immediately.

## Patent

Each contributor licenses you to do everything with this
software that would otherwise infringe any patent claims
they can license or become able to license.

## Reliability

No contributor can revoke this license.

## No Liability

***As far as the law allows, this software comes as is,
without any warranty or condition, and no contributor
will be liable to anyone for any damages related to this
software or this license, under any kind of legal claim.***
{
  "name": "sax",
  "description": "An evented streaming XML parser in JavaScript",
  "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
  "version": "1.6.1",
  "main": "lib/sax.js",
  "license": "BlueOak-1.0.0",
  "repository": {
    "type": "git",
    "url": "git+ssh://git@github.com/isaacs/sax-js.git"
  },
  "files": [
    "lib/sax.js",
    "LICENSE",
    "README.md"
  ],
  "devDependencies": {
    "prettier": "^3.6.2",
    "tap": "^21.1.3"
  },
  "tap": {
    "allow-incomplete-coverage": true
  },
  "engines": {
    "node": ">=11.0.0"
  }
};(function (sax) {
  // wrapper for non-node envs
  sax.parser = function (strict, opt) {
    return new SAXParser(strict, opt)
  }
  sax.SAXParser = SAXParser
  sax.SAXStream = SAXStream
  sax.createStream = createStream

  // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns.
  // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)),
  // since that's the earliest that a buffer overrun could occur.  This way, checks are
  // as rare as required, but as often as necessary to ensure never crossing this bound.
  // Furthermore, buffers are only tested at most once per write(), so passing a very
  // large string into write() might have undesirable effects, but this is manageable by
  // the caller, so it is assumed to be safe.  Thus, a call to write() may, in the extreme
  // edge case, result in creating at most one complete copy of the string passed in.
  // Set to Infinity to have unlimited buffers.
  sax.MAX_BUFFER_LENGTH = 64 * 1024

  var buffers = [
    'comment',
    'sgmlDecl',
    'textNode',
    'tagName',
    'doctype',
    'procInstName',
    'procInstBody',
    'entity',
    'attribName',
    'attribValue',
    'cdata',
    'script',
  ]

  sax.EVENTS = [
    'text',
    'processinginstruction',
    'sgmldeclaration',
    'doctype',
    'comment',
    'opentagstart',
    'attribute',
    'opentag',
    'closetag',
    'opencdata',
    'cdata',
    'closecdata',
    'error',
    'end',
    'ready',
    'script',
    'opennamespace',
    'closenamespace',
  ]

  function SAXParser(strict, opt) {
    if (!(this instanceof SAXParser)) {
      return new SAXParser(strict, opt)
    }

    var parser = this
    clearBuffers(parser)
    parser.q = parser.c = ''
    parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH
    parser.encoding = null;
    parser.opt = opt || {}
    parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags
    parser.looseCase = parser.opt.lowercase ? 'toLowerCase' : 'toUpperCase'
    parser.opt.maxEntityCount = parser.opt.maxEntityCount || 512
    parser.opt.maxEntityDepth = parser.opt.maxEntityDepth || 4
    parser.entityCount = parser.entityDepth = 0
    parser.tags = []
    parser.closed = parser.closedRoot = parser.sawRoot = false
    parser.tag = parser.error = null
    parser.strict = !!strict
    parser.noscript = !!(strict || parser.opt.noscript)
    parser.state = S.BEGIN
    parser.strictEntities = parser.opt.strictEntities
    parser.ENTITIES =
      parser.strictEntities ?
        Object.create(sax.XML_ENTITIES)
      : Object.create(sax.ENTITIES)
    parser.attribList = []

    // namespaces form a prototype chain.
    // it always points at the current tag,
    // which protos to its parent tag.
    if (parser.opt.xmlns) {
      parser.ns = Object.create(rootNS)
    }

    // disallow unquoted attribute values if not otherwise configured
    // and strict mode is true
    if (parser.opt.unquotedAttributeValues === undefined) {
      parser.opt.unquotedAttributeValues = !strict
    }

    // mostly just for error reporting
    parser.trackPosition = parser.opt.position !== false
    if (parser.trackPosition) {
      parser.position = parser.line = parser.column = 0
    }
    emit(parser, 'onready')
  }

  if (!Object.create) {
    Object.create = function (o) {
      function F() {}
      F.prototype = o
      var newf = new F()
      return newf
    }
  }

  if (!Object.keys) {
    Object.keys = function (o) {
      var a = []
      for (var i in o) if (o.hasOwnProperty(i)) a.push(i)
      return a
    }
  }

  function checkBufferLength(parser) {
    var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10)
    var maxActual = 0
    for (var i = 0, l = buffers.length; i < l; i++) {
      var len = parser[buffers[i]].length
      if (len > maxAllowed) {
        // Text/cdata nodes can get big, and since they're buffered,
        // we can get here under normal conditions.
        // Avoid issues by emitting the text node now,
        // so at least it won't get any bigger.
        switch (buffers[i]) {
          case 'textNode':
            closeText(parser)
            break

          case 'cdata':
            emitNode(parser, 'oncdata', parser.cdata)
            parser.cdata = ''
            break

          case 'script':
            emitNode(parser, 'onscript', parser.script)
            parser.script = ''
            break

          default:
            error(parser, 'Max buffer length exceeded: ' + buffers[i])
        }
      }
      maxActual = Math.max(maxActual, len)
    }
    // schedule the next check for the earliest possible buffer overrun.
    var m = sax.MAX_BUFFER_LENGTH - maxActual
    parser.bufferCheckPosition = m + parser.position
  }

  function clearBuffers(parser) {
    for (var i = 0, l = buffers.length; i < l; i++) {
      parser[buffers[i]] = ''
    }
  }

  function flushBuffers(parser) {
    closeText(parser)
    if (parser.cdata !== '') {
      emitNode(parser, 'oncdata', parser.cdata)
      parser.cdata = ''
    }
    if (parser.script !== '') {
      emitNode(parser, 'onscript', parser.script)
      parser.script = ''
    }
  }

  SAXParser.prototype = {
    end: function () {
      end(this)
    },
    write: write,
    resume: function () {
      this.error = null
      return this
    },
    close: function () {
      return this.write(null)
    },
    flush: function () {
      flushBuffers(this)
    },
  }

  var Stream
  try {
    Stream = require('stream').Stream
  } catch (ex) {
    Stream = function () {}
  }
  if (!Stream) Stream = function () {}

  var streamWraps = sax.EVENTS.filter(function (ev) {
    return ev !== 'error' && ev !== 'end'
  })

  function createStream(strict, opt) {
    return new SAXStream(strict, opt)
  }

  function determineBufferEncoding(data, isEnd) {
    // BOM-based detection is the most reliable signal when present.
    if (data.length >= 2) {
      if (data[0] === 0xff && data[1] === 0xfe) {
        return 'utf-16le'
      }

      if (data[0] === 0xfe && data[1] === 0xff) {
        return 'utf-16be'
      }
    }

    if (data.length >= 3 && data[0] === 0xef && data[1] === 0xbb && data[2] === 0xbf) {
      return 'utf8'
    }

    if (data.length >= 4) {
      // XML documents without a BOM still start with "<?xml", which is enough
      // to distinguish UTF-16LE/BE from UTF-8 by looking at the zero bytes.
      if (data[0] === 0x3c && data[1] === 0x00 && data[2] === 0x3f && data[3] === 0x00) {
        return 'utf-16le'
      }

      if (data[0] === 0x00 && data[1] === 0x3c && data[2] === 0x00 && data[3] === 0x3f) {
        return 'utf-16be'
      }

      return 'utf8'
    }

    return isEnd ? 'utf8' : null
  }

  function SAXStream(strict, opt) {
    if (!(this instanceof SAXStream)) {
      return new SAXStream(strict, opt)
    }

    Stream.apply(this)

    this._parser = new SAXParser(strict, opt)
    this.writable = true
    this.readable = true

    var me = this

    this._parser.onend = function () {
      me.emit('end')
    }

    this._parser.onerror = function (er) {
      me.emit('error', er)

      // if didn't throw, then means error was handled.
      // go ahead and clear error, so we can write again.
      me._parser.error = null
    }

    this._decoder = null
    this._decoderBuffer = null
    streamWraps.forEach(function (ev) {
      Object.defineProperty(me, 'on' + ev, {
        get: function () {
          return me._parser['on' + ev]
        },
        set: function (h) {
          if (!h) {
            me.removeAllListeners(ev)
            me._parser['on' + ev] = h
            return h
          }
          me.on(ev, h)
        },
        enumerable: true,
        configurable: false,
      })
    })
  }

  SAXStream.prototype = Object.create(Stream.prototype, {
    constructor: {
      value: SAXStream,
    },
  })

  SAXStream.prototype._decodeBuffer = function (data, isEnd) {
    if (this._decoderBuffer) {
      // Keep incomplete leading bytes until we have enough data to infer the
      // stream encoding, then decode the buffered prefix together with the next chunk.
      data = Buffer.concat([this._decoderBuffer, data])
      this._decoderBuffer = null
    }

    if (!this._decoder) {
      var encoding = determineBufferEncoding(data, isEnd)
      if (!encoding) {
        // A very short first chunk may not contain enough bytes to detect the
        // encoding yet, so defer decoding until the next write/end call.
        this._decoderBuffer = data
        return ''
      }

      // Store the detected transport encoding so strict mode can compare it
      // with the optional encoding declared in the XML prolog later on.
      this._parser.encoding = encoding
      this._decoder = new TextDecoder(encoding)
    }

    return this._decoder.decode(data, { stream: !isEnd })
  }

  SAXStream.prototype.write = function (data) {
    if (
      typeof Buffer === 'function' &&
      typeof Buffer.isBuffer === 'function' &&
      Buffer.isBuffer(data)
    ) {
      data = this._decodeBuffer(data, false)
    } else if (this._decoderBuffer) {
      // Flush any buffered binary prefix before handling a string chunk.
      // This only matters if the caller mixes Buffer and string writes (used in test).
      var remaining = this._decodeBuffer(Buffer.alloc(0), true)
      if (remaining) {
        this._parser.write(remaining)
        this.emit('data', remaining)
      }
    }

    this._parser.write(data.toString())
    this.emit('data', data)
    return true
  }

  SAXStream.prototype.end = function (chunk) {
    if (chunk && chunk.length) {
      this.write(chunk)
    }
    // Flush any remaining decoded data from the TextDecoder
    if (this._decoderBuffer) {
      var finalChunk = this._decodeBuffer(Buffer.alloc(0), true)
      if (finalChunk) {
        this._parser.write(finalChunk)
        this.emit('data', finalChunk)
      }
    } else if (this._decoder) {
      var remaining = this._decoder.decode()
      if (remaining) {
        this._parser.write(remaining)
        this.emit('data', remaining)
      }
    }
    this._parser.end()
    return true
  }

  SAXStream.prototype.on = function (ev, handler) {
    var me = this
    if (!me._parser['on' + ev] && streamWraps.indexOf(ev) !== -1) {
      me._parser['on' + ev] = function () {
        var args =
          arguments.length === 1 ?
            [arguments[0]]
          : Array.apply(null, arguments)
        args.splice(0, 0, ev)
        me.emit.apply(me, args)
      }
    }

    return Stream.prototype.on.call(me, ev, handler)
  }

  // this really needs to be replaced with character classes.
  // XML allows all manner of ridiculous numbers and digits.
  var CDATAre = /^\[CDATA\[$/i
  var DOCTYPEre = /^DOCTYPE$/i
  var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'
  var XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/'
  var rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE }

  // http://www.w3.org/TR/REC-xml/#NT-NameStartChar
  // This implementation works on strings, a single character at a time
  // as such, it cannot ever support astral-plane characters (10000-EFFFF)
  // without a significant breaking change to either this  parser, or the
  // JavaScript language.  Implementation of an emoji-capable xml parser
  // is left as an exercise for the reader.
  var nameStart =
    /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/

  var nameBody =
    /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/

  var entityStart =
    /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
  var entityBody =
    /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/

  function isWhitespace(c) {
    return c === ' ' || c === '\n' || c === '\r' || c === '\t'
  }

  function isQuote(c) {
    return c === '"' || c === "'"
  }

  function isAttribEnd(c) {
    return c === '>' || isWhitespace(c)
  }

  function isMatch(regex, c) {
    return regex.test(c)
  }

  function notMatch(regex, c) {
    return !isMatch(regex, c)
  }

  var S = 0
  sax.STATE = {
    BEGIN: S++, // leading byte order mark or whitespace
    BEGIN_WHITESPACE: S++, // leading whitespace
    TEXT: S++, // general stuff
    TEXT_ENTITY: S++, // &amp and such.
    OPEN_WAKA: S++, // <
    SGML_DECL: S++, // <!BLARG
    SGML_DECL_QUOTED: S++, // <!BLARG foo "bar
    DOCTYPE: S++, // <!DOCTYPE
    DOCTYPE_QUOTED: S++, // <!DOCTYPE "//blah
    DOCTYPE_DTD: S++, // <!DOCTYPE "//blah" [ ...
    DOCTYPE_DTD_QUOTED: S++, // <!DOCTYPE "//blah" [ "foo
    COMMENT_STARTING: S++, // <!-
    COMMENT: S++, // <!--
    COMMENT_ENDING: S++, // <!-- blah -
    COMMENT_ENDED: S++, // <!-- blah --
    CDATA: S++, // <![CDATA[ something
    CDATA_ENDING: S++, // ]
    CDATA_ENDING_2: S++, // ]]
    PROC_INST: S++, // <?hi
    PROC_INST_BODY: S++, // <?hi there
    PROC_INST_ENDING: S++, // <?hi "there" ?
    OPEN_TAG: S++, // <strong
    OPEN_TAG_SLASH: S++, // <strong /
    ATTRIB: S++, // <a
    ATTRIB_NAME: S++, // <a foo
    ATTRIB_NAME_SAW_WHITE: S++, // <a foo _
    ATTRIB_VALUE: S++, // <a foo=
    ATTRIB_VALUE_QUOTED: S++, // <a foo="bar
    ATTRIB_VALUE_CLOSED: S++, // <a foo="bar"
    ATTRIB_VALUE_UNQUOTED: S++, // <a foo=bar
    ATTRIB_VALUE_ENTITY_Q: S++, // <foo bar="&quot;"
    ATTRIB_VALUE_ENTITY_U: S++, // <foo bar=&quot
    CLOSE_TAG: S++, // </a
    CLOSE_TAG_SAW_WHITE: S++, // </a   >
    SCRIPT: S++, // <script> ...
    SCRIPT_ENDING: S++, // <script> ... <
  }

  sax.XML_ENTITIES = Object.assign(Object.create(null), {
    amp: '&',
    gt: '>',
    lt: '<',
    quot: '"',
    apos: "'",
  })

  sax.ENTITIES = Object.assign(Object.create(null), {
    amp: '&',
    gt: '>',
    lt: '<',
    quot: '"',
    apos: "'",
    AElig: 198,
    Aacute: 193,
    Acirc: 194,
    Agrave: 192,
    Aring: 197,
    Atilde: 195,
    Auml: 196,
    Ccedil: 199,
    ETH: 208,
    Eacute: 201,
    Ecirc: 202,
    Egrave: 200,
    Euml: 203,
    Iacute: 205,
    Icirc: 206,
    Igrave: 204,
    Iuml: 207,
    Ntilde: 209,
    Oacute: 211,
    Ocirc: 212,
    Ograve: 210,
    Oslash: 216,
    Otilde: 213,
    Ouml: 214,
    THORN: 222,
    Uacute: 218,
    Ucirc: 219,
    Ugrave: 217,
    Uuml: 220,
    Yacute: 221,
    aacute: 225,
    acirc: 226,
    aelig: 230,
    agrave: 224,
    aring: 229,
    atilde: 227,
    auml: 228,
    ccedil: 231,
    eacute: 233,
    ecirc: 234,
    egrave: 232,
    eth: 240,
    euml: 235,
    iacute: 237,
    icirc: 238,
    igrave: 236,
    iuml: 239,
    ntilde: 241,
    oacute: 243,
    ocirc: 244,
    ograve: 242,
    oslash: 248,
    otilde: 245,
    ouml: 246,
    szlig: 223,
    thorn: 254,
    uacute: 250,
    ucirc: 251,
    ugrave: 249,
    uuml: 252,
    yacute: 253,
    yuml: 255,
    copy: 169,
    reg: 174,
    nbsp: 160,
    iexcl: 161,
    cent: 162,
    pound: 163,
    curren: 164,
    yen: 165,
    brvbar: 166,
    sect: 167,
    uml: 168,
    ordf: 170,
    laquo: 171,
    not: 172,
    shy: 173,
    macr: 175,
    deg: 176,
    plusmn: 177,
    sup1: 185,
    sup2: 178,
    sup3: 179,
    acute: 180,
    micro: 181,
    para: 182,
    middot: 183,
    cedil: 184,
    ordm: 186,
    raquo: 187,
    frac14: 188,
    frac12: 189,
    frac34: 190,
    iquest: 191,
    times: 215,
    divide: 247,
    OElig: 338,
    oelig: 339,
    Scaron: 352,
    scaron: 353,
    Yuml: 376,
    fnof: 402,
    circ: 710,
    tilde: 732,
    Alpha: 913,
    Beta: 914,
    Gamma: 915,
    Delta: 916,
    Epsilon: 917,
    Zeta: 918,
    Eta: 919,
    Theta: 920,
    Iota: 921,
    Kappa: 922,
    Lambda: 923,
    Mu: 924,
    Nu: 925,
    Xi: 926,
    Omicron: 927,
    Pi: 928,
    Rho: 929,
    Sigma: 931,
    Tau: 932,
    Upsilon: 933,
    Phi: 934,
    Chi: 935,
    Psi: 936,
    Omega: 937,
    alpha: 945,
    beta: 946,
    gamma: 947,
    delta: 948,
    epsilon: 949,
    zeta: 950,
    eta: 951,
    theta: 952,
    iota: 953,
    kappa: 954,
    lambda: 955,
    mu: 956,
    nu: 957,
    xi: 958,
    omicron: 959,
    pi: 960,
    rho: 961,
    sigmaf: 962,
    sigma: 963,
    tau: 964,
    upsilon: 965,
    phi: 966,
    chi: 967,
    psi: 968,
    omega: 969,
    thetasym: 977,
    upsih: 978,
    piv: 982,
    ensp: 8194,
    emsp: 8195,
    thinsp: 8201,
    zwnj: 8204,
    zwj: 8205,
    lrm: 8206,
    rlm: 8207,
    ndash: 8211,
    mdash: 8212,
    lsquo: 8216,
    rsquo: 8217,
    sbquo: 8218,
    ldquo: 8220,
    rdquo: 8221,
    bdquo: 8222,
    dagger: 8224,
    Dagger: 8225,
    bull: 8226,
    hellip: 8230,
    permil: 8240,
    prime: 8242,
    Prime: 8243,
    lsaquo: 8249,
    rsaquo: 8250,
    oline: 8254,
    frasl: 8260,
    euro: 8364,
    image: 8465,
    weierp: 8472,
    real: 8476,
    trade: 8482,
    alefsym: 8501,
    larr: 8592,
    uarr: 8593,
    rarr: 8594,
    darr: 8595,
    harr: 8596,
    crarr: 8629,
    lArr: 8656,
    uArr: 8657,
    rArr: 8658,
    dArr: 8659,
    hArr: 8660,
    forall: 8704,
    part: 8706,
    exist: 8707,
    empty: 8709,
    nabla: 8711,
    isin: 8712,
    notin: 8713,
    ni: 8715,
    prod: 8719,
    sum: 8721,
    minus: 8722,
    lowast: 8727,
    radic: 8730,
    prop: 8733,
    infin: 8734,
    ang: 8736,
    and: 8743,
    or: 8744,
    cap: 8745,
    cup: 8746,
    int: 8747,
    there4: 8756,
    sim: 8764,
    cong: 8773,
    asymp: 8776,
    ne: 8800,
    equiv: 8801,
    le: 8804,
    ge: 8805,
    sub: 8834,
    sup: 8835,
    nsub: 8836,
    sube: 8838,
    supe: 8839,
    oplus: 8853,
    otimes: 8855,
    perp: 8869,
    sdot: 8901,
    lceil: 8968,
    rceil: 8969,
    lfloor: 8970,
    rfloor: 8971,
    lang: 9001,
    rang: 9002,
    loz: 9674,
    spades: 9824,
    clubs: 9827,
    hearts: 9829,
    diams: 9830,
  })

  Object.keys(sax.ENTITIES).forEach(function (key) {
    var e = sax.ENTITIES[key]
    var s = typeof e === 'number' ? String.fromCharCode(e) : e
    sax.ENTITIES[key] = s
  })

  for (var s in sax.STATE) {
    sax.STATE[sax.STATE[s]] = s
  }

  // shorthand
  S = sax.STATE

  function emit(parser, event, data) {
    parser[event] && parser[event](data)
  }

  function getDeclaredEncoding(body) {
    var match = body && body.match(/(?:^|\s)encoding\s*=\s*(['"])([^'"]+)\1/i)
    return match ? match[2] : null
  }

  function normalizeEncodingName(encoding) {
    if (!encoding) {
      return null
    }

    return encoding.toLowerCase().replace(/[^a-z0-9]/g, '')
  }

  function encodingsMatch(detectedEncoding, declaredEncoding) {
    const detected = normalizeEncodingName(detectedEncoding)
    const declared = normalizeEncodingName(declaredEncoding)

    if (!detected || !declared) {
      return true
    }

    if (declared === 'utf16') {
      return detected === 'utf16le' || detected === 'utf16be'
    }

    return detected === declared
  }

  function validateXmlDeclarationEncoding(parser, data) {
    if (
      !parser.strict ||
      !parser.encoding ||
      !data ||
      data.name !== 'xml'
    ) {
      return
    }

    var declaredEncoding = getDeclaredEncoding(data.body)
    if (
      declaredEncoding &&
      !encodingsMatch(parser.encoding, declaredEncoding)
    ) {
      strictFail(
        parser,
        'XML declaration encoding ' +
          declaredEncoding +
          ' does not match detected stream encoding ' +
          parser.encoding.toUpperCase()
      )
    }
  }

  function emitNode(parser, nodeType, data) {
    if (parser.textNode) closeText(parser)
    emit(parser, nodeType, data)
  }

  function closeText(parser) {
    parser.textNode = textopts(parser.opt, parser.textNode)
    if (parser.textNode) emit(parser, 'ontext', parser.textNode)
    parser.textNode = ''
  }

  function textopts(opt, text) {
    if (opt.trim) text = text.trim()
    if (opt.normalize) text = text.replace(/\s+/g, ' ')
    return text
  }

  function error(parser, er) {
    closeText(parser)
    if (parser.trackPosition) {
      er +=
        '\nLine: ' +
        parser.line +
        '\nColumn: ' +
        parser.column +
        '\nChar: ' +
        parser.c
    }
    er = new Error(er)
    parser.error = er
    emit(parser, 'onerror', er)
    return parser
  }

  function end(parser) {
    if (parser.sawRoot && !parser.closedRoot)
      strictFail(parser, 'Unclosed root tag')
    if (
      parser.state !== S.BEGIN &&
      parser.state !== S.BEGIN_WHITESPACE &&
      parser.state !== S.TEXT
    ) {
      error(parser, 'Unexpected end')
    }
    closeText(parser)
    parser.c = ''
    parser.closed = true
    emit(parser, 'onend')
    SAXParser.call(parser, parser.strict, parser.opt)
    return parser
  }

  function strictFail(parser, message) {
    if (typeof parser !== 'object' || !(parser instanceof SAXParser)) {
      throw new Error('bad call to strictFail')
    }
    if (parser.strict) {
      error(parser, message)
    }
  }

  function newTag(parser) {
    if (!parser.strict) parser.tagName = parser.tagName[parser.looseCase]()
    var parent = parser.tags[parser.tags.length - 1] || parser
    var tag = (parser.tag = { name: parser.tagName, attributes: {} })

    // will be overridden if tag contails an xmlns="foo" or xmlns:foo="bar"
    if (parser.opt.xmlns) {
      tag.ns = parent.ns
    }
    parser.attribList.length = 0
    emitNode(parser, 'onopentagstart', tag)
  }

  function qname(name, attribute) {
    var i = name.indexOf(':')
    var qualName = i < 0 ? ['', name] : name.split(':')
    var prefix = qualName[0]
    var local = qualName[1]

    // <x "xmlns"="http://foo">
    if (attribute && name === 'xmlns') {
      prefix = 'xmlns'
      local = ''
    }

    return { prefix: prefix, local: local }
  }

  function attrib(parser) {
    if (!parser.strict) {
      parser.attribName = parser.attribName[parser.looseCase]()
    }

    if (
      parser.attribList.indexOf(parser.attribName) !== -1 ||
      parser.tag.attributes.hasOwnProperty(parser.attribName)
    ) {
      parser.attribName = parser.attribValue = ''
      return
    }

    if (parser.opt.xmlns) {
      var qn = qname(parser.attribName, true)
      var prefix = qn.prefix
      var local = qn.local

      if (prefix === 'xmlns') {
        // namespace binding attribute. push the binding into scope
        if (local === 'xml' && parser.attribValue !== XML_NAMESPACE) {
          strictFail(
            parser,
            'xml: prefix must be bound to ' +
              XML_NAMESPACE +
              '\n' +
              'Actual: ' +
              parser.attribValue
          )
        } else if (
          local === 'xmlns' &&
          parser.attribValue !== XMLNS_NAMESPACE
        ) {
          strictFail(
            parser,
            'xmlns: prefix must be bound to ' +
              XMLNS_NAMESPACE +
              '\n' +
              'Actual: ' +
              parser.attribValue
          )
        } else {
          var tag = parser.tag
          var parent = parser.tags[parser.tags.length - 1] || parser
          if (tag.ns === parent.ns) {
            tag.ns = Object.create(parent.ns)
          }
          tag.ns[local] = parser.attribValue
        }
      }

      // defer onattribute events until all attributes have been seen
      // so any new bindings can take effect. preserve attribute order
      // so deferred events can be emitted in document order
      parser.attribList.push([parser.attribName, parser.attribValue])
    } else {
      // in non-xmlns mode, we can emit the event right away
      parser.tag.attributes[parser.attribName] = parser.attribValue
      emitNode(parser, 'onattribute', {
        name: parser.attribName,
        value: parser.attribValue,
      })
    }

    parser.attribName = parser.attribValue = ''
  }

  function openTag(parser, selfClosing) {
    if (parser.opt.xmlns) {
      // emit namespace binding events
      var tag = parser.tag

      // add namespace info to tag
      var qn = qname(parser.tagName)
      tag.prefix = qn.prefix
      tag.local = qn.local
      tag.uri = tag.ns[qn.prefix] || ''

      if (tag.prefix && !tag.uri) {
        strictFail(
          parser,
          'Unbound namespace prefix: ' + JSON.stringify(parser.tagName)
        )
        tag.uri = qn.prefix
      }

      var parent = parser.tags[parser.tags.length - 1] || parser
      if (tag.ns && parent.ns !== tag.ns) {
        Object.keys(tag.ns).forEach(function (p) {
          emitNode(parser, 'onopennamespace', {
            prefix: p,
            uri: tag.ns[p],
          })
        })
      }

      // handle deferred onattribute events
      // Note: do not apply default ns to attributes:
      //   http://www.w3.org/TR/REC-xml-names/#defaulting
      for (var i = 0, l = parser.attribList.length; i < l; i++) {
        var nv = parser.attribList[i]
        var name = nv[0]
        var value = nv[1]
        var qualName = qname(name, true)
        var prefix = qualName.prefix
        var local = qualName.local
        var uri = prefix === '' ? '' : tag.ns[prefix] || ''
        var a = {
          name: name,
          value: value,
          prefix: prefix,
          local: local,
          uri: uri,
        }

        // if there's any attributes with an undefined namespace,
        // then fail on them now.
        if (prefix && prefix !== 'xmlns' && !uri) {
          strictFail(
            parser,
            'Unbound namespace prefix: ' + JSON.stringify(prefix)
          )
          a.uri = prefix
        }
        parser.tag.attributes[name] = a
        emitNode(parser, 'onattribute', a)
      }
      parser.attribList.length = 0
    }

    parser.tag.isSelfClosing = !!selfClosing

    // process the tag
    parser.sawRoot = true
    parser.tags.push(parser.tag)
    emitNode(parser, 'onopentag', parser.tag)
    if (!selfClosing) {
      // special case for <script> in non-strict mode.
      if (!parser.noscript && parser.tagName.toLowerCase() === 'script') {
        parser.state = S.SCRIPT
      } else {
        parser.state = S.TEXT
      }
      parser.tag = null
      parser.tagName = ''
    }
    parser.attribName = parser.attribValue = ''
    parser.attribList.length = 0
  }

  function closeTag(parser) {
    if (!parser.tagName) {
      strictFail(parser, 'Weird empty close tag.')
      parser.textNode += '</>'
      parser.state = S.TEXT
      return
    }

    if (parser.script) {
      if (parser.tagName !== 'script') {
        parser.script += '</' + parser.tagName + '>'
        parser.tagName = ''
        parser.state = S.SCRIPT
        return
      }
      emitNode(parser, 'onscript', parser.script)
      parser.script = ''
    }

    // first make sure that the closing tag actually exists.
    // <a><b></c></b></a> will close everything, otherwise.
    var t = parser.tags.length
    var tagName = parser.tagName
    if (!parser.strict) {
      tagName = tagName[parser.looseCase]()
    }
    var closeTo = tagName
    while (t--) {
      var close = parser.tags[t]
      if (close.name !== closeTo) {
        // fail the first time in strict mode
        strictFail(parser, 'Unexpected close tag')
      } else {
        break
      }
    }

    // didn't find it.  we already failed for strict, so just abort.
    if (t < 0) {
      strictFail(parser, 'Unmatched closing tag: ' + parser.tagName)
      parser.textNode += '</' + parser.tagName + '>'
      parser.state = S.TEXT
      return
    }
    parser.tagName = tagName
    var s = parser.tags.length
    while (s-- > t) {
      var tag = (parser.tag = parser.tags.pop())
      parser.tagName = parser.tag.name
      emitNode(parser, 'onclosetag', parser.tagName)

      var x = {}
      for (var i in tag.ns) {
        x[i] = tag.ns[i]
      }

      var parent = parser.tags[parser.tags.length - 1] || parser
      if (parser.opt.xmlns && tag.ns !== parent.ns) {
        // remove namespace bindings introduced by tag
        Object.keys(tag.ns).forEach(function (p) {
          var n = tag.ns[p]
          emitNode(parser, 'onclosenamespace', { prefix: p, uri: n })
        })
      }
    }
    if (t === 0) parser.closedRoot = true
    parser.tagName = parser.attribValue = parser.attribName = ''
    parser.attribList.length = 0
    parser.state = S.TEXT
  }

  function parseEntity(parser) {
    var entity = parser.entity
    var entityLC = entity.toLowerCase()
    var num
    var numStr = ''

    if (parser.ENTITIES[entity]) {
      return parser.ENTITIES[entity]
    }
    if (parser.ENTITIES[entityLC]) {
      return parser.ENTITIES[entityLC]
    }
    entity = entityLC
    if (entity.charAt(0) === '#') {
      if (entity.charAt(1) === 'x') {
        entity = entity.slice(2)
        num = parseInt(entity, 16)
        numStr = num.toString(16)
      } else {
        entity = entity.slice(1)
        num = parseInt(entity, 10)
        numStr = num.toString(10)
      }
    }
    entity = entity.replace(/^0+/, '')
    if (
      isNaN(num) ||
      numStr.toLowerCase() !== entity ||
      num < 0 ||
      num > 0x10ffff ||
      !isXmlChar(num)
    ) {
      strictFail(parser, 'Invalid character entity')
      return '&' + parser.entity + ';'
    }

    return String.fromCodePoint(num)
  }

  // Returns true if `num` is a code point that matches the XML `Char`
  // production, false otherwise. Character references that resolve to a
  // character outside this range (e.g. surrogates or restricted control
  // characters) are not well-formed.
  // https://www.w3.org/TR/REC-xml/#NT-Char
  // https://www.w3.org/TR/REC-xml/#wf-Legalchar
  function isXmlChar(num) {
    return (
      num === 0x9 ||
      num === 0xa ||
      num === 0xd ||
      (num >= 0x20 && num <= 0xd7ff) ||
      (num >= 0xe000 && num <= 0xfffd) ||
      (num >= 0x10000 && num <= 0x10ffff)
    )
  }

  function beginWhiteSpace(parser, c) {
    if (c === '<') {
      parser.state = S.OPEN_WAKA
      parser.startTagPosition = parser.position
    } else if (!isWhitespace(c)) {
      // have to process this as a text node.
      // weird, but happens.
      strictFail(parser, 'Non-whitespace before first tag.')
      parser.textNode = c
      parser.state = S.TEXT
    }
  }

  function charAt(chunk, i) {
    var result = ''
    if (i < chunk.length) {
      result = chunk.charAt(i)
    }
    return result
  }

  function write(chunk) {
    var parser = this
    if (this.error) {
      throw this.error
    }
    if (parser.closed) {
      return error(
        parser,
        'Cannot write after close. Assign an onready handler.'
      )
    }
    if (chunk === null) {
      return end(parser)
    }
    if (typeof chunk === 'object') {
      chunk = chunk.toString()
    }
    var i = 0
    var c = ''
    while (true) {
      c = charAt(chunk, i++)
      parser.c = c

      if (!c) {
        break
      }

      if (parser.trackPosition) {
        parser.position++
        if (c === '\n') {
          parser.line++
          parser.column = 0
        } else {
          parser.column++
        }
      }

      switch (parser.state) {
        case S.BEGIN:
          parser.state = S.BEGIN_WHITESPACE
          if (c === '\uFEFF') {
            continue
          }
          beginWhiteSpace(parser, c)
          continue

        case S.BEGIN_WHITESPACE:
          beginWhiteSpace(parser, c)
          continue

        case S.TEXT:
          if (parser.sawRoot && !parser.closedRoot) {
            var starti = i - 1
            while (c && c !== '<' && c !== '&') {
              c = charAt(chunk, i++)
              if (c && parser.trackPosition) {
                parser.position++
                if (c === '\n') {
                  parser.line++
                  parser.column = 0
                } else {
                  parser.column++
                }
              }
            }
            parser.textNode += chunk.substring(starti, i - 1)
          }
          if (
            c === '<' &&
            !(parser.sawRoot && parser.closedRoot && !parser.strict)
          ) {
            parser.state = S.OPEN_WAKA
            parser.startTagPosition = parser.position
          } else {
            if (
              !isWhitespace(c) &&
              (!parser.sawRoot || parser.closedRoot)
            ) {
              strictFail(parser, 'Text data outside of root node.')
            }
            if (c === '&') {
              parser.state = S.TEXT_ENTITY
            } else {
              parser.textNode += c
            }
          }
          continue

        case S.SCRIPT:
          // only non-strict
          if (c === '<') {
            parser.state = S.SCRIPT_ENDING
          } else {
            parser.script += c
          }
          continue

        case S.SCRIPT_ENDING:
          if (c === '/') {
            parser.state = S.CLOSE_TAG
          } else {
            parser.script += '<' + c
            parser.state = S.SCRIPT
          }
          continue

        case S.OPEN_WAKA:
          // either a /, ?, !, or text is coming next.
          if (c === '!') {
            parser.state = S.SGML_DECL
            parser.sgmlDecl = ''
          } else if (isWhitespace(c)) {
            // wait for it...
          } else if (isMatch(nameStart, c)) {
            parser.state = S.OPEN_TAG
            parser.tagName = c
          } else if (c === '/') {
            parser.state = S.CLOSE_TAG
            parser.tagName = ''
          } else if (c === '?') {
            parser.state = S.PROC_INST
            parser.procInstName = parser.procInstBody = ''
          } else {
            strictFail(parser, 'Unencoded <')
            // if there was some whitespace, then add that in.
            if (parser.startTagPosition + 1 < parser.position) {
              var pad = parser.position - parser.startTagPosition
              c = new Array(pad).join(' ') + c
            }
            parser.textNode += '<' + c
            parser.state = S.TEXT
          }
          continue

        case S.SGML_DECL:
          if (parser.sgmlDecl + c === '--') {
            parser.state = S.COMMENT
            parser.comment = ''
            parser.sgmlDecl = ''
            continue
          }

          if (
            parser.doctype &&
            parser.doctype !== true &&
            parser.sgmlDecl
          ) {
            parser.state = S.DOCTYPE_DTD
            parser.doctype += '<!' + parser.sgmlDecl + c
            parser.sgmlDecl = ''
          } else if (CDATAre.test(parser.sgmlDecl + c)) {
            emitNode(parser, 'onopencdata')
            parser.state = S.CDATA
            parser.sgmlDecl = ''
            parser.cdata = ''
          } else if (DOCTYPEre.test(parser.sgmlDecl + c)) {
            parser.state = S.DOCTYPE
            if (parser.doctype || parser.sawRoot) {
              strictFail(
                parser,
                'Inappropriately located doctype declaration'
              )
            }
            parser.doctype = ''
            parser.sgmlDecl = ''
          } else if (c === '>') {
            emitNode(parser, 'onsgmldeclaration', parser.sgmlDecl)
            parser.sgmlDecl = ''
            parser.state = S.TEXT
          } else if (isQuote(c)) {
            parser.state = S.SGML_DECL_QUOTED
            parser.sgmlDecl += c
          } else {
            parser.sgmlDecl += c
          }
          continue

        case S.SGML_DECL_QUOTED:
          if (c === parser.q) {
            parser.state = S.SGML_DECL
            parser.q = ''
          }
          parser.sgmlDecl += c
          continue

        case S.DOCTYPE:
          if (c === '>') {
            parser.state = S.TEXT
            emitNode(parser, 'ondoctype', parser.doctype)
            parser.doctype = true // just remember that we saw it.
          } else {
            parser.doctype += c
            if (c === '[') {
              parser.state = S.DOCTYPE_DTD
            } else if (isQuote(c)) {
              parser.state = S.DOCTYPE_QUOTED
              parser.q = c
            }
          }
          continue

        case S.DOCTYPE_QUOTED:
          parser.doctype += c
          if (c === parser.q) {
            parser.q = ''
            parser.state = S.DOCTYPE
          }
          continue

        case S.DOCTYPE_DTD:
          if (c === ']') {
            parser.doctype += c
            parser.state = S.DOCTYPE
          } else if (c === '<') {
            parser.state = S.OPEN_WAKA
            parser.startTagPosition = parser.position
          } else if (isQuote(c)) {
            parser.doctype += c
            parser.state = S.DOCTYPE_DTD_QUOTED
            parser.q = c
          } else {
            parser.doctype += c
          }
          continue

        case S.DOCTYPE_DTD_QUOTED:
          parser.doctype += c
          if (c === parser.q) {
            parser.state = S.DOCTYPE_DTD
            parser.q = ''
          }
          continue

        case S.COMMENT:
          if (c === '-') {
            parser.state = S.COMMENT_ENDING
          } else {
            parser.comment += c
          }
          continue

        case S.COMMENT_ENDING:
          if (c === '-') {
            parser.state = S.COMMENT_ENDED
            parser.comment = textopts(parser.opt, parser.comment)
            if (parser.comment) {
              emitNode(parser, 'oncomment', parser.comment)
            }
            parser.comment = ''
          } else {
            parser.comment += '-' + c
            parser.state = S.COMMENT
          }
          continue

        case S.COMMENT_ENDED:
          if (c !== '>') {
            strictFail(parser, 'Malformed comment')
            // allow <!-- blah -- bloo --> in non-strict mode,
            // which is a comment of " blah -- bloo "
            parser.comment += '--' + c
            parser.state = S.COMMENT
          } else if (parser.doctype && parser.doctype !== true) {
            parser.state = S.DOCTYPE_DTD
          } else {
            parser.state = S.TEXT
          }
          continue

        case S.CDATA:
          var starti = i - 1
          while (c && c !== ']') {
            c = charAt(chunk, i++)
            if (c && parser.trackPosition) {
              parser.position++
              if (c === '\n') {
                parser.line++
                parser.column = 0
              } else {
                parser.column++
              }
            }
          }
          parser.cdata += chunk.substring(starti, i - 1)
          if (c === ']') {
            parser.state = S.CDATA_ENDING
          }
          continue

        case S.CDATA_ENDING:
          if (c === ']') {
            parser.state = S.CDATA_ENDING_2
          } else {
            parser.cdata += ']' + c
            parser.state = S.CDATA
          }
          continue

        case S.CDATA_ENDING_2:
          if (c === '>') {
            if (parser.cdata) {
              emitNode(parser, 'oncdata', parser.cdata)
            }
            emitNode(parser, 'onclosecdata')
            parser.cdata = ''
            parser.state = S.TEXT
          } else if (c === ']') {
            parser.cdata += ']'
          } else {
            parser.cdata += ']]' + c
            parser.state = S.CDATA
          }
          continue

        case S.PROC_INST:
          if (c === '?') {
            parser.state = S.PROC_INST_ENDING
          } else if (isWhitespace(c)) {
            parser.state = S.PROC_INST_BODY
          } else {
            parser.procInstName += c
          }
          continue

        case S.PROC_INST_BODY:
          if (!parser.procInstBody && isWhitespace(c)) {
            continue
          } else if (c === '?') {
            parser.state = S.PROC_INST_ENDING
          } else {
            parser.procInstBody += c
          }
          continue

        case S.PROC_INST_ENDING:
          if (c === '>') {
            const procInstEndData = {
              name: parser.procInstName,
              body: parser.procInstBody,
            }
            validateXmlDeclarationEncoding(parser, procInstEndData)
            emitNode(parser, 'onprocessinginstruction', procInstEndData)
            parser.procInstName = parser.procInstBody = ''
            parser.state = S.TEXT
          } else {
            parser.procInstBody += '?' + c
            parser.state = S.PROC_INST_BODY
          }
          continue

        case S.OPEN_TAG:
          if (isMatch(nameBody, c)) {
            parser.tagName += c
          } else {
            newTag(parser)
            if (c === '>') {
              openTag(parser)
            } else if (c === '/') {
              parser.state = S.OPEN_TAG_SLASH
            } else {
              if (!isWhitespace(c)) {
                strictFail(parser, 'Invalid character in tag name')
              }
              parser.state = S.ATTRIB
            }
          }
          continue

        case S.OPEN_TAG_SLASH:
          if (c === '>') {
            openTag(parser, true)
            closeTag(parser)
          } else {
            strictFail(
              parser,
              'Forward-slash in opening tag not followed by >'
            )
            parser.state = S.ATTRIB
          }
          continue

        case S.ATTRIB:
          // haven't read the attribute name yet.
          if (isWhitespace(c)) {
            continue
          } else if (c === '>') {
            openTag(parser)
          } else if (c === '/') {
            parser.state = S.OPEN_TAG_SLASH
          } else if (isMatch(nameStart, c)) {
            parser.attribName = c
            parser.attribValue = ''
            parser.state = S.ATTRIB_NAME
          } else {
            strictFail(parser, 'Invalid attribute name')
          }
          continue

        case S.ATTRIB_NAME:
          if (c === '=') {
            parser.state = S.ATTRIB_VALUE
          } else if (c === '>') {
            strictFail(parser, 'Attribute without value')
            parser.attribValue = parser.attribName
            attrib(parser)
            openTag(parser)
          } else if (isWhitespace(c)) {
            parser.state = S.ATTRIB_NAME_SAW_WHITE
          } else if (isMatch(nameBody, c)) {
            parser.attribName += c
          } else {
            strictFail(parser, 'Invalid attribute name')
          }
          continue

        case S.ATTRIB_NAME_SAW_WHITE:
          if (c === '=') {
            parser.state = S.ATTRIB_VALUE
          } else if (isWhitespace(c)) {
            continue
          } else {
            strictFail(parser, 'Attribute without value')
            parser.tag.attributes[parser.attribName] = ''
            parser.attribValue = ''
            emitNode(parser, 'onattribute', {
              name: parser.attribName,
              value: '',
            })
            parser.attribName = ''
            if (c === '>') {
              openTag(parser)
            } else if (isMatch(nameStart, c)) {
              parser.attribName = c
              parser.state = S.ATTRIB_NAME
            } else {
              strictFail(parser, 'Invalid attribute name')
              parser.state = S.ATTRIB
            }
          }
          continue

        case S.ATTRIB_VALUE:
          if (isWhitespace(c)) {
            continue
          } else if (isQuote(c)) {
            parser.q = c
            parser.state = S.ATTRIB_VALUE_QUOTED
          } else {
            if (!parser.opt.unquotedAttributeValues) {
              error(parser, 'Unquoted attribute value')
            }
            parser.state = S.ATTRIB_VALUE_UNQUOTED
            parser.attribValue = c
          }
          continue

        case S.ATTRIB_VALUE_QUOTED:
          if (c !== parser.q) {
            if (c === '&') {
              parser.state = S.ATTRIB_VALUE_ENTITY_Q
            } else {
              parser.attribValue += c
            }
            continue
          }
          attrib(parser)
          parser.q = ''
          parser.state = S.ATTRIB_VALUE_CLOSED
          continue

        case S.ATTRIB_VALUE_CLOSED:
          if (isWhitespace(c)) {
            parser.state = S.ATTRIB
          } else if (c === '>') {
            openTag(parser)
          } else if (c === '/') {
            parser.state = S.OPEN_TAG_SLASH
          } else if (isMatch(nameStart, c)) {
            strictFail(parser, 'No whitespace between attributes')
            parser.attribName = c
            parser.attribValue = ''
            parser.state = S.ATTRIB_NAME
          } else {
            strictFail(parser, 'Invalid attribute name')
          }
          continue

        case S.ATTRIB_VALUE_UNQUOTED:
          if (!isAttribEnd(c)) {
            if (c === '&') {
              parser.state = S.ATTRIB_VALUE_ENTITY_U
            } else {
              parser.attribValue += c
            }
            continue
          }
          attrib(parser)
          if (c === '>') {
            openTag(parser)
          } else {
            parser.state = S.ATTRIB
          }
          continue

        case S.CLOSE_TAG:
          if (!parser.tagName) {
            if (isWhitespace(c)) {
              continue
            } else if (notMatch(nameStart, c)) {
              if (parser.script) {
                parser.script += '</' + c
                parser.state = S.SCRIPT
              } else {
                strictFail(parser, 'Invalid tagname in closing tag.')
              }
            } else {
              parser.tagName = c
            }
          } else if (c === '>') {
            closeTag(parser)
          } else if (isMatch(nameBody, c)) {
            parser.tagName += c
          } else if (parser.script) {
            parser.script += '</' + parser.tagName + c
            parser.tagName = ''
            parser.state = S.SCRIPT
          } else {
            if (!isWhitespace(c)) {
              strictFail(parser, 'Invalid tagname in closing tag')
            }
            parser.state = S.CLOSE_TAG_SAW_WHITE
          }
          continue

        case S.CLOSE_TAG_SAW_WHITE:
          if (isWhitespace(c)) {
            continue
          }
          if (c === '>') {
            closeTag(parser)
          } else {
            strictFail(parser, 'Invalid characters in closing tag')
          }
          continue

        case S.TEXT_ENTITY:
        case S.ATTRIB_VALUE_ENTITY_Q:
        case S.ATTRIB_VALUE_ENTITY_U:
          var returnState
          var buffer
          switch (parser.state) {
            case S.TEXT_ENTITY:
              returnState = S.TEXT
              buffer = 'textNode'
              break

            case S.ATTRIB_VALUE_ENTITY_Q:
              returnState = S.ATTRIB_VALUE_QUOTED
              buffer = 'attribValue'
              break

            case S.ATTRIB_VALUE_ENTITY_U:
              returnState = S.ATTRIB_VALUE_UNQUOTED
              buffer = 'attribValue'
              break
          }

          if (c === ';') {
            var parsedEntity = parseEntity(parser)
            if (
              parser.opt.unparsedEntities &&
              !Object.values(sax.XML_ENTITIES).includes(parsedEntity)
            ) {
              if ((parser.entityCount += 1) > parser.opt.maxEntityCount) {
                error(
                  parser,
                  'Parsed entity count exceeds max entity count'
                )
              }

              if ((parser.entityDepth += 1) > parser.opt.maxEntityDepth) {
                error(
                  parser,
                  'Parsed entity depth exceeds max entity depth'
                )
              }

              parser.entity = ''
              parser.state = returnState
              parser.write(parsedEntity)
              parser.entityDepth -= 1
            } else {
              parser[buffer] += parsedEntity
              parser.entity = ''
              parser.state = returnState
            }
          } else if (
            isMatch(parser.entity.length ? entityBody : entityStart, c)
          ) {
            parser.entity += c
          } else {
            strictFail(parser, 'Invalid character in entity name')
            parser[buffer] += '&' + parser.entity + c
            parser.entity = ''
            parser.state = returnState
          }

          continue

        default: /* istanbul ignore next */ {
          throw new Error(parser, 'Unknown state: ' + parser.state)
        }
      }
    } // while

    if (parser.position >= parser.bufferCheckPosition) {
      checkBufferLength(parser)
    }
    return parser
  }

  /*! http://mths.be/fromcodepoint v0.1.0 by @mathias */
  /* istanbul ignore next */
  if (!String.fromCodePoint) {
    ;(function () {
      var stringFromCharCode = String.fromCharCode
      var floor = Math.floor
      var fromCodePoint = function () {
        var MAX_SIZE = 0x4000
        var codeUnits = []
        var highSurrogate
        var lowSurrogate
        var index = -1
        var length = arguments.length
        if (!length) {
          return ''
        }
        var result = ''
        while (++index < length) {
          var codePoint = Number(arguments[index])
          if (
            !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
            codePoint < 0 || // not a valid Unicode code point
            codePoint > 0x10ffff || // not a valid Unicode code point
            floor(codePoint) !== codePoint // not an integer
          ) {
            throw RangeError('Invalid code point: ' + codePoint)
          }
          if (codePoint <= 0xffff) {
            // BMP code point
            codeUnits.push(codePoint)
          } else {
            // Astral code point; split in surrogate halves
            // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
            codePoint -= 0x10000
            highSurrogate = (codePoint >> 10) + 0xd800
            lowSurrogate = (codePoint % 0x400) + 0xdc00
            codeUnits.push(highSurrogate, lowSurrogate)
          }
          if (index + 1 === length || codeUnits.length > MAX_SIZE) {
            result += stringFromCharCode.apply(null, codeUnits)
            codeUnits.length = 0
          }
        }
        return result
      }
      /* istanbul ignore next */
      if (Object.defineProperty) {
        Object.defineProperty(String, 'fromCodePoint', {
          value: fromCodePoint,
          configurable: true,
          writable: true,
        })
      } else {
        String.fromCodePoint = fromCodePoint
      }
    })()
  }
})(typeof exports === 'undefined' ? (this.sax = {}) : exports)
MIT License

Copyright (c) 2020 Zurab Benashvili (binier) <zura.bena@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
  "name": "tiny-typed-emitter",
  "version": "2.1.0",
  "description": "Fully type-checked EventEmitter",
  "main": "lib/index",
  "repository": "https://github.com/binier/tiny-typed-emitter.git",
  "author": "Zurab Benashvili <zura.benashvili@gmail.com>",
  "license": "MIT",
  "files": [
    "lib/*"
  ],
  "devDependencies": {
    "@types/node": "^13.13.4",
    "typescript": "^3.8.3"
  }
}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypedEmitter = require("events").EventEmitter;
(The MIT License)

Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the 'Software'), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict'

exports.fromCallback = function (fn) {
  return Object.defineProperty(function () {
    if (typeof arguments[arguments.length - 1] === 'function') fn.apply(this, arguments)
    else {
      return new Promise((resolve, reject) => {
        arguments[arguments.length] = (err, res) => {
          if (err) return reject(err)
          resolve(res)
        }
        arguments.length++
        fn.apply(this, arguments)
      })
    }
  }, 'name', { value: fn.name })
}

exports.fromPromise = function (fn) {
  return Object.defineProperty(function () {
    const cb = arguments[arguments.length - 1]
    if (typeof cb !== 'function') return fn.apply(this, arguments)
    else fn.apply(this, arguments).then(r => cb(null, r), cb)
  }, 'name', { value: fn.name })
}
{
  "name": "universalify",
  "version": "0.1.2",
  "description": "Make a callback- or promise-based function support both promises and callbacks.",
  "homepage": "https://github.com/RyanZim/universalify#readme",
  "license": "MIT",
  "author": "Ryan Zimmerman <opensrc@ryanzim.com>",
  "files": [
    "index.js"
  ],
  "repository": {
    "type": "git",
    "url": "git+https://github.com/RyanZim/universalify.git"
  },
  "devDependencies": {
    "colortape": "^0.1.2",
    "coveralls": "^3.0.1",
    "nyc": "^10.2.0",
    "standard": "^10.0.1",
    "tape": "^4.6.3"
  },
  "engines": {
    "node": ">= 4.0.0"
  }
}The MIT License (MIT)

Copyright (c) 2015 Loopline Systems

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

{
  "name": "builder-util-runtime",
  "version": "9.7.0",
  "main": "out/index.js",
  "author": "Vladimir Krivosheev",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/electron-userland/electron-builder.git",
    "directory": "packages/builder-util-runtime"
  },
  "homepage": "https://github.com/electron-userland/electron-builder",
  "files": [
    "out"
  ],
  "engines": {
    "node": ">=12.0.0"
  },
  "dependencies": {
    "debug": "^4.3.4",
    "sax": "^1.2.4"
  },
  "devDependencies": {
    "@types/debug": "4.1.7",
    "@types/sax": "1.2.3"
  },
  "types": "./out/index.d.ts"
}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CancellationError = exports.CancellationToken = void 0;
const events_1 = require("events");
class CancellationToken extends events_1.EventEmitter {
    get cancelled() {
        return this._cancelled || (this._parent != null && this._parent.cancelled);
    }
    set parent(value) {
        this.removeParentCancelHandler();
        this._parent = value;
        this.parentCancelHandler = () => this.cancel();
        this._parent.onCancel(this.parentCancelHandler);
    }
    // babel cannot compile ... correctly for super calls
    constructor(parent) {
        super();
        this.parentCancelHandler = null;
        this._parent = null;
        this._cancelled = false;
        if (parent != null) {
            this.parent = parent;
        }
    }
    cancel() {
        this._cancelled = true;
        this.emit("cancel");
    }
    onCancel(handler) {
        if (this.cancelled) {
            handler();
        }
        else {
            this.once("cancel", handler);
        }
    }
    createPromise(callback) {
        if (this.cancelled) {
            return Promise.reject(new CancellationError());
        }
        const finallyHandler = () => {
            if (cancelHandler != null) {
                try {
                    this.removeListener("cancel", cancelHandler);
                    cancelHandler = null;
                }
                catch (_ignore) {
                    // ignore
                }
            }
        };
        let cancelHandler = null;
        return new Promise((resolve, reject) => {
            let addedCancelHandler = null;
            cancelHandler = () => {
                try {
                    if (addedCancelHandler != null) {
                        addedCancelHandler();
                        addedCancelHandler = null;
                    }
                }
                finally {
                    reject(new CancellationError());
                }
            };
            if (this.cancelled) {
                cancelHandler();
                return;
            }
            this.onCancel(cancelHandler);
            callback(resolve, reject, (callback) => {
                addedCancelHandler = callback;
            });
        })
            .then(it => {
            finallyHandler();
            return it;
        })
            .catch((e) => {
            finallyHandler();
            throw e;
        });
    }
    removeParentCancelHandler() {
        const parent = this._parent;
        if (parent != null && this.parentCancelHandler != null) {
            parent.removeListener("cancel", this.parentCancelHandler);
            this.parentCancelHandler = null;
        }
    }
    dispose() {
        try {
            this.removeParentCancelHandler();
        }
        finally {
            this.removeAllListeners();
            this._parent = null;
        }
    }
}
exports.CancellationToken = CancellationToken;
class CancellationError extends Error {
    constructor() {
        super("cancelled");
    }
}
exports.CancellationError = CancellationError;
//# sourceMappingURL=CancellationToken.js.map{"version":3,"file":"CancellationToken.js","sourceRoot":"","sources":["../src/CancellationToken.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"events\"\n\nexport class CancellationToken extends EventEmitter {\n  private parentCancelHandler: (() => any) | null = null\n\n  private _cancelled: boolean\n  get cancelled(): boolean {\n    return this._cancelled || (this._parent != null && this._parent.cancelled)\n  }\n\n  private _parent: CancellationToken | null = null\n  set parent(value: CancellationToken) {\n    this.removeParentCancelHandler()\n\n    this._parent = value\n    this.parentCancelHandler = () => this.cancel()\n    this._parent.onCancel(this.parentCancelHandler)\n  }\n\n  // babel cannot compile ... correctly for super calls\n  constructor(parent?: CancellationToken) {\n    super()\n\n    this._cancelled = false\n    if (parent != null) {\n      this.parent = parent\n    }\n  }\n\n  cancel() {\n    this._cancelled = true\n    this.emit(\"cancel\")\n  }\n\n  private onCancel(handler: () => any) {\n    if (this.cancelled) {\n      handler()\n    } else {\n      this.once(\"cancel\", handler)\n    }\n  }\n\n  createPromise<R>(\n    callback: (resolve: (thenableOrResult: R | PromiseLike<R>) => void, reject: (error: Error) => void, onCancel: (callback: () => void) => void) => void\n  ): Promise<R> {\n    if (this.cancelled) {\n      return Promise.reject<R>(new CancellationError())\n    }\n\n    const finallyHandler = () => {\n      if (cancelHandler != null) {\n        try {\n          this.removeListener(\"cancel\", cancelHandler)\n          cancelHandler = null\n        } catch (_ignore) {\n          // ignore\n        }\n      }\n    }\n\n    let cancelHandler: (() => void) | null = null\n    return new Promise<R>((resolve, reject) => {\n      let addedCancelHandler: (() => void) | null = null\n\n      cancelHandler = () => {\n        try {\n          if (addedCancelHandler != null) {\n            addedCancelHandler()\n            addedCancelHandler = null\n          }\n        } finally {\n          reject(new CancellationError())\n        }\n      }\n\n      if (this.cancelled) {\n        cancelHandler()\n        return\n      }\n\n      this.onCancel(cancelHandler)\n\n      callback(resolve, reject, (callback: () => void) => {\n        addedCancelHandler = callback\n      })\n    })\n      .then(it => {\n        finallyHandler()\n        return it\n      })\n      .catch((e: any) => {\n        finallyHandler()\n        throw e\n      })\n  }\n\n  private removeParentCancelHandler() {\n    const parent = this._parent\n    if (parent != null && this.parentCancelHandler != null) {\n      parent.removeListener(\"cancel\", this.parentCancelHandler)\n      this.parentCancelHandler = null\n    }\n  }\n\n  dispose() {\n    try {\n      this.removeParentCancelHandler()\n    } finally {\n      this.removeAllListeners()\n      this._parent = null\n    }\n  }\n}\n\nexport class CancellationError extends Error {\n  constructor() {\n    super(\"cancelled\")\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemoLazy = void 0;
class MemoLazy {
    constructor(selector, creator) {
        this.selector = selector;
        this.creator = creator;
        this.selected = undefined;
        this._value = undefined;
    }
    get hasValue() {
        return this._value !== undefined;
    }
    get value() {
        const selected = this.selector();
        if (this._value !== undefined && equals(this.selected, selected)) {
            // value exists and selected hasn't changed, so return the cached value
            return this._value;
        }
        this.selected = selected;
        const result = this.creator(selected);
        this.value = result;
        return result;
    }
    set value(value) {
        this._value = value;
    }
}
exports.MemoLazy = MemoLazy;
function equals(firstValue, secondValue) {
    const isFirstObject = typeof firstValue === "object" && firstValue !== null;
    const isSecondObject = typeof secondValue === "object" && secondValue !== null;
    // do a shallow comparison of objects, arrays etc.
    if (isFirstObject && isSecondObject) {
        const keys1 = Object.keys(firstValue);
        const keys2 = Object.keys(secondValue);
        return keys1.length === keys2.length && keys1.every((key) => equals(firstValue[key], secondValue[key]));
    }
    // otherwise just compare the values directly
    return firstValue === secondValue;
}
//# sourceMappingURL=MemoLazy.js.map{"version":3,"file":"MemoLazy.js","sourceRoot":"","sources":["../src/MemoLazy.ts"],"names":[],"mappings":";;;AAAA,MAAa,QAAQ;IAInB,YACU,QAAiB,EACjB,OAAoC;QADpC,aAAQ,GAAR,QAAQ,CAAS;QACjB,YAAO,GAAP,OAAO,CAA6B;QALtC,aAAQ,GAAkB,SAAS,CAAA;QACnC,WAAM,GAA2B,SAAS,CAAA;IAK/C,CAAC;IAEJ,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,CAAA;IAClC,CAAC;IAED,IAAI,KAAK;QACP,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;QAChC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;YACjE,uEAAuE;YACvE,OAAO,IAAI,CAAC,MAAM,CAAA;QACpB,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACrC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;QAEnB,OAAO,MAAM,CAAA;IACf,CAAC;IAED,IAAI,KAAK,CAAC,KAAiB;QACzB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;IACrB,CAAC;CACF;AA9BD,4BA8BC;AAED,SAAS,MAAM,CAAC,UAAe,EAAE,WAAgB;IAC/C,MAAM,aAAa,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,CAAA;IAC3E,MAAM,cAAc,GAAG,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,KAAK,IAAI,CAAA;IAE9E,kDAAkD;IAClD,IAAI,aAAa,IAAI,cAAc,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACrC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAEtC,OAAO,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAC9G,CAAC;IAED,6CAA6C;IAC7C,OAAO,UAAU,KAAK,WAAW,CAAA;AACnC,CAAC","sourcesContent":["export class MemoLazy<S, V> {\n  private selected: S | undefined = undefined\n  private _value: Promise<V> | undefined = undefined\n\n  constructor(\n    private selector: () => S,\n    private creator: (selected: S) => Promise<V>\n  ) {}\n\n  get hasValue() {\n    return this._value !== undefined\n  }\n\n  get value(): Promise<V> {\n    const selected = this.selector()\n    if (this._value !== undefined && equals(this.selected, selected)) {\n      // value exists and selected hasn't changed, so return the cached value\n      return this._value\n    }\n\n    this.selected = selected\n    const result = this.creator(selected)\n    this.value = result\n\n    return result\n  }\n\n  set value(value: Promise<V>) {\n    this._value = value\n  }\n}\n\nfunction equals(firstValue: any, secondValue: any): boolean {\n  const isFirstObject = typeof firstValue === \"object\" && firstValue !== null\n  const isSecondObject = typeof secondValue === \"object\" && secondValue !== null\n\n  // do a shallow comparison of objects, arrays etc.\n  if (isFirstObject && isSecondObject) {\n    const keys1 = Object.keys(firstValue)\n    const keys2 = Object.keys(secondValue)\n\n    return keys1.length === keys2.length && keys1.every((key: any) => equals(firstValue[key], secondValue[key]))\n  }\n\n  // otherwise just compare the values directly\n  return firstValue === secondValue\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProgressCallbackTransform = void 0;
const stream_1 = require("stream");
class ProgressCallbackTransform extends stream_1.Transform {
    constructor(total, cancellationToken, onProgress) {
        super();
        this.total = total;
        this.cancellationToken = cancellationToken;
        this.onProgress = onProgress;
        this.start = Date.now();
        this.transferred = 0;
        this.delta = 0;
        this.nextUpdate = this.start + 1000;
    }
    _transform(chunk, encoding, callback) {
        if (this.cancellationToken.cancelled) {
            callback(new Error("cancelled"), null);
            return;
        }
        this.transferred += chunk.length;
        this.delta += chunk.length;
        const now = Date.now();
        if (now >= this.nextUpdate && this.transferred !== this.total /* will be emitted on _flush */) {
            this.nextUpdate = now + 1000;
            this.onProgress({
                total: this.total,
                delta: this.delta,
                transferred: this.transferred,
                percent: (this.transferred / this.total) * 100,
                bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),
            });
            this.delta = 0;
        }
        callback(null, chunk);
    }
    _flush(callback) {
        if (this.cancellationToken.cancelled) {
            callback(new Error("cancelled"));
            return;
        }
        this.onProgress({
            total: this.total,
            delta: this.delta,
            transferred: this.total,
            percent: 100,
            bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),
        });
        this.delta = 0;
        callback(null);
    }
}
exports.ProgressCallbackTransform = ProgressCallbackTransform;
//# sourceMappingURL=ProgressCallbackTransform.js.map{"version":3,"file":"ProgressCallbackTransform.js","sourceRoot":"","sources":["../src/ProgressCallbackTransform.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAWlC,MAAa,yBAA0B,SAAQ,kBAAS;IAOtD,YACmB,KAAa,EACb,iBAAoC,EACpC,UAAuC;QAExD,KAAK,EAAE,CAAA;QAJU,UAAK,GAAL,KAAK,CAAQ;QACb,sBAAiB,GAAjB,iBAAiB,CAAmB;QACpC,eAAU,GAAV,UAAU,CAA6B;QATlD,UAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAClB,gBAAW,GAAG,CAAC,CAAA;QACf,UAAK,GAAG,CAAC,CAAA;QAET,eAAU,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IAQtC,CAAC;IAED,UAAU,CAAC,KAAU,EAAE,QAAgB,EAAE,QAAa;QACpD,IAAI,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC;YACrC,QAAQ,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAA;YACtC,OAAM;QACR,CAAC;QAED,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,MAAM,CAAA;QAChC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAA;QAE1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,KAAK,CAAC,+BAA+B,EAAE,CAAC;YAC9F,IAAI,CAAC,UAAU,GAAG,GAAG,GAAG,IAAI,CAAA;YAE5B,IAAI,CAAC,UAAU,CAAC;gBACd,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,OAAO,EAAE,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG;gBAC9C,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;aAC3E,CAAC,CAAA;YACF,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;QAChB,CAAC;QAED,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACvB,CAAC;IAED,MAAM,CAAC,QAAa;QAClB,IAAI,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC;YACrC,QAAQ,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAA;YAChC,OAAM;QACR,CAAC;QAED,IAAI,CAAC,UAAU,CAAC;YACd,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,KAAK;YACvB,OAAO,EAAE,GAAG;YACZ,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;SAClF,CAAC,CAAA;QACF,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;QAEd,QAAQ,CAAC,IAAI,CAAC,CAAA;IAChB,CAAC;CACF;AA1DD,8DA0DC","sourcesContent":["import { Transform } from \"stream\"\nimport { CancellationToken } from \"./CancellationToken\"\n\nexport interface ProgressInfo {\n  total: number\n  delta: number\n  transferred: number\n  percent: number\n  bytesPerSecond: number\n}\n\nexport class ProgressCallbackTransform extends Transform {\n  private start = Date.now()\n  private transferred = 0\n  private delta = 0\n\n  private nextUpdate = this.start + 1000\n\n  constructor(\n    private readonly total: number,\n    private readonly cancellationToken: CancellationToken,\n    private readonly onProgress: (info: ProgressInfo) => any\n  ) {\n    super()\n  }\n\n  _transform(chunk: any, encoding: string, callback: any) {\n    if (this.cancellationToken.cancelled) {\n      callback(new Error(\"cancelled\"), null)\n      return\n    }\n\n    this.transferred += chunk.length\n    this.delta += chunk.length\n\n    const now = Date.now()\n    if (now >= this.nextUpdate && this.transferred !== this.total /* will be emitted on _flush */) {\n      this.nextUpdate = now + 1000\n\n      this.onProgress({\n        total: this.total,\n        delta: this.delta,\n        transferred: this.transferred,\n        percent: (this.transferred / this.total) * 100,\n        bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),\n      })\n      this.delta = 0\n    }\n\n    callback(null, chunk)\n  }\n\n  _flush(callback: any): void {\n    if (this.cancellationToken.cancelled) {\n      callback(new Error(\"cancelled\"))\n      return\n    }\n\n    this.onProgress({\n      total: this.total,\n      delta: this.delta,\n      transferred: this.total,\n      percent: 100,\n      bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),\n    })\n    this.delta = 0\n\n    callback(null)\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=blockMapApi.js.map{"version":3,"file":"blockMapApi.js","sourceRoot":"","sources":["../src/blockMapApi.ts"],"names":[],"mappings":"","sourcesContent":["export interface FileChunks {\n  checksums: Array<string>\n  sizes: Array<number>\n}\n\nexport interface BlockMap {\n  version: \"1\" | \"2\"\n  files: Array<BlockMapFile>\n}\n\nexport interface BlockMapFile extends FileChunks {\n  name: string\n  offset: number\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.newError = newError;
function newError(message, code) {
    const error = new Error(message);
    error.code = code;
    return error;
}
//# sourceMappingURL=error.js.map{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":";;AAAA,4BAIC;AAJD,SAAgB,QAAQ,CAAC,OAAe,EAAE,IAAY;IACpD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAC/B;IAAC,KAA+B,CAAC,IAAI,GAAG,IAAI,CAAA;IAC7C,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["export function newError(message: string, code: string) {\n  const error = new Error(message)\n  ;(error as NodeJS.ErrnoException).code = code\n  return error\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DigestTransform = exports.HttpExecutor = exports.HttpError = void 0;
exports.addSensitiveRedirectHeader = addSensitiveRedirectHeader;
exports.addSensitiveFieldPattern = addSensitiveFieldPattern;
exports.createHttpError = createHttpError;
exports.parseJson = parseJson;
exports.configureRequestOptionsFromUrl = configureRequestOptionsFromUrl;
exports.configureRequestUrl = configureRequestUrl;
exports.safeGetHeader = safeGetHeader;
exports.configureRequestOptions = configureRequestOptions;
exports.isSensitiveFieldName = isSensitiveFieldName;
exports.hashSensitiveValue = hashSensitiveValue;
exports.safeStringifyJson = safeStringifyJson;
const crypto_1 = require("crypto");
const debug_1 = require("debug");
const fs_1 = require("fs");
const stream_1 = require("stream");
const url_1 = require("url");
const CancellationToken_1 = require("./CancellationToken");
const error_1 = require("./error");
const ProgressCallbackTransform_1 = require("./ProgressCallbackTransform");
const debug = (0, debug_1.default)("electron-builder");
// ── Sensitive-data registries ────────────────────────────────────────────────
// Normalise a header or field name: lowercase + strip all separators (- and _).
// Shared by both registries so lookup is always separator-agnostic.
const normalizeName = (name) => name.toLowerCase().replace(/[-_]/g, "");
// HTTP header names (normalised) stripped on cross-origin redirects.
// Stored normalised; lookup normalises the incoming key with normalizeName().
const SENSITIVE_REDIRECT_HEADERS = new Set(["authorization", "proxyauthorization", "privatetoken", "xapikey", "xauthtoken", "xaccesstoken", "xgitlabtoken", "cookie", "xcsrftoken"]);
// Substrings: a field name containing any of these (after normalization) is redacted.
const SENSITIVE_FIELD_PATTERNS = ["token", "password", "secret", "authorization", "credential", "apikey", "passphrase", "auth"];
// Suffixes: a field name ending with any of these (after normalization) is redacted.
// Intentionally greedy — "publicKey" is also stripped; over-stripping debug logs is
// acceptable, under-stripping a credential is not.
const SENSITIVE_FIELD_SUFFIXES = ["key"];
/**
 * Register an additional HTTP header to strip on cross-origin redirects.
 * Intended for custom publishers (e.g. GenericPublisher with a non-standard auth header).
 */
function addSensitiveRedirectHeader(header) {
    SENSITIVE_REDIRECT_HEADERS.add(normalizeName(header));
}
/**
 * Register an additional substring pattern used by {@link safeStringifyJson} to
 * identify sensitive field names. Input is normalized (lowercased, separators stripped).
 * Intended for custom publishers that store credentials under non-standard field names.
 */
function addSensitiveFieldPattern(pattern) {
    SENSITIVE_FIELD_PATTERNS.push(pattern.toLowerCase().replace(/[-_]/g, ""));
}
function createHttpError(response, description = null) {
    return new HttpError(response.statusCode || -1, `${response.statusCode} ${response.statusMessage}` +
        (description == null ? "" : "\n" + JSON.stringify(description, null, "  ")) +
        "\nHeaders: " +
        safeStringifyJson(response.headers), description);
}
const HTTP_STATUS_CODES = new Map([
    [429, "Too many requests"],
    [400, "Bad request"],
    [403, "Forbidden"],
    [404, "Not found"],
    [405, "Method not allowed"],
    [406, "Not acceptable"],
    [408, "Request timeout"],
    [413, "Request entity too large"],
    [500, "Internal server error"],
    [502, "Bad gateway"],
    [503, "Service unavailable"],
    [504, "Gateway timeout"],
    [505, "HTTP version not supported"],
]);
class HttpError extends Error {
    constructor(statusCode, message = `HTTP error: ${HTTP_STATUS_CODES.get(statusCode) || statusCode}`, description = null) {
        super(message);
        this.statusCode = statusCode;
        this.description = description;
        this.name = "HttpError";
        this.code = `HTTP_ERROR_${statusCode}`;
    }
    isServerError() {
        return this.statusCode >= 500 && this.statusCode <= 599;
    }
}
exports.HttpError = HttpError;
function parseJson(result) {
    return result.then(it => (it == null || it.length === 0 ? null : JSON.parse(it)));
}
class HttpExecutor {
    constructor() {
        this.maxRedirects = 10;
    }
    request(options, cancellationToken = new CancellationToken_1.CancellationToken(), data) {
        configureRequestOptions(options);
        const json = data == null ? undefined : JSON.stringify(data);
        const encodedData = json ? Buffer.from(json) : undefined;
        if (encodedData != null) {
            if (debug.enabled) {
                debug(safeStringifyJson(data));
            }
            const { headers, ...opts } = options;
            options = {
                method: "post",
                headers: {
                    "Content-Type": "application/json",
                    "Content-Length": encodedData.length,
                    ...headers,
                },
                ...opts,
            };
        }
        return this.doApiRequest(options, cancellationToken, it => it.end(encodedData));
    }
    doApiRequest(options, cancellationToken, requestProcessor, redirectCount = 0) {
        if (debug.enabled) {
            const { headers: _headers, auth: _auth, ...safeOptions } = options;
            debug(`Request: ${safeStringifyJson(safeOptions)}`);
        }
        return cancellationToken.createPromise((resolve, reject, onCancel) => {
            const request = this.createRequest(options, (response) => {
                try {
                    this.handleResponse(response, options, cancellationToken, resolve, reject, redirectCount, requestProcessor);
                }
                catch (e) {
                    reject(e);
                }
            });
            this.addErrorAndTimeoutHandlers(request, reject, options.timeout);
            this.addRedirectHandlers(request, options, reject, redirectCount, options => {
                this.doApiRequest(options, cancellationToken, requestProcessor, redirectCount).then(resolve).catch(reject);
            });
            requestProcessor(request, reject);
            onCancel(() => request.abort());
        });
    }
    // noinspection JSUnusedLocalSymbols
    // eslint-disable-next-line
    addRedirectHandlers(request, options, reject, redirectCount, handler) {
        // not required for NodeJS
    }
    addErrorAndTimeoutHandlers(request, reject, timeout = 60 * 1000) {
        this.addTimeOutHandler(request, reject, timeout);
        request.on("error", reject);
        request.on("aborted", () => {
            reject(new Error("Request has been aborted by the server"));
        });
    }
    handleResponse(response, options, cancellationToken, resolve, reject, redirectCount, requestProcessor) {
        var _a;
        if (debug.enabled) {
            const { headers: _headers, auth: _auth, ...safeOptions } = options;
            debug(`Response: ${response.statusCode} ${response.statusMessage}, request options: ${safeStringifyJson(safeOptions)}`);
        }
        // we handle any other >= 400 error on request end (read detailed message in the response body)
        if (response.statusCode === 404) {
            // error is clear, we don't need to read detailed error description
            reject(createHttpError(response, `method: ${options.method || "GET"} url: ${options.protocol || "https:"}//${options.hostname}${options.port ? `:${options.port}` : ""}${options.path}

Please double check that your authentication token is correct. Due to security reasons, actual status maybe not reported, but 404.
`));
            return;
        }
        else if (response.statusCode === 204) {
            // on DELETE request
            resolve();
            return;
        }
        const code = (_a = response.statusCode) !== null && _a !== void 0 ? _a : 0;
        const shouldRedirect = code >= 300 && code < 400;
        const redirectUrl = safeGetHeader(response, "location");
        if (shouldRedirect && redirectUrl != null) {
            if (redirectCount > this.maxRedirects) {
                reject(this.createMaxRedirectError());
                return;
            }
            this.doApiRequest(HttpExecutor.prepareRedirectUrlOptions(redirectUrl, options), cancellationToken, requestProcessor, redirectCount).then(resolve).catch(reject);
            return;
        }
        response.setEncoding("utf8");
        let data = "";
        response.on("error", reject);
        response.on("data", (chunk) => (data += chunk));
        response.on("end", () => {
            try {
                if (response.statusCode != null && response.statusCode >= 400) {
                    const contentType = safeGetHeader(response, "content-type");
                    const isJson = contentType != null && (Array.isArray(contentType) ? contentType.find(it => it.includes("json")) != null : contentType.includes("json"));
                    reject(createHttpError(response, `method: ${options.method || "GET"} url: ${options.protocol || "https:"}//${options.hostname}${options.port ? `:${options.port}` : ""}${options.path}

          Data:
          ${isJson ? safeStringifyJson(JSON.parse(data)) : data}
          `));
                }
                else {
                    resolve(data.length === 0 ? null : data);
                }
            }
            catch (e) {
                reject(e);
            }
        });
    }
    async downloadToBuffer(url, options) {
        return await options.cancellationToken.createPromise((resolve, reject, onCancel) => {
            const responseChunks = [];
            const requestOptions = {
                headers: options.headers || undefined,
                // because PrivateGitHubProvider requires HttpExecutor.prepareRedirectUrlOptions logic, so, we need to redirect manually
                redirect: "manual",
            };
            configureRequestUrl(url, requestOptions);
            configureRequestOptions(requestOptions);
            this.doDownload(requestOptions, {
                destination: null,
                options,
                onCancel,
                callback: error => {
                    if (error == null) {
                        resolve(Buffer.concat(responseChunks));
                    }
                    else {
                        reject(error);
                    }
                },
                responseHandler: (response, callback) => {
                    let receivedLength = 0;
                    response.on("data", (chunk) => {
                        receivedLength += chunk.length;
                        if (receivedLength > 524288000) {
                            callback(new Error("Maximum allowed size is 500 MB"));
                            return;
                        }
                        responseChunks.push(chunk);
                    });
                    response.on("end", () => {
                        callback(null);
                    });
                },
            }, 0);
        });
    }
    doDownload(requestOptions, options, redirectCount) {
        const request = this.createRequest(requestOptions, (response) => {
            if (response.statusCode >= 400) {
                options.callback(new Error(`Cannot download "${requestOptions.protocol || "https:"}//${requestOptions.hostname}${requestOptions.path}", status ${response.statusCode}: ${response.statusMessage}`));
                return;
            }
            // It is possible for the response stream to fail, e.g. when a network is lost while
            // response stream is in progress. Stop waiting and reject so consumer can catch the error.
            response.on("error", options.callback);
            // this code not relevant for Electron (redirect event instead handled)
            const redirectUrl = safeGetHeader(response, "location");
            if (redirectUrl != null) {
                if (redirectCount < this.maxRedirects) {
                    this.doDownload(HttpExecutor.prepareRedirectUrlOptions(redirectUrl, requestOptions), options, redirectCount++);
                }
                else {
                    options.callback(this.createMaxRedirectError());
                }
                return;
            }
            if (options.responseHandler == null) {
                configurePipes(options, response);
            }
            else {
                options.responseHandler(response, options.callback);
            }
        });
        this.addErrorAndTimeoutHandlers(request, options.callback, requestOptions.timeout);
        this.addRedirectHandlers(request, requestOptions, options.callback, redirectCount, requestOptions => {
            this.doDownload(requestOptions, options, redirectCount++);
        });
        request.end();
    }
    createMaxRedirectError() {
        return new Error(`Too many redirects (> ${this.maxRedirects})`);
    }
    addTimeOutHandler(request, callback, timeout) {
        request.on("socket", (socket) => {
            socket.setTimeout(timeout, () => {
                request.abort();
                callback(new Error("Request timed out"));
            });
        });
    }
    static prepareRedirectUrlOptions(redirectUrl, options) {
        const newOptions = configureRequestOptionsFromUrl(redirectUrl, { ...options });
        const headers = newOptions.headers;
        if (headers == null) {
            return newOptions;
        }
        const originalUrl = HttpExecutor.reconstructOriginalUrl(options);
        const parsedRedirectUrl = parseUrl(redirectUrl, options);
        if (HttpExecutor.isCrossOriginRedirect(originalUrl, parsedRedirectUrl)) {
            if (debug.enabled) {
                debug(`Cross-origin redirect (${originalUrl.host} → ${parsedRedirectUrl.host}): stripping sensitive headers`);
            }
            for (const key of Object.keys(headers)) {
                if (SENSITIVE_REDIRECT_HEADERS.has(normalizeName(key))) {
                    delete headers[key];
                }
            }
        }
        return newOptions;
    }
    static reconstructOriginalUrl(options) {
        const protocol = options.protocol || "https:";
        if (!options.hostname) {
            throw new Error("Missing hostname in request options");
        }
        const hostname = options.hostname;
        const port = options.port ? `:${options.port}` : "";
        const path = options.path || "/";
        return new url_1.URL(`${protocol}//${hostname}${port}${path}`);
    }
    static isCrossOriginRedirect(originalUrl, redirectUrl) {
        // Case-insensitive hostname comparison
        if (originalUrl.hostname.toLowerCase() !== redirectUrl.hostname.toLowerCase()) {
            return true;
        }
        // Special case: allow http -> https redirect on same host with standard ports
        // This matches the behavior of Python requests library for backward compatibility
        // url.port returns an empty string if the port is omitted
        // or explicitly set to the default port for a given protocol.
        if (originalUrl.protocol === "http:" &&
            // This can be replaced with `!originalUrl.port`, but for the sake of clarity.
            ["80", ""].includes(originalUrl.port) &&
            redirectUrl.protocol === "https:" &&
            // This can be replaced with `!redirectUrl.port`, but for the sake of clarity.
            ["443", ""].includes(redirectUrl.port)) {
            return false;
        }
        // According to RFC 7235, a change in protocol or port constitutes a cross-origin request.
        // Forwarding authentication headers to a different origin can be a security risk.
        // For example, https://example.com:443 and http://example.com:80 are different origins.
        // We only make an exception for HTTP -> HTTPS upgrades on standard ports for backward compatibility.
        // Strip auth on any other protocol change
        if (originalUrl.protocol !== redirectUrl.protocol) {
            return true;
        }
        // Strip auth on port change (accounting for default ports)
        const originalPort = originalUrl.port;
        const redirectPort = redirectUrl.port;
        return originalPort !== redirectPort;
    }
    static async retryOnServerError(task, maxRetries = 3) {
        for (let attemptNumber = 0;; attemptNumber++) {
            try {
                return await task();
            }
            catch (e) {
                if (attemptNumber < maxRetries && ((e instanceof HttpError && e.isServerError()) || e.code === "EPIPE")) {
                    await new Promise(r => setTimeout(r, 1000 * (attemptNumber + 1)));
                    continue;
                }
                throw e;
            }
        }
    }
}
exports.HttpExecutor = HttpExecutor;
function parseUrl(url, options) {
    try {
        // Would throw exception if url is not absolute
        return new url_1.URL(url);
    }
    catch {
        // Relative URL - construct base URL from original options
        const hostname = options.hostname;
        const protocol = options.protocol || "https:";
        const port = options.port ? `:${options.port}` : "";
        const baseUrl = `${protocol}//${hostname}${port}`;
        return new url_1.URL(url, baseUrl);
    }
}
function configureRequestOptionsFromUrl(url, options) {
    const result = configureRequestOptions(options);
    const parsedUrl = parseUrl(url, options);
    configureRequestUrl(parsedUrl, result);
    return result;
}
function configureRequestUrl(url, options) {
    options.protocol = url.protocol;
    options.hostname = url.hostname;
    if (url.port) {
        options.port = url.port;
    }
    else if (options.port) {
        delete options.port;
    }
    options.path = url.pathname + url.search;
}
class DigestTransform extends stream_1.Transform {
    // noinspection JSUnusedGlobalSymbols
    get actual() {
        return this._actual;
    }
    constructor(expected, algorithm = "sha512", encoding = "base64") {
        super();
        this.expected = expected;
        this.algorithm = algorithm;
        this.encoding = encoding;
        this._actual = null;
        this.isValidateOnEnd = true;
        this.digester = (0, crypto_1.createHash)(algorithm);
    }
    // noinspection JSUnusedGlobalSymbols
    _transform(chunk, encoding, callback) {
        this.digester.update(chunk);
        callback(null, chunk);
    }
    // noinspection JSUnusedGlobalSymbols
    _flush(callback) {
        this._actual = this.digester.digest(this.encoding);
        if (this.isValidateOnEnd) {
            try {
                this.validate();
            }
            catch (e) {
                callback(e);
                return;
            }
        }
        callback(null);
    }
    validate() {
        if (this._actual == null) {
            throw (0, error_1.newError)("Not finished yet", "ERR_STREAM_NOT_FINISHED");
        }
        if (this._actual !== this.expected) {
            throw (0, error_1.newError)(`${this.algorithm} checksum mismatch, expected ${this.expected}, got ${this._actual}`, "ERR_CHECKSUM_MISMATCH");
        }
        return null;
    }
}
exports.DigestTransform = DigestTransform;
function checkSha2(sha2Header, sha2, callback) {
    if (sha2Header != null && sha2 != null && sha2Header !== sha2) {
        callback(new Error(`checksum mismatch: expected ${sha2} but got ${sha2Header} (X-Checksum-Sha2 header)`));
        return false;
    }
    return true;
}
function safeGetHeader(response, headerKey) {
    const value = response.headers[headerKey];
    if (value == null) {
        return null;
    }
    else if (Array.isArray(value)) {
        // electron API
        return value.length === 0 ? null : value[value.length - 1];
    }
    else {
        return value;
    }
}
function configurePipes(options, response) {
    if (!checkSha2(safeGetHeader(response, "X-Checksum-Sha2"), options.options.sha2, options.callback)) {
        return;
    }
    const streams = [];
    if (options.options.onProgress != null) {
        const contentLength = safeGetHeader(response, "content-length");
        if (contentLength != null) {
            streams.push(new ProgressCallbackTransform_1.ProgressCallbackTransform(parseInt(contentLength, 10), options.options.cancellationToken, options.options.onProgress));
        }
    }
    const sha512 = options.options.sha512;
    if (sha512 != null) {
        streams.push(new DigestTransform(sha512, "sha512", sha512.length === 128 && !sha512.includes("+") && !sha512.includes("Z") && !sha512.includes("=") ? "hex" : "base64"));
    }
    else if (options.options.sha2 != null) {
        streams.push(new DigestTransform(options.options.sha2, "sha256", "hex"));
    }
    const fileOut = (0, fs_1.createWriteStream)(options.destination);
    streams.push(fileOut);
    let lastStream = response;
    for (const stream of streams) {
        stream.on("error", (error) => {
            fileOut.close();
            if (!options.options.cancellationToken.cancelled) {
                options.callback(error);
            }
        });
        lastStream = lastStream.pipe(stream);
    }
    fileOut.on("finish", () => {
        ;
        fileOut.close(options.callback);
    });
}
function configureRequestOptions(options, token, method) {
    if (method != null) {
        options.method = method;
    }
    options.headers = { ...options.headers };
    const headers = options.headers;
    if (token != null) {
        ;
        headers.authorization = token.startsWith("Basic") || token.startsWith("Bearer") ? token : `token ${token}`;
    }
    if (headers["User-Agent"] == null) {
        headers["User-Agent"] = "electron-builder";
    }
    if (method == null || method === "GET" || headers["Cache-Control"] == null) {
        headers["Cache-Control"] = "no-cache";
    }
    // do not specify for node (in any case we use https module)
    if (options.protocol == null && process.versions.electron != null) {
        options.protocol = "https:";
    }
    return options;
}
function isSensitiveFieldName(name) {
    const normalized = normalizeName(name);
    return SENSITIVE_FIELD_PATTERNS.some(p => normalized.includes(p)) || SENSITIVE_FIELD_SUFFIXES.some(s => normalized.endsWith(s));
}
function hashSensitiveValue(value) {
    return `${(0, crypto_1.createHash)("sha256").update(value).digest("hex")} (sha256 hash)`;
}
function safeStringifyJson(data, skippedNames) {
    return JSON.stringify(data, (name, value) => {
        if (isSensitiveFieldName(name) || (skippedNames != null && skippedNames.has(name))) {
            return typeof value === "string" ? hashSensitiveValue(value) : "<stripped sensitive data>";
        }
        return value;
    }, 2);
}
//# sourceMappingURL=httpExecutor.js.map{"version":3,"file":"httpExecutor.js","sourceRoot":"","sources":["../src/httpExecutor.ts"],"names":[],"mappings":"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","sourcesContent":["import { BinaryToTextEncoding, createHash, Hash } from \"crypto\"\nimport _debug from \"debug\"\nimport { createWriteStream } from \"fs\"\nimport { IncomingMessage, OutgoingHttpHeader, OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { Socket } from \"net\"\nimport { Transform } from \"stream\"\nimport { URL } from \"url\"\nimport { Nullish } from \".\"\nimport { CancellationToken } from \"./CancellationToken\"\nimport { newError } from \"./error\"\nimport { ProgressCallbackTransform, ProgressInfo } from \"./ProgressCallbackTransform\"\n\nconst debug = _debug(\"electron-builder\")\n\n// ── Sensitive-data registries ────────────────────────────────────────────────\n\n// Normalise a header or field name: lowercase + strip all separators (- and _).\n// Shared by both registries so lookup is always separator-agnostic.\nconst normalizeName = (name: string): string => name.toLowerCase().replace(/[-_]/g, \"\")\n\n// HTTP header names (normalised) stripped on cross-origin redirects.\n// Stored normalised; lookup normalises the incoming key with normalizeName().\nconst SENSITIVE_REDIRECT_HEADERS = new Set([\"authorization\", \"proxyauthorization\", \"privatetoken\", \"xapikey\", \"xauthtoken\", \"xaccesstoken\", \"xgitlabtoken\", \"cookie\", \"xcsrftoken\"])\n\n// Substrings: a field name containing any of these (after normalization) is redacted.\nconst SENSITIVE_FIELD_PATTERNS: string[] = [\"token\", \"password\", \"secret\", \"authorization\", \"credential\", \"apikey\", \"passphrase\", \"auth\"] as const\n\n// Suffixes: a field name ending with any of these (after normalization) is redacted.\n// Intentionally greedy — \"publicKey\" is also stripped; over-stripping debug logs is\n// acceptable, under-stripping a credential is not.\nconst SENSITIVE_FIELD_SUFFIXES: string[] = [\"key\"] as const\n\n/**\n * Register an additional HTTP header to strip on cross-origin redirects.\n * Intended for custom publishers (e.g. GenericPublisher with a non-standard auth header).\n */\nexport function addSensitiveRedirectHeader(header: string): void {\n  SENSITIVE_REDIRECT_HEADERS.add(normalizeName(header))\n}\n\n/**\n * Register an additional substring pattern used by {@link safeStringifyJson} to\n * identify sensitive field names. Input is normalized (lowercased, separators stripped).\n * Intended for custom publishers that store credentials under non-standard field names.\n */\nexport function addSensitiveFieldPattern(pattern: string): void {\n  SENSITIVE_FIELD_PATTERNS.push(pattern.toLowerCase().replace(/[-_]/g, \"\"))\n}\n\nexport interface RequestHeaders extends OutgoingHttpHeaders {\n  [key: string]: OutgoingHttpHeader | undefined\n}\n\nexport interface DownloadOptions {\n  readonly headers?: OutgoingHttpHeaders | null\n  readonly sha2?: string | null\n  readonly sha512?: string | null\n\n  readonly cancellationToken: CancellationToken\n\n  // noinspection JSUnusedLocalSymbols\n  onProgress?: (progress: ProgressInfo) => void\n}\n\nexport function createHttpError(response: IncomingMessage, description: any | null = null) {\n  return new HttpError(\n    response.statusCode || -1,\n    `${response.statusCode} ${response.statusMessage}` +\n      (description == null ? \"\" : \"\\n\" + JSON.stringify(description, null, \"  \")) +\n      \"\\nHeaders: \" +\n      safeStringifyJson(response.headers),\n    description\n  )\n}\n\nconst HTTP_STATUS_CODES = new Map<number, string>([\n  [429, \"Too many requests\"],\n  [400, \"Bad request\"],\n  [403, \"Forbidden\"],\n  [404, \"Not found\"],\n  [405, \"Method not allowed\"],\n  [406, \"Not acceptable\"],\n  [408, \"Request timeout\"],\n  [413, \"Request entity too large\"],\n  [500, \"Internal server error\"],\n  [502, \"Bad gateway\"],\n  [503, \"Service unavailable\"],\n  [504, \"Gateway timeout\"],\n  [505, \"HTTP version not supported\"],\n])\n\nexport class HttpError extends Error {\n  constructor(\n    readonly statusCode: number,\n    message = `HTTP error: ${HTTP_STATUS_CODES.get(statusCode) || statusCode}`,\n    readonly description: any | null = null\n  ) {\n    super(message)\n\n    this.name = \"HttpError\"\n    ;(this as NodeJS.ErrnoException).code = `HTTP_ERROR_${statusCode}`\n  }\n\n  isServerError() {\n    return this.statusCode >= 500 && this.statusCode <= 599\n  }\n}\n\nexport function parseJson(result: Promise<string | null>) {\n  return result.then(it => (it == null || it.length === 0 ? null : JSON.parse(it)))\n}\n\ninterface Request {\n  abort: () => void\n  end: (data?: Buffer) => void\n}\nexport abstract class HttpExecutor<T extends Request> {\n  protected readonly maxRedirects = 10\n\n  request(options: RequestOptions, cancellationToken: CancellationToken = new CancellationToken(), data?: { [name: string]: any } | null): Promise<string | null> {\n    configureRequestOptions(options)\n    const json = data == null ? undefined : JSON.stringify(data)\n    const encodedData = json ? Buffer.from(json) : undefined\n    if (encodedData != null) {\n      if (debug.enabled) {\n        debug(safeStringifyJson(data))\n      }\n      const { headers, ...opts } = options\n      options = {\n        method: \"post\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          \"Content-Length\": encodedData.length,\n          ...headers,\n        },\n        ...opts,\n      }\n    }\n    return this.doApiRequest(options, cancellationToken, it => it.end(encodedData))\n  }\n\n  doApiRequest(\n    options: RequestOptions,\n    cancellationToken: CancellationToken,\n    requestProcessor: (request: T, reject: (error: Error) => void) => void,\n    redirectCount = 0\n  ): Promise<string> {\n    if (debug.enabled) {\n      const { headers: _headers, auth: _auth, ...safeOptions } = options as any\n      debug(`Request: ${safeStringifyJson(safeOptions)}`)\n    }\n\n    return cancellationToken.createPromise<string>((resolve, reject, onCancel) => {\n      const request = this.createRequest(options, (response: any) => {\n        try {\n          this.handleResponse(response, options, cancellationToken, resolve, reject, redirectCount, requestProcessor)\n        } catch (e: any) {\n          reject(e)\n        }\n      })\n      this.addErrorAndTimeoutHandlers(request, reject, options.timeout)\n      this.addRedirectHandlers(request, options, reject, redirectCount, options => {\n        this.doApiRequest(options, cancellationToken, requestProcessor, redirectCount).then(resolve).catch(reject)\n      })\n      requestProcessor(request, reject)\n      onCancel(() => request.abort())\n    })\n  }\n\n  // noinspection JSUnusedLocalSymbols\n  // eslint-disable-next-line\n  protected addRedirectHandlers(request: any, options: RequestOptions, reject: (error: Error) => void, redirectCount: number, handler: (options: RequestOptions) => void) {\n    // not required for NodeJS\n  }\n\n  addErrorAndTimeoutHandlers(request: any, reject: (error: Error) => void, timeout = 60 * 1000) {\n    this.addTimeOutHandler(request, reject, timeout)\n    request.on(\"error\", reject)\n    request.on(\"aborted\", () => {\n      reject(new Error(\"Request has been aborted by the server\"))\n    })\n  }\n\n  private handleResponse(\n    response: IncomingMessage,\n    options: RequestOptions,\n    cancellationToken: CancellationToken,\n    resolve: (data?: any) => void,\n    reject: (error: Error) => void,\n    redirectCount: number,\n    requestProcessor: (request: T, reject: (error: Error) => void) => void\n  ) {\n    if (debug.enabled) {\n      const { headers: _headers, auth: _auth, ...safeOptions } = options as any\n      debug(`Response: ${response.statusCode} ${response.statusMessage}, request options: ${safeStringifyJson(safeOptions)}`)\n    }\n\n    // we handle any other >= 400 error on request end (read detailed message in the response body)\n    if (response.statusCode === 404) {\n      // error is clear, we don't need to read detailed error description\n      reject(\n        createHttpError(\n          response,\n          `method: ${options.method || \"GET\"} url: ${options.protocol || \"https:\"}//${options.hostname}${options.port ? `:${options.port}` : \"\"}${options.path}\n\nPlease double check that your authentication token is correct. Due to security reasons, actual status maybe not reported, but 404.\n`\n        )\n      )\n      return\n    } else if (response.statusCode === 204) {\n      // on DELETE request\n      resolve()\n      return\n    }\n\n    const code = response.statusCode ?? 0\n    const shouldRedirect = code >= 300 && code < 400\n    const redirectUrl = safeGetHeader(response, \"location\")\n    if (shouldRedirect && redirectUrl != null) {\n      if (redirectCount > this.maxRedirects) {\n        reject(this.createMaxRedirectError())\n        return\n      }\n\n      this.doApiRequest(HttpExecutor.prepareRedirectUrlOptions(redirectUrl, options), cancellationToken, requestProcessor, redirectCount).then(resolve).catch(reject)\n      return\n    }\n\n    response.setEncoding(\"utf8\")\n\n    let data = \"\"\n    response.on(\"error\", reject)\n    response.on(\"data\", (chunk: string) => (data += chunk))\n    response.on(\"end\", () => {\n      try {\n        if (response.statusCode != null && response.statusCode >= 400) {\n          const contentType = safeGetHeader(response, \"content-type\")\n          const isJson = contentType != null && (Array.isArray(contentType) ? contentType.find(it => it.includes(\"json\")) != null : contentType.includes(\"json\"))\n          reject(\n            createHttpError(\n              response,\n              `method: ${options.method || \"GET\"} url: ${options.protocol || \"https:\"}//${options.hostname}${options.port ? `:${options.port}` : \"\"}${options.path}\n\n          Data:\n          ${isJson ? safeStringifyJson(JSON.parse(data)) : data}\n          `\n            )\n          )\n        } else {\n          resolve(data.length === 0 ? null : data)\n        }\n      } catch (e: any) {\n        reject(e)\n      }\n    })\n  }\n\n  // noinspection JSUnusedLocalSymbols\n  abstract createRequest(options: RequestOptions, callback: (response: any) => void): T\n\n  async downloadToBuffer(url: URL, options: DownloadOptions): Promise<Buffer> {\n    return await options.cancellationToken.createPromise<Buffer>((resolve, reject, onCancel) => {\n      const responseChunks: Buffer[] = []\n      const requestOptions = {\n        headers: options.headers || undefined,\n        // because PrivateGitHubProvider requires HttpExecutor.prepareRedirectUrlOptions logic, so, we need to redirect manually\n        redirect: \"manual\",\n      }\n      configureRequestUrl(url, requestOptions)\n      configureRequestOptions(requestOptions)\n      this.doDownload(\n        requestOptions,\n        {\n          destination: null,\n          options,\n          onCancel,\n          callback: error => {\n            if (error == null) {\n              resolve(Buffer.concat(responseChunks))\n            } else {\n              reject(error)\n            }\n          },\n          responseHandler: (response, callback) => {\n            let receivedLength = 0\n            response.on(\"data\", (chunk: Buffer) => {\n              receivedLength += chunk.length\n              if (receivedLength > 524288000) {\n                callback(new Error(\"Maximum allowed size is 500 MB\"))\n                return\n              }\n              responseChunks.push(chunk)\n            })\n            response.on(\"end\", () => {\n              callback(null)\n            })\n          },\n        },\n        0\n      )\n    })\n  }\n\n  protected doDownload(requestOptions: RequestOptions, options: DownloadCallOptions, redirectCount: number) {\n    const request = this.createRequest(requestOptions, (response: IncomingMessage) => {\n      if (response.statusCode! >= 400) {\n        options.callback(\n          new Error(\n            `Cannot download \"${requestOptions.protocol || \"https:\"}//${requestOptions.hostname}${requestOptions.path}\", status ${response.statusCode}: ${response.statusMessage}`\n          )\n        )\n        return\n      }\n\n      // It is possible for the response stream to fail, e.g. when a network is lost while\n      // response stream is in progress. Stop waiting and reject so consumer can catch the error.\n      response.on(\"error\", options.callback)\n\n      // this code not relevant for Electron (redirect event instead handled)\n      const redirectUrl = safeGetHeader(response, \"location\")\n      if (redirectUrl != null) {\n        if (redirectCount < this.maxRedirects) {\n          this.doDownload(HttpExecutor.prepareRedirectUrlOptions(redirectUrl, requestOptions), options, redirectCount++)\n        } else {\n          options.callback(this.createMaxRedirectError())\n        }\n        return\n      }\n\n      if (options.responseHandler == null) {\n        configurePipes(options, response)\n      } else {\n        options.responseHandler(response, options.callback)\n      }\n    })\n    this.addErrorAndTimeoutHandlers(request, options.callback, requestOptions.timeout)\n    this.addRedirectHandlers(request, requestOptions, options.callback, redirectCount, requestOptions => {\n      this.doDownload(requestOptions, options, redirectCount++)\n    })\n    request.end()\n  }\n\n  protected createMaxRedirectError() {\n    return new Error(`Too many redirects (> ${this.maxRedirects})`)\n  }\n\n  private addTimeOutHandler(request: any, callback: (error: Error) => void, timeout: number) {\n    request.on(\"socket\", (socket: Socket) => {\n      socket.setTimeout(timeout, () => {\n        request.abort()\n        callback(new Error(\"Request timed out\"))\n      })\n    })\n  }\n\n  static prepareRedirectUrlOptions(redirectUrl: string, options: RequestOptions): RequestOptions {\n    const newOptions = configureRequestOptionsFromUrl(redirectUrl, { ...options })\n    const headers = newOptions.headers\n    if (headers == null) {\n      return newOptions\n    }\n\n    const originalUrl = HttpExecutor.reconstructOriginalUrl(options)\n    const parsedRedirectUrl = parseUrl(redirectUrl, options)\n\n    if (HttpExecutor.isCrossOriginRedirect(originalUrl, parsedRedirectUrl)) {\n      if (debug.enabled) {\n        debug(`Cross-origin redirect (${originalUrl.host} → ${parsedRedirectUrl.host}): stripping sensitive headers`)\n      }\n      for (const key of Object.keys(headers)) {\n        if (SENSITIVE_REDIRECT_HEADERS.has(normalizeName(key))) {\n          delete (headers as Record<string, unknown>)[key]\n        }\n      }\n    }\n    return newOptions\n  }\n\n  private static reconstructOriginalUrl(options: RequestOptions): URL {\n    const protocol = options.protocol || \"https:\"\n    if (!options.hostname) {\n      throw new Error(\"Missing hostname in request options\")\n    }\n    const hostname = options.hostname\n    const port = options.port ? `:${options.port}` : \"\"\n    const path = options.path || \"/\"\n    return new URL(`${protocol}//${hostname}${port}${path}`)\n  }\n\n  private static isCrossOriginRedirect(originalUrl: URL, redirectUrl: URL): boolean {\n    // Case-insensitive hostname comparison\n    if (originalUrl.hostname.toLowerCase() !== redirectUrl.hostname.toLowerCase()) {\n      return true\n    }\n\n    // Special case: allow http -> https redirect on same host with standard ports\n    // This matches the behavior of Python requests library for backward compatibility\n    // url.port returns an empty string if the port is omitted\n    // or explicitly set to the default port for a given protocol.\n    if (\n      originalUrl.protocol === \"http:\" &&\n      // This can be replaced with `!originalUrl.port`, but for the sake of clarity.\n      [\"80\", \"\"].includes(originalUrl.port) &&\n      redirectUrl.protocol === \"https:\" &&\n      // This can be replaced with `!redirectUrl.port`, but for the sake of clarity.\n      [\"443\", \"\"].includes(redirectUrl.port)\n    ) {\n      return false\n    }\n\n    // According to RFC 7235, a change in protocol or port constitutes a cross-origin request.\n    // Forwarding authentication headers to a different origin can be a security risk.\n    // For example, https://example.com:443 and http://example.com:80 are different origins.\n    // We only make an exception for HTTP -> HTTPS upgrades on standard ports for backward compatibility.\n\n    // Strip auth on any other protocol change\n    if (originalUrl.protocol !== redirectUrl.protocol) {\n      return true\n    }\n\n    // Strip auth on port change (accounting for default ports)\n    const originalPort = originalUrl.port\n    const redirectPort = redirectUrl.port\n    return originalPort !== redirectPort\n  }\n\n  static async retryOnServerError(task: () => Promise<any>, maxRetries = 3): Promise<any> {\n    for (let attemptNumber = 0; ; attemptNumber++) {\n      try {\n        return await task()\n      } catch (e: any) {\n        if (attemptNumber < maxRetries && ((e instanceof HttpError && e.isServerError()) || e.code === \"EPIPE\")) {\n          await new Promise(r => setTimeout(r, 1000 * (attemptNumber + 1)))\n          continue\n        }\n        throw e\n      }\n    }\n  }\n}\n\nexport interface DownloadCallOptions {\n  responseHandler: ((response: IncomingMessage, callback: (error: Error | null) => void) => void) | null\n  onCancel: (callback: () => void) => void\n  callback: (error: Error | null) => void\n\n  options: DownloadOptions\n\n  destination: string | null\n}\n\nfunction parseUrl(url: string, options: RequestOptions): URL {\n  try {\n    // Would throw exception if url is not absolute\n    return new URL(url)\n  } catch {\n    // Relative URL - construct base URL from original options\n    const hostname = options.hostname\n    const protocol = options.protocol || \"https:\"\n    const port = options.port ? `:${options.port}` : \"\"\n    const baseUrl = `${protocol}//${hostname}${port}`\n    return new URL(url, baseUrl)\n  }\n}\n\nexport function configureRequestOptionsFromUrl(url: string, options: RequestOptions) {\n  const result = configureRequestOptions(options)\n  const parsedUrl = parseUrl(url, options)\n  configureRequestUrl(parsedUrl, result)\n  return result\n}\n\nexport function configureRequestUrl(url: URL, options: RequestOptions): void {\n  options.protocol = url.protocol\n  options.hostname = url.hostname\n  if (url.port) {\n    options.port = url.port\n  } else if (options.port) {\n    delete options.port\n  }\n  options.path = url.pathname + url.search\n}\n\nexport class DigestTransform extends Transform {\n  private readonly digester: Hash\n\n  private _actual: string | null = null\n\n  // noinspection JSUnusedGlobalSymbols\n  get actual() {\n    return this._actual\n  }\n\n  isValidateOnEnd = true\n\n  constructor(\n    readonly expected: string,\n    private readonly algorithm: string = \"sha512\",\n    private readonly encoding: BinaryToTextEncoding = \"base64\"\n  ) {\n    super()\n\n    this.digester = createHash(algorithm)\n  }\n\n  // noinspection JSUnusedGlobalSymbols\n  _transform(chunk: Buffer, encoding: string, callback: any) {\n    this.digester.update(chunk)\n    callback(null, chunk)\n  }\n\n  // noinspection JSUnusedGlobalSymbols\n  _flush(callback: any): void {\n    this._actual = this.digester.digest(this.encoding)\n\n    if (this.isValidateOnEnd) {\n      try {\n        this.validate()\n      } catch (e: any) {\n        callback(e)\n        return\n      }\n    }\n\n    callback(null)\n  }\n\n  validate() {\n    if (this._actual == null) {\n      throw newError(\"Not finished yet\", \"ERR_STREAM_NOT_FINISHED\")\n    }\n\n    if (this._actual !== this.expected) {\n      throw newError(`${this.algorithm} checksum mismatch, expected ${this.expected}, got ${this._actual}`, \"ERR_CHECKSUM_MISMATCH\")\n    }\n\n    return null\n  }\n}\n\nfunction checkSha2(sha2Header: string | Nullish, sha2: string | Nullish, callback: (error: Error | null) => void): boolean {\n  if (sha2Header != null && sha2 != null && sha2Header !== sha2) {\n    callback(new Error(`checksum mismatch: expected ${sha2} but got ${sha2Header} (X-Checksum-Sha2 header)`))\n    return false\n  }\n  return true\n}\n\nexport function safeGetHeader(response: any, headerKey: string) {\n  const value = response.headers[headerKey]\n  if (value == null) {\n    return null\n  } else if (Array.isArray(value)) {\n    // electron API\n    return value.length === 0 ? null : value[value.length - 1]\n  } else {\n    return value\n  }\n}\n\nfunction configurePipes(options: DownloadCallOptions, response: IncomingMessage) {\n  if (!checkSha2(safeGetHeader(response, \"X-Checksum-Sha2\"), options.options.sha2, options.callback)) {\n    return\n  }\n\n  const streams: Array<any> = []\n  if (options.options.onProgress != null) {\n    const contentLength = safeGetHeader(response, \"content-length\")\n    if (contentLength != null) {\n      streams.push(new ProgressCallbackTransform(parseInt(contentLength, 10), options.options.cancellationToken, options.options.onProgress))\n    }\n  }\n\n  const sha512 = options.options.sha512\n  if (sha512 != null) {\n    streams.push(new DigestTransform(sha512, \"sha512\", sha512.length === 128 && !sha512.includes(\"+\") && !sha512.includes(\"Z\") && !sha512.includes(\"=\") ? \"hex\" : \"base64\"))\n  } else if (options.options.sha2 != null) {\n    streams.push(new DigestTransform(options.options.sha2, \"sha256\", \"hex\"))\n  }\n\n  const fileOut = createWriteStream(options.destination!)\n  streams.push(fileOut)\n\n  let lastStream = response\n  for (const stream of streams) {\n    stream.on(\"error\", (error: Error) => {\n      fileOut.close()\n      if (!options.options.cancellationToken.cancelled) {\n        options.callback(error)\n      }\n    })\n    lastStream = lastStream.pipe(stream)\n  }\n\n  fileOut.on(\"finish\", () => {\n    ;(fileOut.close as any)(options.callback)\n  })\n}\n\nexport function configureRequestOptions(options: RequestOptions, token?: string | null, method?: \"GET\" | \"DELETE\" | \"PUT\" | \"POST\"): RequestOptions {\n  if (method != null) {\n    options.method = method\n  }\n\n  options.headers = { ...options.headers }\n  const headers = options.headers\n\n  if (token != null) {\n    ;(headers as any).authorization = token.startsWith(\"Basic\") || token.startsWith(\"Bearer\") ? token : `token ${token}`\n  }\n  if (headers[\"User-Agent\"] == null) {\n    headers[\"User-Agent\"] = \"electron-builder\"\n  }\n\n  if (method == null || method === \"GET\" || headers[\"Cache-Control\"] == null) {\n    headers[\"Cache-Control\"] = \"no-cache\"\n  }\n\n  // do not specify for node (in any case we use https module)\n  if (options.protocol == null && (process.versions as any).electron != null) {\n    options.protocol = \"https:\"\n  }\n  return options\n}\n\nexport function isSensitiveFieldName(name: string): boolean {\n  const normalized = normalizeName(name)\n  return SENSITIVE_FIELD_PATTERNS.some(p => normalized.includes(p)) || SENSITIVE_FIELD_SUFFIXES.some(s => normalized.endsWith(s))\n}\n\nexport function hashSensitiveValue(value: string): string {\n  return `${createHash(\"sha256\").update(value).digest(\"hex\")} (sha256 hash)`\n}\n\nexport function safeStringifyJson(data: any, skippedNames?: Set<string>): string {\n  return JSON.stringify(\n    data,\n    (name, value) => {\n      if (isSensitiveFieldName(name) || (skippedNames != null && skippedNames.has(name))) {\n        return typeof value === \"string\" ? hashSensitiveValue(value) : \"<stripped sensitive data>\"\n      }\n      return value\n    },\n    2\n  )\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CURRENT_APP_PACKAGE_FILE_NAME = exports.CURRENT_APP_INSTALLER_FILE_NAME = exports.objectToArgs = exports.deepAssign = exports.asArray = exports.mapToObject = exports.isValidKey = exports.XElement = exports.parseXml = exports.UUID = exports.parseDn = exports.retry = exports.githubTagPrefix = exports.githubUrl = exports.getS3LikeProviderBaseUrl = exports.ProgressCallbackTransform = exports.MemoLazy = exports.safeStringifyJson = exports.safeGetHeader = exports.parseJson = exports.isSensitiveFieldName = exports.HttpExecutor = exports.hashSensitiveValue = exports.HttpError = exports.DigestTransform = exports.createHttpError = exports.configureRequestUrl = exports.configureRequestOptionsFromUrl = exports.configureRequestOptions = exports.newError = exports.CancellationToken = exports.CancellationError = void 0;
var CancellationToken_1 = require("./CancellationToken");
Object.defineProperty(exports, "CancellationError", { enumerable: true, get: function () { return CancellationToken_1.CancellationError; } });
Object.defineProperty(exports, "CancellationToken", { enumerable: true, get: function () { return CancellationToken_1.CancellationToken; } });
var error_1 = require("./error");
Object.defineProperty(exports, "newError", { enumerable: true, get: function () { return error_1.newError; } });
var httpExecutor_1 = require("./httpExecutor");
Object.defineProperty(exports, "configureRequestOptions", { enumerable: true, get: function () { return httpExecutor_1.configureRequestOptions; } });
Object.defineProperty(exports, "configureRequestOptionsFromUrl", { enumerable: true, get: function () { return httpExecutor_1.configureRequestOptionsFromUrl; } });
Object.defineProperty(exports, "configureRequestUrl", { enumerable: true, get: function () { return httpExecutor_1.configureRequestUrl; } });
Object.defineProperty(exports, "createHttpError", { enumerable: true, get: function () { return httpExecutor_1.createHttpError; } });
Object.defineProperty(exports, "DigestTransform", { enumerable: true, get: function () { return httpExecutor_1.DigestTransform; } });
Object.defineProperty(exports, "HttpError", { enumerable: true, get: function () { return httpExecutor_1.HttpError; } });
Object.defineProperty(exports, "hashSensitiveValue", { enumerable: true, get: function () { return httpExecutor_1.hashSensitiveValue; } });
Object.defineProperty(exports, "HttpExecutor", { enumerable: true, get: function () { return httpExecutor_1.HttpExecutor; } });
Object.defineProperty(exports, "isSensitiveFieldName", { enumerable: true, get: function () { return httpExecutor_1.isSensitiveFieldName; } });
Object.defineProperty(exports, "parseJson", { enumerable: true, get: function () { return httpExecutor_1.parseJson; } });
Object.defineProperty(exports, "safeGetHeader", { enumerable: true, get: function () { return httpExecutor_1.safeGetHeader; } });
Object.defineProperty(exports, "safeStringifyJson", { enumerable: true, get: function () { return httpExecutor_1.safeStringifyJson; } });
var MemoLazy_1 = require("./MemoLazy");
Object.defineProperty(exports, "MemoLazy", { enumerable: true, get: function () { return MemoLazy_1.MemoLazy; } });
var ProgressCallbackTransform_1 = require("./ProgressCallbackTransform");
Object.defineProperty(exports, "ProgressCallbackTransform", { enumerable: true, get: function () { return ProgressCallbackTransform_1.ProgressCallbackTransform; } });
var publishOptions_1 = require("./publishOptions");
Object.defineProperty(exports, "getS3LikeProviderBaseUrl", { enumerable: true, get: function () { return publishOptions_1.getS3LikeProviderBaseUrl; } });
Object.defineProperty(exports, "githubUrl", { enumerable: true, get: function () { return publishOptions_1.githubUrl; } });
Object.defineProperty(exports, "githubTagPrefix", { enumerable: true, get: function () { return publishOptions_1.githubTagPrefix; } });
var retry_1 = require("./retry");
Object.defineProperty(exports, "retry", { enumerable: true, get: function () { return retry_1.retry; } });
var rfc2253Parser_1 = require("./rfc2253Parser");
Object.defineProperty(exports, "parseDn", { enumerable: true, get: function () { return rfc2253Parser_1.parseDn; } });
var uuid_1 = require("./uuid");
Object.defineProperty(exports, "UUID", { enumerable: true, get: function () { return uuid_1.UUID; } });
var xml_1 = require("./xml");
Object.defineProperty(exports, "parseXml", { enumerable: true, get: function () { return xml_1.parseXml; } });
Object.defineProperty(exports, "XElement", { enumerable: true, get: function () { return xml_1.XElement; } });
var objects_1 = require("./objects");
Object.defineProperty(exports, "isValidKey", { enumerable: true, get: function () { return objects_1.isValidKey; } });
Object.defineProperty(exports, "mapToObject", { enumerable: true, get: function () { return objects_1.mapToObject; } });
Object.defineProperty(exports, "asArray", { enumerable: true, get: function () { return objects_1.asArray; } });
Object.defineProperty(exports, "deepAssign", { enumerable: true, get: function () { return objects_1.deepAssign; } });
Object.defineProperty(exports, "objectToArgs", { enumerable: true, get: function () { return objects_1.objectToArgs; } });
// nsis
exports.CURRENT_APP_INSTALLER_FILE_NAME = "installer.exe";
// nsis-web
exports.CURRENT_APP_PACKAGE_FILE_NAME = "package.7z";
//# sourceMappingURL=index.js.map{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yDAA0E;AAAjE,sHAAA,iBAAiB,OAAA;AAAE,sHAAA,iBAAiB,OAAA;AAC7C,iCAAkC;AAAzB,iGAAA,QAAQ,OAAA;AACjB,+CAeuB;AAdrB,uHAAA,uBAAuB,OAAA;AACvB,8HAAA,8BAA8B,OAAA;AAC9B,mHAAA,mBAAmB,OAAA;AACnB,+GAAA,eAAe,OAAA;AACf,+GAAA,eAAe,OAAA;AAEf,yGAAA,SAAS,OAAA;AACT,kHAAA,kBAAkB,OAAA;AAClB,4GAAA,YAAY,OAAA;AACZ,oHAAA,oBAAoB,OAAA;AACpB,yGAAA,SAAS,OAAA;AAET,6GAAA,aAAa,OAAA;AACb,iHAAA,iBAAiB,OAAA;AAEnB,uCAAqC;AAA5B,oGAAA,QAAQ,OAAA;AACjB,yEAAqF;AAA5E,sIAAA,yBAAyB,OAAA;AAClC,mDAmByB;AAbvB,0HAAA,wBAAwB,OAAA;AAExB,2GAAA,SAAS,OAAA;AACT,iHAAA,eAAe,OAAA;AAWjB,iCAA+B;AAAtB,8FAAA,KAAK,OAAA;AACd,iDAAyC;AAAhC,wGAAA,OAAO,OAAA;AAEhB,+BAA6B;AAApB,4FAAA,IAAI,OAAA;AACb,6BAA0C;AAAjC,+FAAA,QAAQ,OAAA;AAAE,+FAAA,QAAQ,OAAA;AAC3B,qCAA+F;AAAtF,qGAAA,UAAU,OAAA;AAAE,sGAAA,WAAW,OAAA;AAAE,kGAAA,OAAO,OAAA;AAAW,qGAAA,UAAU,OAAA;AAAE,uGAAA,YAAY,OAAA;AAE5E,OAAO;AACM,QAAA,+BAA+B,GAAG,eAAe,CAAA;AAC9D,WAAW;AACE,QAAA,6BAA6B,GAAG,YAAY,CAAA","sourcesContent":["export { BlockMap } from \"./blockMapApi\"\nexport { CancellationError, CancellationToken } from \"./CancellationToken\"\nexport { newError } from \"./error\"\nexport {\n  configureRequestOptions,\n  configureRequestOptionsFromUrl,\n  configureRequestUrl,\n  createHttpError,\n  DigestTransform,\n  DownloadOptions,\n  HttpError,\n  hashSensitiveValue,\n  HttpExecutor,\n  isSensitiveFieldName,\n  parseJson,\n  RequestHeaders,\n  safeGetHeader,\n  safeStringifyJson,\n} from \"./httpExecutor\"\nexport { MemoLazy } from \"./MemoLazy\"\nexport { ProgressCallbackTransform, ProgressInfo } from \"./ProgressCallbackTransform\"\nexport {\n  AllPublishOptions,\n  BaseS3Options,\n  BitbucketOptions,\n  CustomPublishOptions,\n  GenericServerOptions,\n  getS3LikeProviderBaseUrl,\n  GithubOptions,\n  githubUrl,\n  githubTagPrefix,\n  GitlabOptions,\n  KeygenOptions,\n  PublishConfiguration,\n  PublishProvider,\n  S3Options,\n  SnapStoreOptions,\n  SpacesOptions,\n  GitlabReleaseInfo,\n  GitlabReleaseAsset,\n} from \"./publishOptions\"\nexport { retry } from \"./retry\"\nexport { parseDn } from \"./rfc2253Parser\"\nexport { BlockMapDataHolder, PackageFileInfo, ReleaseNoteInfo, UpdateFileInfo, UpdateInfo, WindowsUpdateInfo } from \"./updateInfo\"\nexport { UUID } from \"./uuid\"\nexport { parseXml, XElement } from \"./xml\"\nexport { isValidKey, mapToObject, asArray, Nullish, deepAssign, objectToArgs } from \"./objects\"\n\n// nsis\nexport const CURRENT_APP_INSTALLER_FILE_NAME = \"installer.exe\"\n// nsis-web\nexport const CURRENT_APP_PACKAGE_FILE_NAME = \"package.7z\"\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mapToObject = mapToObject;
exports.isValidKey = isValidKey;
exports.asArray = asArray;
exports.deepAssign = deepAssign;
exports.objectToArgs = objectToArgs;
function mapToObject(map) {
    const obj = {};
    for (const [key, value] of map) {
        if (!isValidKey(key)) {
            continue;
        }
        if (value instanceof Map) {
            obj[key] = mapToObject(value);
        }
        else {
            obj[key] = value;
        }
    }
    return obj;
}
function isValidKey(key) {
    const protectedProperties = ["__proto__", "prototype", "constructor"];
    if (protectedProperties.includes(key)) {
        return false;
    }
    return ["string", "number", "symbol", "boolean"].includes(typeof key) || key === null;
}
function asArray(v) {
    if (v == null) {
        return [];
    }
    else if (Array.isArray(v)) {
        return v;
    }
    else {
        return [v];
    }
}
function isObject(x) {
    if (Array.isArray(x)) {
        return false;
    }
    const type = typeof x;
    return type === "object" || type === "function";
}
function assignKey(target, from, key) {
    const value = from[key];
    // https://github.com/electron-userland/electron-builder/pull/562
    if (value === undefined) {
        return;
    }
    const prevValue = target[key];
    if (prevValue == null || value == null || !isObject(prevValue) || !isObject(value)) {
        // Merge arrays.
        if (Array.isArray(prevValue) && Array.isArray(value)) {
            target[key] = Array.from(new Set(prevValue.concat(value)));
        }
        else {
            target[key] = value;
        }
    }
    else {
        target[key] = assign(prevValue, value);
    }
}
function assign(to, from) {
    if (to !== from) {
        for (const key of Object.getOwnPropertyNames(from)) {
            if (isValidKey(key)) {
                assignKey(to, from, key);
            }
        }
    }
    return to;
}
function deepAssign(target, ...objects) {
    for (const o of objects) {
        if (o != null) {
            assign(target, o);
        }
    }
    return target;
}
// Flag names must be letters/digits/hyphens only (e.g. "maintainer", "deb-priority").
// Anything else could inject extra flags into the argument array.
const SAFE_FLAG_NAME_RE = /^[a-zA-Z][a-zA-Z0-9-]*$/;
// Null bytes truncate arguments at the C layer; newlines can split arguments in some parsers.
const UNSAFE_VALUE_RE = /[\0\r\n]/;
function objectToArgs(obj) {
    const args = Object.entries(obj).reduce((args, [name, value]) => {
        if (!isValidKey(name) || value == null) {
            return args;
        }
        if (!SAFE_FLAG_NAME_RE.test(name)) {
            throw new Error(`objectToArgs: unsafe flag name rejected: ${JSON.stringify(name)}`);
        }
        if (UNSAFE_VALUE_RE.test(value)) {
            throw new Error(`objectToArgs: value for --${name} contains a null byte or newline`);
        }
        return args.concat([`--${name}`, value]);
    }, []);
    return Object.freeze(args);
}
//# sourceMappingURL=objects.js.map{"version":3,"file":"objects.js","sourceRoot":"","sources":["../src/objects.ts"],"names":[],"mappings":"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","sourcesContent":["export type Nullish = null | undefined\n\ntype RecursiveMap = Map<any, RecursiveMap | any>\n\nexport function mapToObject(map: RecursiveMap) {\n  const obj: any = {}\n  for (const [key, value] of map) {\n    if (!isValidKey(key)) {\n      continue\n    }\n    if (value instanceof Map) {\n      obj[key] = mapToObject(value)\n    } else {\n      obj[key] = value\n    }\n  }\n  return obj\n}\n\nexport function isValidKey(key: any) {\n  const protectedProperties = [\"__proto__\", \"prototype\", \"constructor\"]\n  if (protectedProperties.includes(key)) {\n    return false\n  }\n  return [\"string\", \"number\", \"symbol\", \"boolean\"].includes(typeof key) || key === null\n}\n\nexport function asArray<T>(v: Nullish | T | Array<T>): Array<T> {\n  if (v == null) {\n    return []\n  } else if (Array.isArray(v)) {\n    return v\n  } else {\n    return [v]\n  }\n}\n\nfunction isObject(x: any) {\n  if (Array.isArray(x)) {\n    return false\n  }\n\n  const type = typeof x\n  return type === \"object\" || type === \"function\"\n}\n\nfunction assignKey(target: any, from: any, key: string) {\n  const value = from[key]\n  // https://github.com/electron-userland/electron-builder/pull/562\n  if (value === undefined) {\n    return\n  }\n\n  const prevValue = target[key]\n  if (prevValue == null || value == null || !isObject(prevValue) || !isObject(value)) {\n    // Merge arrays.\n    if (Array.isArray(prevValue) && Array.isArray(value)) {\n      target[key] = Array.from(new Set(prevValue.concat(value)))\n    } else {\n      target[key] = value\n    }\n  } else {\n    target[key] = assign(prevValue, value)\n  }\n}\n\nfunction assign(to: any, from: any) {\n  if (to !== from) {\n    for (const key of Object.getOwnPropertyNames(from)) {\n      if (isValidKey(key)) {\n        assignKey(to, from, key)\n      }\n    }\n  }\n  return to\n}\n\nexport function deepAssign<T>(target: T, ...objects: Array<any>): T {\n  for (const o of objects) {\n    if (o != null) {\n      assign(target, o)\n    }\n  }\n  return target\n}\n\n// Flag names must be letters/digits/hyphens only (e.g. \"maintainer\", \"deb-priority\").\n// Anything else could inject extra flags into the argument array.\nconst SAFE_FLAG_NAME_RE = /^[a-zA-Z][a-zA-Z0-9-]*$/\n\n// Null bytes truncate arguments at the C layer; newlines can split arguments in some parsers.\nconst UNSAFE_VALUE_RE = /[\\0\\r\\n]/\n\nexport function objectToArgs(obj: Record<string, string | null>): readonly string[] {\n  const args = Object.entries(obj).reduce<string[]>((args, [name, value]) => {\n    if (!isValidKey(name) || value == null) {\n      return args\n    }\n    if (!SAFE_FLAG_NAME_RE.test(name)) {\n      throw new Error(`objectToArgs: unsafe flag name rejected: ${JSON.stringify(name)}`)\n    }\n    if (UNSAFE_VALUE_RE.test(value)) {\n      throw new Error(`objectToArgs: value for --${name} contains a null byte or newline`)\n    }\n    return args.concat([`--${name}`, value])\n  }, [])\n  return Object.freeze(args)\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.githubUrl = githubUrl;
exports.githubTagPrefix = githubTagPrefix;
exports.getS3LikeProviderBaseUrl = getS3LikeProviderBaseUrl;
/** @private */
function githubUrl(options, defaultHost = "github.com") {
    return `${options.protocol || "https"}://${options.host || defaultHost}`;
}
function githubTagPrefix(options) {
    var _a;
    if (options.tagNamePrefix) {
        return options.tagNamePrefix;
    }
    if ((_a = options.vPrefixedTagName) !== null && _a !== void 0 ? _a : true) {
        return "v";
    }
    return "";
}
function getS3LikeProviderBaseUrl(configuration) {
    const provider = configuration.provider;
    if (provider === "s3") {
        return s3Url(configuration);
    }
    if (provider === "spaces") {
        return spacesUrl(configuration);
    }
    throw new Error(`Not supported provider: ${provider}`);
}
function s3Url(options) {
    let url;
    if (options.accelerate == true) {
        url = `https://${options.bucket}.s3-accelerate.amazonaws.com`;
    }
    else if (options.endpoint != null) {
        url = `${options.endpoint}/${options.bucket}`;
    }
    else if (options.bucket.includes(".")) {
        if (options.region == null) {
            throw new Error(`Bucket name "${options.bucket}" includes a dot, but S3 region is missing`);
        }
        // special case, see http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro
        if (options.region === "us-east-1") {
            url = `https://s3.amazonaws.com/${options.bucket}`;
        }
        else {
            url = `https://s3-${options.region}.amazonaws.com/${options.bucket}`;
        }
    }
    else if (options.region === "cn-north-1") {
        url = `https://${options.bucket}.s3.${options.region}.amazonaws.com.cn`;
    }
    else {
        url = `https://${options.bucket}.s3.amazonaws.com`;
    }
    return appendPath(url, options.path);
}
function appendPath(url, p) {
    if (p != null && p.length > 0) {
        if (!p.startsWith("/")) {
            url += "/";
        }
        url += p;
    }
    return url;
}
function spacesUrl(options) {
    if (options.name == null) {
        throw new Error(`name is missing`);
    }
    if (options.region == null) {
        throw new Error(`region is missing`);
    }
    return appendPath(`https://${options.name}.${options.region}.digitaloceanspaces.com`, options.path);
}
//# sourceMappingURL=publishOptions.js.map{"version":3,"file":"publishOptions.js","sourceRoot":"","sources":["../src/publishOptions.ts"],"names":[],"mappings":"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","sourcesContent":["import { OutgoingHttpHeaders } from \"http\"\nimport { Nullish } from \".\"\n\nexport type PublishProvider = \"github\" | \"gitlab\" | \"s3\" | \"spaces\" | \"generic\" | \"custom\" | \"snapStore\" | \"keygen\" | \"bitbucket\"\n\n// typescript-json-schema generates only PublishConfiguration if it is specified in the list, so, it is not added here\nexport type AllPublishOptions =\n  | string\n  | GithubOptions\n  | GitlabOptions\n  | S3Options\n  | SpacesOptions\n  | GenericServerOptions\n  | CustomPublishOptions\n  | KeygenOptions\n  | SnapStoreOptions\n  | BitbucketOptions\n\nexport interface PublishConfiguration {\n  /**\n   * The provider.\n   */\n  readonly provider: PublishProvider\n\n  /**\n   * @private\n   * win-only\n   */\n  publisherName?: Array<string> | null\n\n  /**\n   * @private\n   * win-only\n   */\n  readonly updaterCacheDirName?: string | null\n\n  /**\n   * Whether to publish auto update info files.\n   *\n   * Auto update relies only on the first provider in the list (you can specify several publishers).\n   * Thus, probably, there`s no need to upload the metadata files for the other configured providers. But by default will be uploaded.\n   *\n   * @default true\n   */\n  readonly publishAutoUpdate?: boolean\n\n  /**\n   * Any custom request headers\n   */\n  readonly requestHeaders?: OutgoingHttpHeaders\n\n  /**\n   * Request timeout in milliseconds. (Default is 2 minutes; O is ignored)\n   *\n   * @default 120000\n   */\n  readonly timeout?: number | null\n}\n\n// https://github.com/electron-userland/electron-builder/issues/3261\nexport interface CustomPublishOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `custom`.\n   */\n  readonly provider: \"custom\"\n\n  /**\n   * The Provider to provide UpdateInfo regarding available updates.  Required\n   * to use custom providers with electron-updater.\n   */\n  updateProvider?: new (options: CustomPublishOptions, updater: any, runtimeOptions: any) => any\n\n  [index: string]: any\n}\n\n/**\n * [GitHub](https://help.github.com/articles/about-releases/) options.\n *\n * GitHub [personal access token](https://help.github.com/articles/creating-an-access-token-for-command-line-use/) is required. You can generate by going to [https://github.com/settings/tokens/new](https://github.com/settings/tokens/new). The access token should have the repo scope/permission.\n * Define `GH_TOKEN` environment variable.\n */\nexport interface GithubOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `github`.\n   */\n  readonly provider: \"github\"\n\n  /**\n   * The repository name. [Detected automatically](#github-repository-and-bintray-package).\n   */\n  readonly repo?: string | null\n\n  /**\n   * The owner.\n   */\n  readonly owner?: string | null\n\n  /**\n   * Whether to use `v`-prefixed tag name.\n   * @default true\n   * @deprecated please use #tagNamePrefix instead.\n   */\n  readonly vPrefixedTagName?: boolean\n\n  /**\n   * If defined, sets the prefix of the tag name that comes before the semver number.\n   * e.g. \"v\" in \"v1.2.3\" or \"test\" of \"test1.2.3\".\n   * Overrides `vPrefixedTagName`\n   */\n  readonly tagNamePrefix?: string\n\n  /**\n   * The host (including the port if need).\n   * @default github.com\n   */\n  readonly host?: string | null\n\n  /**\n   * The protocol. GitHub Publisher supports only `https`.\n   * @default https\n   */\n  readonly protocol?: \"https\" | \"http\" | null\n\n  /**\n   * The access token to support auto-update from private github repositories. Never specify it in the configuration files. Only for [setFeedURL](https://www.electron.build/auto-update#appupdatersetfeedurloptions).\n   */\n  readonly token?: string | null\n\n  /**\n   * Whether to use private github auto-update provider if `GH_TOKEN` environment variable is defined. See [Private GitHub Update Repo](https://www.electron.build/auto-update#private-github-update-repo).\n   */\n  readonly private?: boolean | null\n\n  /**\n   * The channel.\n   * @default latest\n   */\n  readonly channel?: string | null\n\n  /**\n   * The type of release. By default `draft` release will be created.\n   *\n   * Also you can set release type using environment variable. If `EP_DRAFT`is set to `true` — `draft`, if `EP_PRE_RELEASE`is set to `true` — `prerelease`.\n   * @default draft\n   */\n  releaseType?: \"draft\" | \"prerelease\" | \"release\" | null\n}\n\n/** @private */\nexport function githubUrl(options: GithubOptions, defaultHost = \"github.com\") {\n  return `${options.protocol || \"https\"}://${options.host || defaultHost}`\n}\n\nexport function githubTagPrefix(options: GithubOptions) {\n  if (options.tagNamePrefix) {\n    return options.tagNamePrefix\n  }\n  if (options.vPrefixedTagName ?? true) {\n    return \"v\"\n  }\n  return \"\"\n}\n\n/**\n * [GitLab](https://docs.gitlab.com/ee/user/project/releases/) options.\n *\n * GitLab [personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) is required for private repositories. You can generate one by going to your GitLab profile settings.\n * Define `GITLAB_TOKEN` environment variable.\n */\nexport interface GitlabOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `gitlab`.\n   */\n  readonly provider: \"gitlab\"\n\n  /**\n   * The GitLab project ID or path (e.g., \"12345678\" or \"namespace/project\").\n   */\n  readonly projectId?: string | number | null\n\n  /**\n   * The GitLab host (including the port if need).\n   * @default gitlab.com\n   */\n  readonly host?: string | null\n\n  /**\n   * The access token to support auto-update from private GitLab repositories. Never specify it in the configuration files.\n   */\n  readonly token?: string | null\n\n  /**\n   * Whether to use `v`-prefixed tag name.\n   * @default true\n   */\n  readonly vPrefixedTagName?: boolean\n\n  /**\n   * The channel.\n   * @default latest\n   */\n  readonly channel?: string | null\n\n  /**\n   * Upload target method. Can be \"project_upload\" for GitLab project uploads or \"generic_package\" for GitLab generic packages.\n   * @default \"project_upload\"\n   */\n  readonly uploadTarget?: \"project_upload\" | \"generic_package\" | null\n}\n\n/**\n * Generic (any HTTP(S) server) options.\n * In all publish options [File Macros](https://www.electron.build/file-patterns#file-macros) are supported.\n */\nexport interface GenericServerOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `generic`.\n   */\n  readonly provider: \"generic\"\n\n  /**\n   * The base url. e.g. `https://bucket_name.s3.amazonaws.com`.\n   */\n  readonly url: string\n\n  /**\n   * The channel.\n   * @default latest\n   */\n  readonly channel?: string | null\n\n  /**\n   * Whether to use multiple range requests for differential update. Defaults to `true` if `url` doesn't contain `s3.amazonaws.com`.\n   */\n  readonly useMultipleRangeRequest?: boolean\n}\n\n/**\n * Keygen options.\n * https://keygen.sh/\n * Define `KEYGEN_TOKEN` environment variable.\n */\nexport interface KeygenOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `keygen`.\n   */\n  readonly provider: \"keygen\"\n\n  /**\n   * Keygen host for self-hosted instances\n   * @default \"api.keygen.sh\"\n   */\n  readonly host?: string\n\n  /**\n   * Keygen account's UUID\n   */\n  readonly account: string\n\n  /**\n   * Keygen product's UUID\n   */\n  readonly product: string\n\n  /**\n   * The channel.\n   * @default stable\n   */\n  readonly channel?: \"stable\" | \"rc\" | \"beta\" | \"alpha\" | \"dev\" | null\n\n  /**\n   * The target Platform. Is set programmatically explicitly during publishing.\n   */\n  readonly platform?: string | null\n}\n\n/**\n * Bitbucket options.\n * https://bitbucket.org/\n * Define `BITBUCKET_TOKEN` environment variable.\n *\n * For converting an app password to a usable token, you can utilize this\n```typescript\nconvertAppPassword(owner: string, appPassword: string) {\n  const base64encodedData = Buffer.from(`${owner}:${appPassword.trim()}`).toString(\"base64\")\n  return `Basic ${base64encodedData}`\n}\n```\n */\nexport interface BitbucketOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `bitbucket`.\n   */\n  readonly provider: \"bitbucket\"\n\n  /**\n   * Repository owner\n   */\n  readonly owner: string\n\n  /**\n   * The [app password](https://bitbucket.org/account/settings/app-passwords) to support auto-update from private bitbucket repositories.\n   */\n  readonly token?: string | null\n\n  /**\n   * The user name to support auto-update from private bitbucket repositories.\n   */\n  readonly username?: string | null\n\n  /**\n   * Repository slug/name\n   */\n  readonly slug: string\n\n  /**\n   * The channel.\n   * @default latest\n   */\n  readonly channel?: string | null\n}\n\n/**\n * [Snap Store](https://snapcraft.io/) options. To publish directly to Snapcraft, see <a href=\"https://snapcraft.io/docs/snapcraft-authentication\">Snapcraft authentication options</a> for local or CI/CD authentication options.\n */\nexport interface SnapStoreOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `snapStore`.\n   */\n  readonly provider: \"snapStore\"\n\n  /**\n   * snapcraft repo name\n   */\n  readonly repo?: string\n\n  /**\n   * The list of channels the snap would be released.\n   * @default [\"edge\"]\n   */\n  readonly channels?: string | Array<string> | null\n}\n\nexport interface BaseS3Options extends PublishConfiguration {\n  /**\n   * The update channel.\n   * @default latest\n   */\n  channel?: string | null\n\n  /**\n   * The directory path.\n   * @default /\n   */\n  readonly path?: string | null\n\n  /**\n   * The ACL. Set to `null` to not [add](https://github.com/electron-userland/electron-builder/issues/1822).\n   *\n   * @default public-read\n   */\n  readonly acl?: \"private\" | \"public-read\" | null\n}\n\n/**\n * [Amazon S3](https://aws.amazon.com/s3/) options.\n * AWS credentials are required, please see [getting your credentials](http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/getting-your-credentials.html).\n * To set credentials define `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` [environment variables](http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-environment.html) directly,\n * or use [~/.aws/credentials](http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-shared.html) file,\n * or use [~/.aws/config](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html) file. For the last method to work you will also need to define `AWS_SDK_LOAD_CONFIG=1` environment variable.\n *\n * Example configuration:\n *\n```json\n{\n  \"build\":\n    \"publish\": {\n      \"provider\": \"s3\",\n      \"bucket\": \"bucket-name\"\n    }\n  }\n}\n```\n */\nexport interface S3Options extends BaseS3Options {\n  /**\n   * The provider. Must be `s3`.\n   */\n  readonly provider: \"s3\"\n\n  /**\n   * The bucket name.\n   */\n  readonly bucket: string\n\n  /**\n   * The region. Is determined and set automatically when publishing.\n   */\n  region?: string | null\n\n  /**\n   * The ACL. Set to `null` to not [add](https://github.com/electron-userland/electron-builder/issues/1822).\n   *\n   * Please see [required permissions for the S3 provider](https://github.com/electron-userland/electron-builder/issues/1618#issuecomment-314679128).\n   *\n   * @default public-read\n   */\n  readonly acl?: \"private\" | \"public-read\" | null\n\n  /**\n   * The type of storage to use for the object.\n   * @default STANDARD\n   */\n  readonly storageClass?: \"STANDARD\" | \"REDUCED_REDUNDANCY\" | \"STANDARD_IA\" | null\n\n  /**\n   * Server-side encryption algorithm to use for the object.\n   */\n  readonly encryption?: \"AES256\" | \"aws:kms\" | null\n\n  /**\n   * The endpoint URI to send requests to. The default endpoint is built from the configured region.\n   * The endpoint should be a string like `https://{service}.{region}.amazonaws.com`.\n   */\n  readonly endpoint?: string | null\n\n  /**\n   * If set to true, this will enable the s3 accelerated endpoint\n   * These endpoints have a particular format of:\n   *  ${bucketname}.s3-accelerate.amazonaws.com\n   */\n  readonly accelerate?: boolean\n\n  /**\n   * When true, force a path-style endpoint to be used where the bucket name is part of the path.\n   * [Path-style Access](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#path-style-access)\n   */\n  readonly forcePathStyle?: boolean\n}\n\n/**\n * [DigitalOcean Spaces](https://www.digitalocean.com/community/tutorials/an-introduction-to-digitalocean-spaces) options.\n * Access key is required, define `DO_KEY_ID` and `DO_SECRET_KEY` environment variables.\n */\nexport interface SpacesOptions extends BaseS3Options {\n  /**\n   * The provider. Must be `spaces`.\n   */\n  readonly provider: \"spaces\"\n\n  /**\n   * The space name.\n   */\n  readonly name: string\n\n  /**\n   * The region (e.g. `nyc3`).\n   */\n  readonly region: string\n}\n\nexport interface GitlabReleaseInfo {\n  name: string\n  tag_name: string\n  description: string\n  created_at: string\n  released_at: string\n  upcoming_release: boolean\n  assets: GitlabReleaseAsset\n}\n\nexport interface GitlabReleaseAsset {\n  count: number\n  sources: Array<{\n    format: string\n    url: string\n  }>\n  links: Array<{\n    id: number\n    name: string\n    url: string\n    direct_asset_url: string\n    link_type: string\n  }>\n}\n\nexport function getS3LikeProviderBaseUrl(configuration: PublishConfiguration) {\n  const provider = configuration.provider\n  if (provider === \"s3\") {\n    return s3Url(configuration as S3Options)\n  }\n  if (provider === \"spaces\") {\n    return spacesUrl(configuration as SpacesOptions)\n  }\n  throw new Error(`Not supported provider: ${provider}`)\n}\n\nfunction s3Url(options: S3Options) {\n  let url: string\n  if (options.accelerate == true) {\n    url = `https://${options.bucket}.s3-accelerate.amazonaws.com`\n  } else if (options.endpoint != null) {\n    url = `${options.endpoint}/${options.bucket}`\n  } else if (options.bucket.includes(\".\")) {\n    if (options.region == null) {\n      throw new Error(`Bucket name \"${options.bucket}\" includes a dot, but S3 region is missing`)\n    }\n\n    // special case, see http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro\n    if (options.region === \"us-east-1\") {\n      url = `https://s3.amazonaws.com/${options.bucket}`\n    } else {\n      url = `https://s3-${options.region}.amazonaws.com/${options.bucket}`\n    }\n  } else if (options.region === \"cn-north-1\") {\n    url = `https://${options.bucket}.s3.${options.region}.amazonaws.com.cn`\n  } else {\n    url = `https://${options.bucket}.s3.amazonaws.com`\n  }\n  return appendPath(url, options.path)\n}\n\nfunction appendPath(url: string, p: string | Nullish): string {\n  if (p != null && p.length > 0) {\n    if (!p.startsWith(\"/\")) {\n      url += \"/\"\n    }\n    url += p\n  }\n  return url\n}\n\nfunction spacesUrl(options: SpacesOptions) {\n  if (options.name == null) {\n    throw new Error(`name is missing`)\n  }\n  if (options.region == null) {\n    throw new Error(`region is missing`)\n  }\n  return appendPath(`https://${options.name}.${options.region}.digitaloceanspaces.com`, options.path)\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.retry = retry;
const CancellationToken_1 = require("./CancellationToken");
async function retry(task, options) {
    var _a;
    const { retries: retryCount, interval, backoff = 0, attempt = 0, shouldRetry, cancellationToken = new CancellationToken_1.CancellationToken() } = options;
    try {
        return await task();
    }
    catch (error) {
        if ((await Promise.resolve((_a = shouldRetry === null || shouldRetry === void 0 ? void 0 : shouldRetry(error)) !== null && _a !== void 0 ? _a : true)) && retryCount > 0 && !cancellationToken.cancelled) {
            await new Promise(resolve => setTimeout(resolve, interval + backoff * attempt));
            return await retry(task, { ...options, retries: retryCount - 1, attempt: attempt + 1 });
        }
        else {
            throw error;
        }
    }
}
//# sourceMappingURL=retry.js.map{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":";;AAEA,sBAeC;AAjBD,2DAAuD;AAEhD,KAAK,UAAU,KAAK,CACzB,IAAsB,EACtB,OAA+K;;IAE/K,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,WAAW,EAAE,iBAAiB,GAAG,IAAI,qCAAiB,EAAE,EAAE,GAAG,OAAO,CAAA;IACrI,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,EAAE,CAAA;IACrB,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IAAI,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAG,KAAK,CAAC,mCAAI,IAAI,CAAC,CAAC,IAAI,UAAU,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC;YAC5G,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC,CAAA;YAC/E,OAAO,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,EAAE,CAAC,CAAA;QACzF,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { CancellationToken } from \"./CancellationToken\"\n\nexport async function retry<T>(\n  task: () => Promise<T>,\n  options: { retries: number; interval: number; backoff?: number; attempt?: number; cancellationToken?: CancellationToken; shouldRetry?: (e: any) => boolean | Promise<boolean> }\n): Promise<T> {\n  const { retries: retryCount, interval, backoff = 0, attempt = 0, shouldRetry, cancellationToken = new CancellationToken() } = options\n  try {\n    return await task()\n  } catch (error: any) {\n    if ((await Promise.resolve(shouldRetry?.(error) ?? true)) && retryCount > 0 && !cancellationToken.cancelled) {\n      await new Promise(resolve => setTimeout(resolve, interval + backoff * attempt))\n      return await retry(task, { ...options, retries: retryCount - 1, attempt: attempt + 1 })\n    } else {\n      throw error\n    }\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseDn = parseDn;
function parseDn(seq) {
    let quoted = false;
    let key = null;
    let token = "";
    let nextNonSpace = 0;
    seq = seq.trim();
    const result = new Map();
    for (let i = 0; i <= seq.length; i++) {
        if (i === seq.length) {
            if (key !== null) {
                result.set(key, token);
            }
            break;
        }
        const ch = seq[i];
        if (quoted) {
            if (ch === '"') {
                quoted = false;
                continue;
            }
        }
        else {
            if (ch === '"') {
                quoted = true;
                continue;
            }
            if (ch === "\\") {
                i++;
                const ord = parseInt(seq.slice(i, i + 2), 16);
                if (Number.isNaN(ord)) {
                    token += seq[i];
                }
                else {
                    i++;
                    token += String.fromCharCode(ord);
                }
                continue;
            }
            if (key === null && ch === "=") {
                key = token;
                token = "";
                continue;
            }
            if (ch === "," || ch === ";" || ch === "+") {
                if (key !== null) {
                    result.set(key, token);
                }
                key = null;
                token = "";
                continue;
            }
        }
        if (ch === " " && !quoted) {
            if (token.length === 0) {
                continue;
            }
            if (i > nextNonSpace) {
                let j = i;
                while (seq[j] === " ") {
                    j++;
                }
                nextNonSpace = j;
            }
            if (nextNonSpace >= seq.length ||
                seq[nextNonSpace] === "," ||
                seq[nextNonSpace] === ";" ||
                (key === null && seq[nextNonSpace] === "=") ||
                (key !== null && seq[nextNonSpace] === "+")) {
                i = nextNonSpace - 1;
                continue;
            }
        }
        token += ch;
    }
    return result;
}
//# sourceMappingURL=rfc2253Parser.js.map{"version":3,"file":"rfc2253Parser.js","sourceRoot":"","sources":["../src/rfc2253Parser.ts"],"names":[],"mappings":"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","sourcesContent":["export function parseDn(seq: string): Map<string, string> {\n  let quoted = false\n  let key: string | null = null\n  let token = \"\"\n  let nextNonSpace = 0\n\n  seq = seq.trim()\n  const result = new Map<string, string>()\n  for (let i = 0; i <= seq.length; i++) {\n    if (i === seq.length) {\n      if (key !== null) {\n        result.set(key, token)\n      }\n      break\n    }\n\n    const ch = seq[i]\n    if (quoted) {\n      if (ch === '\"') {\n        quoted = false\n        continue\n      }\n    } else {\n      if (ch === '\"') {\n        quoted = true\n        continue\n      }\n\n      if (ch === \"\\\\\") {\n        i++\n        const ord = parseInt(seq.slice(i, i + 2), 16)\n        if (Number.isNaN(ord)) {\n          token += seq[i]\n        } else {\n          i++\n          token += String.fromCharCode(ord)\n        }\n        continue\n      }\n\n      if (key === null && ch === \"=\") {\n        key = token\n        token = \"\"\n        continue\n      }\n\n      if (ch === \",\" || ch === \";\" || ch === \"+\") {\n        if (key !== null) {\n          result.set(key, token)\n        }\n        key = null\n        token = \"\"\n        continue\n      }\n    }\n\n    if (ch === \" \" && !quoted) {\n      if (token.length === 0) {\n        continue\n      }\n\n      if (i > nextNonSpace) {\n        let j = i\n        while (seq[j] === \" \") {\n          j++\n        }\n        nextNonSpace = j\n      }\n\n      if (\n        nextNonSpace >= seq.length ||\n        seq[nextNonSpace] === \",\" ||\n        seq[nextNonSpace] === \";\" ||\n        (key === null && seq[nextNonSpace] === \"=\") ||\n        (key !== null && seq[nextNonSpace] === \"+\")\n      ) {\n        i = nextNonSpace - 1\n        continue\n      }\n    }\n\n    token += ch\n  }\n\n  return result\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=updateInfo.js.map{"version":3,"file":"updateInfo.js","sourceRoot":"","sources":["../src/updateInfo.ts"],"names":[],"mappings":"","sourcesContent":["export interface ReleaseNoteInfo {\n  /**\n   * The version.\n   */\n  readonly version: string\n\n  /**\n   * The note.\n   */\n  readonly note: string | null\n}\n\nexport interface BlockMapDataHolder {\n  /**\n   * The file size. Used to verify downloaded size (save one HTTP request to get length).\n   * Also used when block map data is embedded into the file (appimage, windows web installer package).\n   */\n  size?: number\n\n  /**\n   * The block map file size. Used when block map data is embedded into the file (appimage, windows web installer package).\n   * This information can be obtained from the file itself, but it requires additional HTTP request,\n   * so, to reduce request count, block map size is specified in the update metadata too.\n   */\n  blockMapSize?: number\n\n  /**\n   * The file checksum.\n   */\n  readonly sha512: string\n\n  readonly isAdminRightsRequired?: boolean\n}\n\nexport interface PackageFileInfo extends BlockMapDataHolder {\n  readonly path: string\n}\n\nexport interface UpdateFileInfo extends BlockMapDataHolder {\n  url: string\n}\n\nexport interface UpdateInfo {\n  /**\n   * The version.\n   */\n  readonly version: string\n\n  readonly files: Array<UpdateFileInfo>\n\n  /** @deprecated */\n  readonly path: string\n\n  /** @deprecated */\n  readonly sha512: string\n\n  /**\n   * The release name.\n   */\n  releaseName?: string | null\n\n  /**\n   * The release notes. List if `updater.fullChangelog` is set to `true`, `string` otherwise.\n   */\n  releaseNotes?: string | Array<ReleaseNoteInfo> | null\n\n  /**\n   * The release date.\n   */\n  releaseDate: string\n\n  /**\n   * The [staged rollout](https://www.electron.build/auto-update#staged-rollouts) percentage, 0-100.\n   */\n  readonly stagingPercentage?: number\n\n  /**\n   * The minimum version of system required for the app to run. Sample value: macOS `23.1.0`, Windows `10.0.22631`.\n   * Same with os.release() value, this is a kernel version.\n   */\n  readonly minimumSystemVersion?: string\n}\n\nexport interface WindowsUpdateInfo extends UpdateInfo {\n  packages?: { [arch: string]: PackageFileInfo } | null\n\n  /**\n   * @deprecated\n   * @private\n   */\n  sha2?: string\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.nil = exports.UUID = void 0;
const crypto_1 = require("crypto");
const error_1 = require("./error");
const invalidName = "options.name must be either a string or a Buffer";
// Node ID according to rfc4122#section-4.5
const randomHost = (0, crypto_1.randomBytes)(16);
randomHost[0] = randomHost[0] | 0x01;
// lookup table hex to byte
const hex2byte = {};
// lookup table byte to hex
const byte2hex = [];
// populate lookup tables
for (let i = 0; i < 256; i++) {
    const hex = (i + 0x100).toString(16).substr(1);
    hex2byte[hex] = i;
    byte2hex[i] = hex;
}
// UUID class
class UUID {
    constructor(uuid) {
        this.ascii = null;
        this.binary = null;
        const check = UUID.check(uuid);
        if (!check) {
            throw new Error("not a UUID");
        }
        this.version = check.version;
        if (check.format === "ascii") {
            this.ascii = uuid;
        }
        else {
            this.binary = uuid;
        }
    }
    static v5(name, namespace) {
        return uuidNamed(name, "sha1", 0x50, namespace);
    }
    toString() {
        if (this.ascii == null) {
            this.ascii = stringify(this.binary);
        }
        return this.ascii;
    }
    inspect() {
        return `UUID v${this.version} ${this.toString()}`;
    }
    static check(uuid, offset = 0) {
        if (typeof uuid === "string") {
            uuid = uuid.toLowerCase();
            if (!/^[a-f0-9]{8}(-[a-f0-9]{4}){3}-([a-f0-9]{12})$/.test(uuid)) {
                return false;
            }
            if (uuid === "00000000-0000-0000-0000-000000000000") {
                return { version: undefined, variant: "nil", format: "ascii" };
            }
            return {
                version: (hex2byte[uuid[14] + uuid[15]] & 0xf0) >> 4,
                variant: getVariant((hex2byte[uuid[19] + uuid[20]] & 0xe0) >> 5),
                format: "ascii",
            };
        }
        if (Buffer.isBuffer(uuid)) {
            if (uuid.length < offset + 16) {
                return false;
            }
            let i = 0;
            for (; i < 16; i++) {
                if (uuid[offset + i] !== 0) {
                    break;
                }
            }
            if (i === 16) {
                return { version: undefined, variant: "nil", format: "binary" };
            }
            return {
                version: (uuid[offset + 6] & 0xf0) >> 4,
                variant: getVariant((uuid[offset + 8] & 0xe0) >> 5),
                format: "binary",
            };
        }
        throw (0, error_1.newError)("Unknown type of uuid", "ERR_UNKNOWN_UUID_TYPE");
    }
    // read stringified uuid into a Buffer
    static parse(input) {
        const buffer = Buffer.allocUnsafe(16);
        let j = 0;
        for (let i = 0; i < 16; i++) {
            buffer[i] = hex2byte[input[j++] + input[j++]];
            if (i === 3 || i === 5 || i === 7 || i === 9) {
                j += 1;
            }
        }
        return buffer;
    }
}
exports.UUID = UUID;
// from rfc4122#appendix-C
UUID.OID = UUID.parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8");
// according to rfc4122#section-4.1.1
function getVariant(bits) {
    switch (bits) {
        case 0:
        case 1:
        case 3:
            return "ncs";
        case 4:
        case 5:
            return "rfc4122";
        case 6:
            return "microsoft";
        default:
            return "future";
    }
}
var UuidEncoding;
(function (UuidEncoding) {
    UuidEncoding[UuidEncoding["ASCII"] = 0] = "ASCII";
    UuidEncoding[UuidEncoding["BINARY"] = 1] = "BINARY";
    UuidEncoding[UuidEncoding["OBJECT"] = 2] = "OBJECT";
})(UuidEncoding || (UuidEncoding = {}));
// v3 + v5
function uuidNamed(name, hashMethod, version, namespace, encoding = UuidEncoding.ASCII) {
    const hash = (0, crypto_1.createHash)(hashMethod);
    const nameIsNotAString = typeof name !== "string";
    if (nameIsNotAString && !Buffer.isBuffer(name)) {
        throw (0, error_1.newError)(invalidName, "ERR_INVALID_UUID_NAME");
    }
    hash.update(namespace);
    hash.update(name);
    const buffer = hash.digest();
    let result;
    switch (encoding) {
        case UuidEncoding.BINARY:
            buffer[6] = (buffer[6] & 0x0f) | version;
            buffer[8] = (buffer[8] & 0x3f) | 0x80;
            result = buffer;
            break;
        case UuidEncoding.OBJECT:
            buffer[6] = (buffer[6] & 0x0f) | version;
            buffer[8] = (buffer[8] & 0x3f) | 0x80;
            result = new UUID(buffer);
            break;
        default:
            result =
                byte2hex[buffer[0]] +
                    byte2hex[buffer[1]] +
                    byte2hex[buffer[2]] +
                    byte2hex[buffer[3]] +
                    "-" +
                    byte2hex[buffer[4]] +
                    byte2hex[buffer[5]] +
                    "-" +
                    byte2hex[(buffer[6] & 0x0f) | version] +
                    byte2hex[buffer[7]] +
                    "-" +
                    byte2hex[(buffer[8] & 0x3f) | 0x80] +
                    byte2hex[buffer[9]] +
                    "-" +
                    byte2hex[buffer[10]] +
                    byte2hex[buffer[11]] +
                    byte2hex[buffer[12]] +
                    byte2hex[buffer[13]] +
                    byte2hex[buffer[14]] +
                    byte2hex[buffer[15]];
            break;
    }
    return result;
}
function stringify(buffer) {
    return (byte2hex[buffer[0]] +
        byte2hex[buffer[1]] +
        byte2hex[buffer[2]] +
        byte2hex[buffer[3]] +
        "-" +
        byte2hex[buffer[4]] +
        byte2hex[buffer[5]] +
        "-" +
        byte2hex[buffer[6]] +
        byte2hex[buffer[7]] +
        "-" +
        byte2hex[buffer[8]] +
        byte2hex[buffer[9]] +
        "-" +
        byte2hex[buffer[10]] +
        byte2hex[buffer[11]] +
        byte2hex[buffer[12]] +
        byte2hex[buffer[13]] +
        byte2hex[buffer[14]] +
        byte2hex[buffer[15]]);
}
// according to rfc4122#section-4.1.7
exports.nil = new UUID("00000000-0000-0000-0000-000000000000");
// UUID.v4 = uuidRandom
// UUID.v4fast = uuidRandomFast
// UUID.v3 = function(options, callback) {
//     return uuidNamed("md5", 0x30, options, callback)
// }
//# sourceMappingURL=uuid.js.map{"version":3,"file":"uuid.js","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from \"crypto\"\nimport { newError } from \"./error\"\n\nconst invalidName = \"options.name must be either a string or a Buffer\"\n\n// Node ID according to rfc4122#section-4.5\nconst randomHost = randomBytes(16)\nrandomHost[0] = randomHost[0] | 0x01\n\n// lookup table hex to byte\nconst hex2byte: any = {}\n\n// lookup table byte to hex\nconst byte2hex: Array<string> = []\n// populate lookup tables\nfor (let i = 0; i < 256; i++) {\n  const hex = (i + 0x100).toString(16).substr(1)\n  hex2byte[hex] = i\n  byte2hex[i] = hex\n}\n\n// UUID class\nexport class UUID {\n  private ascii: string | null = null\n  private readonly binary: Buffer | null = null\n  private readonly version: number\n\n  // from rfc4122#appendix-C\n  static readonly OID: Buffer = UUID.parse(\"6ba7b812-9dad-11d1-80b4-00c04fd430c8\")\n\n  constructor(uuid: Buffer | string) {\n    const check = UUID.check(uuid)\n    if (!check) {\n      throw new Error(\"not a UUID\")\n    }\n\n    this.version = check.version!\n\n    if (check.format === \"ascii\") {\n      this.ascii = uuid as string\n    } else {\n      this.binary = uuid as Buffer\n    }\n  }\n\n  static v5(name: string | Buffer, namespace: Buffer) {\n    return uuidNamed(name, \"sha1\", 0x50, namespace)\n  }\n\n  toString() {\n    if (this.ascii == null) {\n      this.ascii = stringify(this.binary!)\n    }\n    return this.ascii\n  }\n\n  inspect() {\n    return `UUID v${this.version} ${this.toString()}`\n  }\n\n  static check(uuid: Buffer | string, offset = 0) {\n    if (typeof uuid === \"string\") {\n      uuid = uuid.toLowerCase()\n\n      if (!/^[a-f0-9]{8}(-[a-f0-9]{4}){3}-([a-f0-9]{12})$/.test(uuid)) {\n        return false\n      }\n\n      if (uuid === \"00000000-0000-0000-0000-000000000000\") {\n        return { version: undefined, variant: \"nil\", format: \"ascii\" }\n      }\n\n      return {\n        version: (hex2byte[uuid[14] + uuid[15]] & 0xf0) >> 4,\n        variant: getVariant((hex2byte[uuid[19] + uuid[20]] & 0xe0) >> 5),\n        format: \"ascii\",\n      }\n    }\n\n    if (Buffer.isBuffer(uuid)) {\n      if (uuid.length < offset + 16) {\n        return false\n      }\n\n      let i = 0\n      for (; i < 16; i++) {\n        if (uuid[offset + i] !== 0) {\n          break\n        }\n      }\n      if (i === 16) {\n        return { version: undefined, variant: \"nil\", format: \"binary\" }\n      }\n\n      return {\n        version: (uuid[offset + 6] & 0xf0) >> 4,\n        variant: getVariant((uuid[offset + 8] & 0xe0) >> 5),\n        format: \"binary\",\n      }\n    }\n\n    throw newError(\"Unknown type of uuid\", \"ERR_UNKNOWN_UUID_TYPE\")\n  }\n\n  // read stringified uuid into a Buffer\n  static parse(input: string): Buffer {\n    const buffer = Buffer.allocUnsafe(16)\n    let j = 0\n    for (let i = 0; i < 16; i++) {\n      buffer[i] = hex2byte[input[j++] + input[j++]]\n      if (i === 3 || i === 5 || i === 7 || i === 9) {\n        j += 1\n      }\n    }\n    return buffer\n  }\n}\n\n// according to rfc4122#section-4.1.1\nfunction getVariant(bits: number) {\n  switch (bits) {\n    case 0:\n    case 1:\n    case 3:\n      return \"ncs\"\n    case 4:\n    case 5:\n      return \"rfc4122\"\n    case 6:\n      return \"microsoft\"\n    default:\n      return \"future\"\n  }\n}\n\nenum UuidEncoding {\n  ASCII,\n  BINARY,\n  OBJECT,\n}\n\n// v3 + v5\nfunction uuidNamed(name: string | Buffer, hashMethod: string, version: number, namespace: Buffer, encoding: UuidEncoding = UuidEncoding.ASCII) {\n  const hash = createHash(hashMethod)\n\n  const nameIsNotAString = typeof name !== \"string\"\n  if (nameIsNotAString && !Buffer.isBuffer(name)) {\n    throw newError(invalidName, \"ERR_INVALID_UUID_NAME\")\n  }\n\n  hash.update(namespace)\n  hash.update(name)\n\n  const buffer = hash.digest()\n  let result: any\n  switch (encoding) {\n    case UuidEncoding.BINARY:\n      buffer[6] = (buffer[6] & 0x0f) | version\n      buffer[8] = (buffer[8] & 0x3f) | 0x80\n      result = buffer\n      break\n    case UuidEncoding.OBJECT:\n      buffer[6] = (buffer[6] & 0x0f) | version\n      buffer[8] = (buffer[8] & 0x3f) | 0x80\n      result = new UUID(buffer)\n      break\n    default:\n      result =\n        byte2hex[buffer[0]] +\n        byte2hex[buffer[1]] +\n        byte2hex[buffer[2]] +\n        byte2hex[buffer[3]] +\n        \"-\" +\n        byte2hex[buffer[4]] +\n        byte2hex[buffer[5]] +\n        \"-\" +\n        byte2hex[(buffer[6] & 0x0f) | version] +\n        byte2hex[buffer[7]] +\n        \"-\" +\n        byte2hex[(buffer[8] & 0x3f) | 0x80] +\n        byte2hex[buffer[9]] +\n        \"-\" +\n        byte2hex[buffer[10]] +\n        byte2hex[buffer[11]] +\n        byte2hex[buffer[12]] +\n        byte2hex[buffer[13]] +\n        byte2hex[buffer[14]] +\n        byte2hex[buffer[15]]\n      break\n  }\n  return result\n}\n\nfunction stringify(buffer: Buffer) {\n  return (\n    byte2hex[buffer[0]] +\n    byte2hex[buffer[1]] +\n    byte2hex[buffer[2]] +\n    byte2hex[buffer[3]] +\n    \"-\" +\n    byte2hex[buffer[4]] +\n    byte2hex[buffer[5]] +\n    \"-\" +\n    byte2hex[buffer[6]] +\n    byte2hex[buffer[7]] +\n    \"-\" +\n    byte2hex[buffer[8]] +\n    byte2hex[buffer[9]] +\n    \"-\" +\n    byte2hex[buffer[10]] +\n    byte2hex[buffer[11]] +\n    byte2hex[buffer[12]] +\n    byte2hex[buffer[13]] +\n    byte2hex[buffer[14]] +\n    byte2hex[buffer[15]]\n  )\n}\n\n// according to rfc4122#section-4.1.7\nexport const nil = new UUID(\"00000000-0000-0000-0000-000000000000\")\n\n// UUID.v4 = uuidRandom\n\n// UUID.v4fast = uuidRandomFast\n\n// UUID.v3 = function(options, callback) {\n//     return uuidNamed(\"md5\", 0x30, options, callback)\n// }\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XElement = void 0;
exports.parseXml = parseXml;
const sax = require("sax");
const error_1 = require("./error");
class XElement {
    constructor(name) {
        this.name = name;
        this.value = "";
        this.attributes = null;
        this.isCData = false;
        this.elements = null;
        if (!name) {
            throw (0, error_1.newError)("Element name cannot be empty", "ERR_XML_ELEMENT_NAME_EMPTY");
        }
        if (!isValidName(name)) {
            throw (0, error_1.newError)(`Invalid element name: ${name}`, "ERR_XML_ELEMENT_INVALID_NAME");
        }
    }
    attribute(name) {
        const result = this.attributes === null ? null : this.attributes[name];
        if (result == null) {
            throw (0, error_1.newError)(`No attribute "${name}"`, "ERR_XML_MISSED_ATTRIBUTE");
        }
        return result;
    }
    removeAttribute(name) {
        if (this.attributes !== null) {
            delete this.attributes[name];
        }
    }
    element(name, ignoreCase = false, errorIfMissed = null) {
        const result = this.elementOrNull(name, ignoreCase);
        if (result === null) {
            throw (0, error_1.newError)(errorIfMissed || `No element "${name}"`, "ERR_XML_MISSED_ELEMENT");
        }
        return result;
    }
    elementOrNull(name, ignoreCase = false) {
        if (this.elements === null) {
            return null;
        }
        for (const element of this.elements) {
            if (isNameEquals(element, name, ignoreCase)) {
                return element;
            }
        }
        return null;
    }
    getElements(name, ignoreCase = false) {
        if (this.elements === null) {
            return [];
        }
        return this.elements.filter(it => isNameEquals(it, name, ignoreCase));
    }
    elementValueOrEmpty(name, ignoreCase = false) {
        const element = this.elementOrNull(name, ignoreCase);
        return element === null ? "" : element.value;
    }
}
exports.XElement = XElement;
const NAME_REG_EXP = new RegExp(/^[A-Za-z_][:A-Za-z0-9_-]*$/i);
function isValidName(name) {
    return NAME_REG_EXP.test(name);
}
function isNameEquals(element, name, ignoreCase) {
    const elementName = element.name;
    return elementName === name || (ignoreCase === true && elementName.length === name.length && elementName.toLowerCase() === name.toLowerCase());
}
function parseXml(data) {
    let rootElement = null;
    const parser = sax.parser(true, {});
    const elements = [];
    parser.onopentag = saxElement => {
        const element = new XElement(saxElement.name);
        element.attributes = saxElement.attributes;
        if (rootElement === null) {
            rootElement = element;
        }
        else {
            const parent = elements[elements.length - 1];
            if (parent.elements == null) {
                parent.elements = [];
            }
            parent.elements.push(element);
        }
        elements.push(element);
    };
    parser.onclosetag = () => {
        elements.pop();
    };
    parser.ontext = text => {
        if (elements.length > 0) {
            elements[elements.length - 1].value = text;
        }
    };
    parser.oncdata = cdata => {
        const element = elements[elements.length - 1];
        element.value = cdata;
        element.isCData = true;
    };
    parser.onerror = err => {
        throw err;
    };
    parser.write(data);
    return rootElement;
}
//# sourceMappingURL=xml.js.map{"version":3,"file":"xml.js","sourceRoot":"","sources":["../src/xml.ts"],"names":[],"mappings":"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","sourcesContent":["import * as sax from \"sax\"\nimport { newError } from \"./error\"\n\nexport class XElement {\n  value = \"\"\n  attributes: Record<string, string> | null = null\n  isCData = false\n  elements: Array<XElement> | null = null\n\n  constructor(readonly name: string) {\n    if (!name) {\n      throw newError(\"Element name cannot be empty\", \"ERR_XML_ELEMENT_NAME_EMPTY\")\n    }\n    if (!isValidName(name)) {\n      throw newError(`Invalid element name: ${name}`, \"ERR_XML_ELEMENT_INVALID_NAME\")\n    }\n  }\n\n  attribute(name: string): string {\n    const result = this.attributes === null ? null : this.attributes[name]\n    if (result == null) {\n      throw newError(`No attribute \"${name}\"`, \"ERR_XML_MISSED_ATTRIBUTE\")\n    }\n    return result\n  }\n\n  removeAttribute(name: string): void {\n    if (this.attributes !== null) {\n      delete this.attributes[name]\n    }\n  }\n\n  element(name: string, ignoreCase = false, errorIfMissed: string | null = null): XElement {\n    const result = this.elementOrNull(name, ignoreCase)\n    if (result === null) {\n      throw newError(errorIfMissed || `No element \"${name}\"`, \"ERR_XML_MISSED_ELEMENT\")\n    }\n    return result\n  }\n\n  elementOrNull(name: string, ignoreCase = false): XElement | null {\n    if (this.elements === null) {\n      return null\n    }\n\n    for (const element of this.elements) {\n      if (isNameEquals(element, name, ignoreCase)) {\n        return element\n      }\n    }\n\n    return null\n  }\n\n  getElements(name: string, ignoreCase = false) {\n    if (this.elements === null) {\n      return []\n    }\n    return this.elements.filter(it => isNameEquals(it, name, ignoreCase))\n  }\n\n  elementValueOrEmpty(name: string, ignoreCase = false): string {\n    const element = this.elementOrNull(name, ignoreCase)\n    return element === null ? \"\" : element.value\n  }\n}\n\nconst NAME_REG_EXP = new RegExp(/^[A-Za-z_][:A-Za-z0-9_-]*$/i)\n\nfunction isValidName(name: string) {\n  return NAME_REG_EXP.test(name)\n}\n\nfunction isNameEquals(element: XElement, name: string, ignoreCase: boolean) {\n  const elementName = element.name\n  return elementName === name || (ignoreCase === true && elementName.length === name.length && elementName.toLowerCase() === name.toLowerCase())\n}\n\nexport function parseXml(data: string): XElement {\n  let rootElement: XElement | null = null\n  const parser = sax.parser(true, {})\n  const elements: Array<XElement> = []\n\n  parser.onopentag = saxElement => {\n    const element = new XElement(saxElement.name)\n    element.attributes = saxElement.attributes as Record<string, string>\n\n    if (rootElement === null) {\n      rootElement = element\n    } else {\n      const parent = elements[elements.length - 1]\n      if (parent.elements == null) {\n        parent.elements = []\n      }\n      parent.elements.push(element)\n    }\n    elements.push(element)\n  }\n\n  parser.onclosetag = () => {\n    elements.pop()\n  }\n\n  parser.ontext = text => {\n    if (elements.length > 0) {\n      elements[elements.length - 1].value = text\n    }\n  }\n\n  parser.oncdata = cdata => {\n    const element = elements[elements.length - 1]\n    element.value = cdata\n    element.isCData = true\n  }\n\n  parser.onerror = err => {\n    throw err\n  }\n\n  parser.write(data)\n  return rootElement!\n}\n"]}(The MIT License)

Copyright (c) 2011-2017 JP Richardson

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
 merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{
  "name": "fs-extra",
  "version": "10.1.0",
  "description": "fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as recursive mkdir, copy, and remove.",
  "engines": {
    "node": ">=12"
  },
  "homepage": "https://github.com/jprichardson/node-fs-extra",
  "repository": {
    "type": "git",
    "url": "https://github.com/jprichardson/node-fs-extra"
  },
  "author": "JP Richardson <jprichardson@gmail.com>",
  "license": "MIT",
  "dependencies": {
    "graceful-fs": "^4.2.0",
    "jsonfile": "^6.0.1",
    "universalify": "^2.0.0"
  },
  "devDependencies": {
    "at-least-node": "^1.0.0",
    "klaw": "^2.1.1",
    "klaw-sync": "^3.0.2",
    "minimist": "^1.1.1",
    "mocha": "^5.0.5",
    "nyc": "^15.0.0",
    "proxyquire": "^2.0.1",
    "read-dir-files": "^0.1.1",
    "standard": "^16.0.3"
  },
  "main": "./lib/index.js",
  "files": [
    "lib/",
    "!lib/**/__tests__/"
  ],
  "sideEffects": false
}'use strict'

module.exports = {
  // Export promiseified graceful-fs:
  ...require('./fs'),
  // Export extra methods:
  ...require('./copy'),
  ...require('./empty'),
  ...require('./ensure'),
  ...require('./json'),
  ...require('./mkdirs'),
  ...require('./move'),
  ...require('./output-file'),
  ...require('./path-exists'),
  ...require('./remove')
}
'use strict'

const fs = require('../fs')
const path = require('path')
const util = require('util')

function getStats (src, dest, opts) {
  const statFunc = opts.dereference
    ? (file) => fs.stat(file, { bigint: true })
    : (file) => fs.lstat(file, { bigint: true })
  return Promise.all([
    statFunc(src),
    statFunc(dest).catch(err => {
      if (err.code === 'ENOENT') return null
      throw err
    })
  ]).then(([srcStat, destStat]) => ({ srcStat, destStat }))
}

function getStatsSync (src, dest, opts) {
  let destStat
  const statFunc = opts.dereference
    ? (file) => fs.statSync(file, { bigint: true })
    : (file) => fs.lstatSync(file, { bigint: true })
  const srcStat = statFunc(src)
  try {
    destStat = statFunc(dest)
  } catch (err) {
    if (err.code === 'ENOENT') return { srcStat, destStat: null }
    throw err
  }
  return { srcStat, destStat }
}

function checkPaths (src, dest, funcName, opts, cb) {
  util.callbackify(getStats)(src, dest, opts, (err, stats) => {
    if (err) return cb(err)
    const { srcStat, destStat } = stats

    if (destStat) {
      if (areIdentical(srcStat, destStat)) {
        const srcBaseName = path.basename(src)
        const destBaseName = path.basename(dest)
        if (funcName === 'move' &&
          srcBaseName !== destBaseName &&
          srcBaseName.toLowerCase() === destBaseName.toLowerCase()) {
          return cb(null, { srcStat, destStat, isChangingCase: true })
        }
        return cb(new Error('Source and destination must not be the same.'))
      }
      if (srcStat.isDirectory() && !destStat.isDirectory()) {
        return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`))
      }
      if (!srcStat.isDirectory() && destStat.isDirectory()) {
        return cb(new Error(`Cannot overwrite directory '${dest}' with non-directory '${src}'.`))
      }
    }

    if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
      return cb(new Error(errMsg(src, dest, funcName)))
    }
    return cb(null, { srcStat, destStat })
  })
}

function checkPathsSync (src, dest, funcName, opts) {
  const { srcStat, destStat } = getStatsSync(src, dest, opts)

  if (destStat) {
    if (areIdentical(srcStat, destStat)) {
      const srcBaseName = path.basename(src)
      const destBaseName = path.basename(dest)
      if (funcName === 'move' &&
        srcBaseName !== destBaseName &&
        srcBaseName.toLowerCase() === destBaseName.toLowerCase()) {
        return { srcStat, destStat, isChangingCase: true }
      }
      throw new Error('Source and destination must not be the same.')
    }
    if (srcStat.isDirectory() && !destStat.isDirectory()) {
      throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)
    }
    if (!srcStat.isDirectory() && destStat.isDirectory()) {
      throw new Error(`Cannot overwrite directory '${dest}' with non-directory '${src}'.`)
    }
  }

  if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
    throw new Error(errMsg(src, dest, funcName))
  }
  return { srcStat, destStat }
}

// recursively check if dest parent is a subdirectory of src.
// It works for all file types including symlinks since it
// checks the src and dest inodes. It starts from the deepest
// parent and stops once it reaches the src parent or the root path.
function checkParentPaths (src, srcStat, dest, funcName, cb) {
  const srcParent = path.resolve(path.dirname(src))
  const destParent = path.resolve(path.dirname(dest))
  if (destParent === srcParent || destParent === path.parse(destParent).root) return cb()
  fs.stat(destParent, { bigint: true }, (err, destStat) => {
    if (err) {
      if (err.code === 'ENOENT') return cb()
      return cb(err)
    }
    if (areIdentical(srcStat, destStat)) {
      return cb(new Error(errMsg(src, dest, funcName)))
    }
    return checkParentPaths(src, srcStat, destParent, funcName, cb)
  })
}

function checkParentPathsSync (src, srcStat, dest, funcName) {
  const srcParent = path.resolve(path.dirname(src))
  const destParent = path.resolve(path.dirname(dest))
  if (destParent === srcParent || destParent === path.parse(destParent).root) return
  let destStat
  try {
    destStat = fs.statSync(destParent, { bigint: true })
  } catch (err) {
    if (err.code === 'ENOENT') return
    throw err
  }
  if (areIdentical(srcStat, destStat)) {
    throw new Error(errMsg(src, dest, funcName))
  }
  return checkParentPathsSync(src, srcStat, destParent, funcName)
}

function areIdentical (srcStat, destStat) {
  return destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev
}

// return true if dest is a subdir of src, otherwise false.
// It only checks the path strings.
function isSrcSubdir (src, dest) {
  const srcArr = path.resolve(src).split(path.sep).filter(i => i)
  const destArr = path.resolve(dest).split(path.sep).filter(i => i)
  return srcArr.reduce((acc, cur, i) => acc && destArr[i] === cur, true)
}

function errMsg (src, dest, funcName) {
  return `Cannot ${funcName} '${src}' to a subdirectory of itself, '${dest}'.`
}

module.exports = {
  checkPaths,
  checkPathsSync,
  checkParentPaths,
  checkParentPathsSync,
  isSrcSubdir,
  areIdentical
}
'use strict'

const fs = require('graceful-fs')

function utimesMillis (path, atime, mtime, callback) {
  // if (!HAS_MILLIS_RES) return fs.utimes(path, atime, mtime, callback)
  fs.open(path, 'r+', (err, fd) => {
    if (err) return callback(err)
    fs.futimes(fd, atime, mtime, futimesErr => {
      fs.close(fd, closeErr => {
        if (callback) callback(futimesErr || closeErr)
      })
    })
  })
}

function utimesMillisSync (path, atime, mtime) {
  const fd = fs.openSync(path, 'r+')
  fs.futimesSync(fd, atime, mtime)
  return fs.closeSync(fd)
}

module.exports = {
  utimesMillis,
  utimesMillisSync
}
'use strict'

const fs = require('graceful-fs')
const u = require('universalify').fromCallback
const rimraf = require('./rimraf')

function remove (path, callback) {
  // Node 14.14.0+
  if (fs.rm) return fs.rm(path, { recursive: true, force: true }, callback)
  rimraf(path, callback)
}

function removeSync (path) {
  // Node 14.14.0+
  if (fs.rmSync) return fs.rmSync(path, { recursive: true, force: true })
  rimraf.sync(path)
}

module.exports = {
  remove: u(remove),
  removeSync
}
'use strict'

const fs = require('graceful-fs')
const path = require('path')
const assert = require('assert')

const isWindows = (process.platform === 'win32')

function defaults (options) {
  const methods = [
    'unlink',
    'chmod',
    'stat',
    'lstat',
    'rmdir',
    'readdir'
  ]
  methods.forEach(m => {
    options[m] = options[m] || fs[m]
    m = m + 'Sync'
    options[m] = options[m] || fs[m]
  })

  options.maxBusyTries = options.maxBusyTries || 3
}

function rimraf (p, options, cb) {
  let busyTries = 0

  if (typeof options === 'function') {
    cb = options
    options = {}
  }

  assert(p, 'rimraf: missing path')
  assert.strictEqual(typeof p, 'string', 'rimraf: path should be a string')
  assert.strictEqual(typeof cb, 'function', 'rimraf: callback function required')
  assert(options, 'rimraf: invalid options argument provided')
  assert.strictEqual(typeof options, 'object', 'rimraf: options should be object')

  defaults(options)

  rimraf_(p, options, function CB (er) {
    if (er) {
      if ((er.code === 'EBUSY' || er.code === 'ENOTEMPTY' || er.code === 'EPERM') &&
          busyTries < options.maxBusyTries) {
        busyTries++
        const time = busyTries * 100
        // try again, with the same exact callback as this one.
        return setTimeout(() => rimraf_(p, options, CB), time)
      }

      // already gone
      if (er.code === 'ENOENT') er = null
    }

    cb(er)
  })
}

// Two possible strategies.
// 1. Assume it's a file.  unlink it, then do the dir stuff on EPERM or EISDIR
// 2. Assume it's a directory.  readdir, then do the file stuff on ENOTDIR
//
// Both result in an extra syscall when you guess wrong.  However, there
// are likely far more normal files in the world than directories.  This
// is based on the assumption that a the average number of files per
// directory is >= 1.
//
// If anyone ever complains about this, then I guess the strategy could
// be made configurable somehow.  But until then, YAGNI.
function rimraf_ (p, options, cb) {
  assert(p)
  assert(options)
  assert(typeof cb === 'function')

  // sunos lets the root user unlink directories, which is... weird.
  // so we have to lstat here and make sure it's not a dir.
  options.lstat(p, (er, st) => {
    if (er && er.code === 'ENOENT') {
      return cb(null)
    }

    // Windows can EPERM on stat.  Life is suffering.
    if (er && er.code === 'EPERM' && isWindows) {
      return fixWinEPERM(p, options, er, cb)
    }

    if (st && st.isDirectory()) {
      return rmdir(p, options, er, cb)
    }

    options.unlink(p, er => {
      if (er) {
        if (er.code === 'ENOENT') {
          return cb(null)
        }
        if (er.code === 'EPERM') {
          return (isWindows)
            ? fixWinEPERM(p, options, er, cb)
            : rmdir(p, options, er, cb)
        }
        if (er.code === 'EISDIR') {
          return rmdir(p, options, er, cb)
        }
      }
      return cb(er)
    })
  })
}

function fixWinEPERM (p, options, er, cb) {
  assert(p)
  assert(options)
  assert(typeof cb === 'function')

  options.chmod(p, 0o666, er2 => {
    if (er2) {
      cb(er2.code === 'ENOENT' ? null : er)
    } else {
      options.stat(p, (er3, stats) => {
        if (er3) {
          cb(er3.code === 'ENOENT' ? null : er)
        } else if (stats.isDirectory()) {
          rmdir(p, options, er, cb)
        } else {
          options.unlink(p, cb)
        }
      })
    }
  })
}

function fixWinEPERMSync (p, options, er) {
  let stats

  assert(p)
  assert(options)

  try {
    options.chmodSync(p, 0o666)
  } catch (er2) {
    if (er2.code === 'ENOENT') {
      return
    } else {
      throw er
    }
  }

  try {
    stats = options.statSync(p)
  } catch (er3) {
    if (er3.code === 'ENOENT') {
      return
    } else {
      throw er
    }
  }

  if (stats.isDirectory()) {
    rmdirSync(p, options, er)
  } else {
    options.unlinkSync(p)
  }
}

function rmdir (p, options, originalEr, cb) {
  assert(p)
  assert(options)
  assert(typeof cb === 'function')

  // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
  // if we guessed wrong, and it's not a directory, then
  // raise the original error.
  options.rmdir(p, er => {
    if (er && (er.code === 'ENOTEMPTY' || er.code === 'EEXIST' || er.code === 'EPERM')) {
      rmkids(p, options, cb)
    } else if (er && er.code === 'ENOTDIR') {
      cb(originalEr)
    } else {
      cb(er)
    }
  })
}

function rmkids (p, options, cb) {
  assert(p)
  assert(options)
  assert(typeof cb === 'function')

  options.readdir(p, (er, files) => {
    if (er) return cb(er)

    let n = files.length
    let errState

    if (n === 0) return options.rmdir(p, cb)

    files.forEach(f => {
      rimraf(path.join(p, f), options, er => {
        if (errState) {
          return
        }
        if (er) return cb(errState = er)
        if (--n === 0) {
          options.rmdir(p, cb)
        }
      })
    })
  })
}

// this looks simpler, and is strictly *faster*, but will
// tie up the JavaScript thread and fail on excessively
// deep directory trees.
function rimrafSync (p, options) {
  let st

  options = options || {}
  defaults(options)

  assert(p, 'rimraf: missing path')
  assert.strictEqual(typeof p, 'string', 'rimraf: path should be a string')
  assert(options, 'rimraf: missing options')
  assert.strictEqual(typeof options, 'object', 'rimraf: options should be object')

  try {
    st = options.lstatSync(p)
  } catch (er) {
    if (er.code === 'ENOENT') {
      return
    }

    // Windows can EPERM on stat.  Life is suffering.
    if (er.code === 'EPERM' && isWindows) {
      fixWinEPERMSync(p, options, er)
    }
  }

  try {
    // sunos lets the root user unlink directories, which is... weird.
    if (st && st.isDirectory()) {
      rmdirSync(p, options, null)
    } else {
      options.unlinkSync(p)
    }
  } catch (er) {
    if (er.code === 'ENOENT') {
      return
    } else if (er.code === 'EPERM') {
      return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er)
    } else if (er.code !== 'EISDIR') {
      throw er
    }
    rmdirSync(p, options, er)
  }
}

function rmdirSync (p, options, originalEr) {
  assert(p)
  assert(options)

  try {
    options.rmdirSync(p)
  } catch (er) {
    if (er.code === 'ENOTDIR') {
      throw originalEr
    } else if (er.code === 'ENOTEMPTY' || er.code === 'EEXIST' || er.code === 'EPERM') {
      rmkidsSync(p, options)
    } else if (er.code !== 'ENOENT') {
      throw er
    }
  }
}

function rmkidsSync (p, options) {
  assert(p)
  assert(options)
  options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options))

  if (isWindows) {
    // We only end up here once we got ENOTEMPTY at least once, and
    // at this point, we are guaranteed to have removed all the kids.
    // So, we know that it won't be ENOENT or ENOTDIR or anything else.
    // try really hard to delete stuff on windows, because it has a
    // PROFOUNDLY annoying habit of not closing handles promptly when
    // files are deleted, resulting in spurious ENOTEMPTY errors.
    const startTime = Date.now()
    do {
      try {
        const ret = options.rmdirSync(p, options)
        return ret
      } catch {}
    } while (Date.now() - startTime < 500) // give up after 500ms
  } else {
    const ret = options.rmdirSync(p, options)
    return ret
  }
}

module.exports = rimraf
rimraf.sync = rimrafSync
'use strict'
const u = require('universalify').fromPromise
const fs = require('../fs')

function pathExists (path) {
  return fs.access(path).then(() => true).catch(() => false)
}

module.exports = {
  pathExists: u(pathExists),
  pathExistsSync: fs.existsSync
}
'use strict'

const u = require('universalify').fromCallback
const fs = require('graceful-fs')
const path = require('path')
const mkdir = require('../mkdirs')
const pathExists = require('../path-exists').pathExists

function outputFile (file, data, encoding, callback) {
  if (typeof encoding === 'function') {
    callback = encoding
    encoding = 'utf8'
  }

  const dir = path.dirname(file)
  pathExists(dir, (err, itDoes) => {
    if (err) return callback(err)
    if (itDoes) return fs.writeFile(file, data, encoding, callback)

    mkdir.mkdirs(dir, err => {
      if (err) return callback(err)

      fs.writeFile(file, data, encoding, callback)
    })
  })
}

function outputFileSync (file, ...args) {
  const dir = path.dirname(file)
  if (fs.existsSync(dir)) {
    return fs.writeFileSync(file, ...args)
  }
  mkdir.mkdirsSync(dir)
  fs.writeFileSync(file, ...args)
}

module.exports = {
  outputFile: u(outputFile),
  outputFileSync
}
'use strict'

const u = require('universalify').fromCallback
module.exports = {
  move: u(require('./move')),
  moveSync: require('./move-sync')
}
'use strict'

const fs = require('graceful-fs')
const path = require('path')
const copySync = require('../copy').copySync
const removeSync = require('../remove').removeSync
const mkdirpSync = require('../mkdirs').mkdirpSync
const stat = require('../util/stat')

function moveSync (src, dest, opts) {
  opts = opts || {}
  const overwrite = opts.overwrite || opts.clobber || false

  const { srcStat, isChangingCase = false } = stat.checkPathsSync(src, dest, 'move', opts)
  stat.checkParentPathsSync(src, srcStat, dest, 'move')
  if (!isParentRoot(dest)) mkdirpSync(path.dirname(dest))
  return doRename(src, dest, overwrite, isChangingCase)
}

function isParentRoot (dest) {
  const parent = path.dirname(dest)
  const parsedPath = path.parse(parent)
  return parsedPath.root === parent
}

function doRename (src, dest, overwrite, isChangingCase) {
  if (isChangingCase) return rename(src, dest, overwrite)
  if (overwrite) {
    removeSync(dest)
    return rename(src, dest, overwrite)
  }
  if (fs.existsSync(dest)) throw new Error('dest already exists.')
  return rename(src, dest, overwrite)
}

function rename (src, dest, overwrite) {
  try {
    fs.renameSync(src, dest)
  } catch (err) {
    if (err.code !== 'EXDEV') throw err
    return moveAcrossDevice(src, dest, overwrite)
  }
}

function moveAcrossDevice (src, dest, overwrite) {
  const opts = {
    overwrite,
    errorOnExist: true
  }
  copySync(src, dest, opts)
  return removeSync(src)
}

module.exports = moveSync
'use strict'

const fs = require('graceful-fs')
const path = require('path')
const copy = require('../copy').copy
const remove = require('../remove').remove
const mkdirp = require('../mkdirs').mkdirp
const pathExists = require('../path-exists').pathExists
const stat = require('../util/stat')

function move (src, dest, opts, cb) {
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }

  opts = opts || {}

  const overwrite = opts.overwrite || opts.clobber || false

  stat.checkPaths(src, dest, 'move', opts, (err, stats) => {
    if (err) return cb(err)
    const { srcStat, isChangingCase = false } = stats
    stat.checkParentPaths(src, srcStat, dest, 'move', err => {
      if (err) return cb(err)
      if (isParentRoot(dest)) return doRename(src, dest, overwrite, isChangingCase, cb)
      mkdirp(path.dirname(dest), err => {
        if (err) return cb(err)
        return doRename(src, dest, overwrite, isChangingCase, cb)
      })
    })
  })
}

function isParentRoot (dest) {
  const parent = path.dirname(dest)
  const parsedPath = path.parse(parent)
  return parsedPath.root === parent
}

function doRename (src, dest, overwrite, isChangingCase, cb) {
  if (isChangingCase) return rename(src, dest, overwrite, cb)
  if (overwrite) {
    return remove(dest, err => {
      if (err) return cb(err)
      return rename(src, dest, overwrite, cb)
    })
  }
  pathExists(dest, (err, destExists) => {
    if (err) return cb(err)
    if (destExists) return cb(new Error('dest already exists.'))
    return rename(src, dest, overwrite, cb)
  })
}

function rename (src, dest, overwrite, cb) {
  fs.rename(src, dest, err => {
    if (!err) return cb()
    if (err.code !== 'EXDEV') return cb(err)
    return moveAcrossDevice(src, dest, overwrite, cb)
  })
}

function moveAcrossDevice (src, dest, overwrite, cb) {
  const opts = {
    overwrite,
    errorOnExist: true
  }
  copy(src, dest, opts, err => {
    if (err) return cb(err)
    return remove(src, cb)
  })
}

module.exports = move
'use strict'
const u = require('universalify').fromPromise
const { makeDir: _makeDir, makeDirSync } = require('./make-dir')
const makeDir = u(_makeDir)

module.exports = {
  mkdirs: makeDir,
  mkdirsSync: makeDirSync,
  // alias
  mkdirp: makeDir,
  mkdirpSync: makeDirSync,
  ensureDir: makeDir,
  ensureDirSync: makeDirSync
}
'use strict'
const fs = require('../fs')
const { checkPath } = require('./utils')

const getMode = options => {
  const defaults = { mode: 0o777 }
  if (typeof options === 'number') return options
  return ({ ...defaults, ...options }).mode
}

module.exports.makeDir = async (dir, options) => {
  checkPath(dir)

  return fs.mkdir(dir, {
    mode: getMode(options),
    recursive: true
  })
}

module.exports.makeDirSync = (dir, options) => {
  checkPath(dir)

  return fs.mkdirSync(dir, {
    mode: getMode(options),
    recursive: true
  })
}
// Adapted from https://github.com/sindresorhus/make-dir
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict'
const path = require('path')

// https://github.com/nodejs/node/issues/8987
// https://github.com/libuv/libuv/pull/1088
module.exports.checkPath = function checkPath (pth) {
  if (process.platform === 'win32') {
    const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, ''))

    if (pathHasInvalidWinCharacters) {
      const error = new Error(`Path contains invalid characters: ${pth}`)
      error.code = 'EINVAL'
      throw error
    }
  }
}
'use strict'

const u = require('universalify').fromPromise
const jsonFile = require('./jsonfile')

jsonFile.outputJson = u(require('./output-json'))
jsonFile.outputJsonSync = require('./output-json-sync')
// aliases
jsonFile.outputJSON = jsonFile.outputJson
jsonFile.outputJSONSync = jsonFile.outputJsonSync
jsonFile.writeJSON = jsonFile.writeJson
jsonFile.writeJSONSync = jsonFile.writeJsonSync
jsonFile.readJSON = jsonFile.readJson
jsonFile.readJSONSync = jsonFile.readJsonSync

module.exports = jsonFile
'use strict'

const jsonFile = require('jsonfile')

module.exports = {
  // jsonfile exports
  readJson: jsonFile.readFile,
  readJsonSync: jsonFile.readFileSync,
  writeJson: jsonFile.writeFile,
  writeJsonSync: jsonFile.writeFileSync
}
'use strict'

const { stringify } = require('jsonfile/utils')
const { outputFileSync } = require('../output-file')

function outputJsonSync (file, data, options) {
  const str = stringify(data, options)

  outputFileSync(file, str, options)
}

module.exports = outputJsonSync
'use strict'

const { stringify } = require('jsonfile/utils')
const { outputFile } = require('../output-file')

async function outputJson (file, data, options = {}) {
  const str = stringify(data, options)

  await outputFile(file, str, options)
}

module.exports = outputJson
'use strict'
// This is adapted from https://github.com/normalize/mz
// Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors
const u = require('universalify').fromCallback
const fs = require('graceful-fs')

const api = [
  'access',
  'appendFile',
  'chmod',
  'chown',
  'close',
  'copyFile',
  'fchmod',
  'fchown',
  'fdatasync',
  'fstat',
  'fsync',
  'ftruncate',
  'futimes',
  'lchmod',
  'lchown',
  'link',
  'lstat',
  'mkdir',
  'mkdtemp',
  'open',
  'opendir',
  'readdir',
  'readFile',
  'readlink',
  'realpath',
  'rename',
  'rm',
  'rmdir',
  'stat',
  'symlink',
  'truncate',
  'unlink',
  'utimes',
  'writeFile'
].filter(key => {
  // Some commands are not available on some systems. Ex:
  // fs.opendir was added in Node.js v12.12.0
  // fs.rm was added in Node.js v14.14.0
  // fs.lchown is not available on at least some Linux
  return typeof fs[key] === 'function'
})

// Export cloned fs:
Object.assign(exports, fs)

// Universalify async methods:
api.forEach(method => {
  exports[method] = u(fs[method])
})

// We differ from mz/fs in that we still ship the old, broken, fs.exists()
// since we are a drop-in replacement for the native module
exports.exists = function (filename, callback) {
  if (typeof callback === 'function') {
    return fs.exists(filename, callback)
  }
  return new Promise(resolve => {
    return fs.exists(filename, resolve)
  })
}

// fs.read(), fs.write(), & fs.writev() need special treatment due to multiple callback args

exports.read = function (fd, buffer, offset, length, position, callback) {
  if (typeof callback === 'function') {
    return fs.read(fd, buffer, offset, length, position, callback)
  }
  return new Promise((resolve, reject) => {
    fs.read(fd, buffer, offset, length, position, (err, bytesRead, buffer) => {
      if (err) return reject(err)
      resolve({ bytesRead, buffer })
    })
  })
}

// Function signature can be
// fs.write(fd, buffer[, offset[, length[, position]]], callback)
// OR
// fs.write(fd, string[, position[, encoding]], callback)
// We need to handle both cases, so we use ...args
exports.write = function (fd, buffer, ...args) {
  if (typeof args[args.length - 1] === 'function') {
    return fs.write(fd, buffer, ...args)
  }

  return new Promise((resolve, reject) => {
    fs.write(fd, buffer, ...args, (err, bytesWritten, buffer) => {
      if (err) return reject(err)
      resolve({ bytesWritten, buffer })
    })
  })
}

// fs.writev only available in Node v12.9.0+
if (typeof fs.writev === 'function') {
  // Function signature is
  // s.writev(fd, buffers[, position], callback)
  // We need to handle the optional arg, so we use ...args
  exports.writev = function (fd, buffers, ...args) {
    if (typeof args[args.length - 1] === 'function') {
      return fs.writev(fd, buffers, ...args)
    }

    return new Promise((resolve, reject) => {
      fs.writev(fd, buffers, ...args, (err, bytesWritten, buffers) => {
        if (err) return reject(err)
        resolve({ bytesWritten, buffers })
      })
    })
  }
}

// fs.realpath.native sometimes not available if fs is monkey-patched
if (typeof fs.realpath.native === 'function') {
  exports.realpath.native = u(fs.realpath.native)
} else {
  process.emitWarning(
    'fs.realpath.native is not a function. Is fs being monkey-patched?',
    'Warning', 'fs-extra-WARN0003'
  )
}
'use strict'

const u = require('universalify').fromCallback
const path = require('path')
const fs = require('graceful-fs')
const mkdir = require('../mkdirs')

function createFile (file, callback) {
  function makeFile () {
    fs.writeFile(file, '', err => {
      if (err) return callback(err)
      callback()
    })
  }

  fs.stat(file, (err, stats) => { // eslint-disable-line handle-callback-err
    if (!err && stats.isFile()) return callback()
    const dir = path.dirname(file)
    fs.stat(dir, (err, stats) => {
      if (err) {
        // if the directory doesn't exist, make it
        if (err.code === 'ENOENT') {
          return mkdir.mkdirs(dir, err => {
            if (err) return callback(err)
            makeFile()
          })
        }
        return callback(err)
      }

      if (stats.isDirectory()) makeFile()
      else {
        // parent is not a directory
        // This is just to cause an internal ENOTDIR error to be thrown
        fs.readdir(dir, err => {
          if (err) return callback(err)
        })
      }
    })
  })
}

function createFileSync (file) {
  let stats
  try {
    stats = fs.statSync(file)
  } catch {}
  if (stats && stats.isFile()) return

  const dir = path.dirname(file)
  try {
    if (!fs.statSync(dir).isDirectory()) {
      // parent is not a directory
      // This is just to cause an internal ENOTDIR error to be thrown
      fs.readdirSync(dir)
    }
  } catch (err) {
    // If the stat call above failed because the directory doesn't exist, create it
    if (err && err.code === 'ENOENT') mkdir.mkdirsSync(dir)
    else throw err
  }

  fs.writeFileSync(file, '')
}

module.exports = {
  createFile: u(createFile),
  createFileSync
}
'use strict'

const { createFile, createFileSync } = require('./file')
const { createLink, createLinkSync } = require('./link')
const { createSymlink, createSymlinkSync } = require('./symlink')

module.exports = {
  // file
  createFile,
  createFileSync,
  ensureFile: createFile,
  ensureFileSync: createFileSync,
  // link
  createLink,
  createLinkSync,
  ensureLink: createLink,
  ensureLinkSync: createLinkSync,
  // symlink
  createSymlink,
  createSymlinkSync,
  ensureSymlink: createSymlink,
  ensureSymlinkSync: createSymlinkSync
}
'use strict'

const u = require('universalify').fromCallback
const path = require('path')
const fs = require('graceful-fs')
const mkdir = require('../mkdirs')
const pathExists = require('../path-exists').pathExists
const { areIdentical } = require('../util/stat')

function createLink (srcpath, dstpath, callback) {
  function makeLink (srcpath, dstpath) {
    fs.link(srcpath, dstpath, err => {
      if (err) return callback(err)
      callback(null)
    })
  }

  fs.lstat(dstpath, (_, dstStat) => {
    fs.lstat(srcpath, (err, srcStat) => {
      if (err) {
        err.message = err.message.replace('lstat', 'ensureLink')
        return callback(err)
      }
      if (dstStat && areIdentical(srcStat, dstStat)) return callback(null)

      const dir = path.dirname(dstpath)
      pathExists(dir, (err, dirExists) => {
        if (err) return callback(err)
        if (dirExists) return makeLink(srcpath, dstpath)
        mkdir.mkdirs(dir, err => {
          if (err) return callback(err)
          makeLink(srcpath, dstpath)
        })
      })
    })
  })
}

function createLinkSync (srcpath, dstpath) {
  let dstStat
  try {
    dstStat = fs.lstatSync(dstpath)
  } catch {}

  try {
    const srcStat = fs.lstatSync(srcpath)
    if (dstStat && areIdentical(srcStat, dstStat)) return
  } catch (err) {
    err.message = err.message.replace('lstat', 'ensureLink')
    throw err
  }

  const dir = path.dirname(dstpath)
  const dirExists = fs.existsSync(dir)
  if (dirExists) return fs.linkSync(srcpath, dstpath)
  mkdir.mkdirsSync(dir)

  return fs.linkSync(srcpath, dstpath)
}

module.exports = {
  createLink: u(createLink),
  createLinkSync
}
'use strict'

const path = require('path')
const fs = require('graceful-fs')
const pathExists = require('../path-exists').pathExists

/**
 * Function that returns two types of paths, one relative to symlink, and one
 * relative to the current working directory. Checks if path is absolute or
 * relative. If the path is relative, this function checks if the path is
 * relative to symlink or relative to current working directory. This is an
 * initiative to find a smarter `srcpath` to supply when building symlinks.
 * This allows you to determine which path to use out of one of three possible
 * types of source paths. The first is an absolute path. This is detected by
 * `path.isAbsolute()`. When an absolute path is provided, it is checked to
 * see if it exists. If it does it's used, if not an error is returned
 * (callback)/ thrown (sync). The other two options for `srcpath` are a
 * relative url. By default Node's `fs.symlink` works by creating a symlink
 * using `dstpath` and expects the `srcpath` to be relative to the newly
 * created symlink. If you provide a `srcpath` that does not exist on the file
 * system it results in a broken symlink. To minimize this, the function
 * checks to see if the 'relative to symlink' source file exists, and if it
 * does it will use it. If it does not, it checks if there's a file that
 * exists that is relative to the current working directory, if does its used.
 * This preserves the expectations of the original fs.symlink spec and adds
 * the ability to pass in `relative to current working direcotry` paths.
 */

function symlinkPaths (srcpath, dstpath, callback) {
  if (path.isAbsolute(srcpath)) {
    return fs.lstat(srcpath, (err) => {
      if (err) {
        err.message = err.message.replace('lstat', 'ensureSymlink')
        return callback(err)
      }
      return callback(null, {
        toCwd: srcpath,
        toDst: srcpath
      })
    })
  } else {
    const dstdir = path.dirname(dstpath)
    const relativeToDst = path.join(dstdir, srcpath)
    return pathExists(relativeToDst, (err, exists) => {
      if (err) return callback(err)
      if (exists) {
        return callback(null, {
          toCwd: relativeToDst,
          toDst: srcpath
        })
      } else {
        return fs.lstat(srcpath, (err) => {
          if (err) {
            err.message = err.message.replace('lstat', 'ensureSymlink')
            return callback(err)
          }
          return callback(null, {
            toCwd: srcpath,
            toDst: path.relative(dstdir, srcpath)
          })
        })
      }
    })
  }
}

function symlinkPathsSync (srcpath, dstpath) {
  let exists
  if (path.isAbsolute(srcpath)) {
    exists = fs.existsSync(srcpath)
    if (!exists) throw new Error('absolute srcpath does not exist')
    return {
      toCwd: srcpath,
      toDst: srcpath
    }
  } else {
    const dstdir = path.dirname(dstpath)
    const relativeToDst = path.join(dstdir, srcpath)
    exists = fs.existsSync(relativeToDst)
    if (exists) {
      return {
        toCwd: relativeToDst,
        toDst: srcpath
      }
    } else {
      exists = fs.existsSync(srcpath)
      if (!exists) throw new Error('relative srcpath does not exist')
      return {
        toCwd: srcpath,
        toDst: path.relative(dstdir, srcpath)
      }
    }
  }
}

module.exports = {
  symlinkPaths,
  symlinkPathsSync
}
'use strict'

const fs = require('graceful-fs')

function symlinkType (srcpath, type, callback) {
  callback = (typeof type === 'function') ? type : callback
  type = (typeof type === 'function') ? false : type
  if (type) return callback(null, type)
  fs.lstat(srcpath, (err, stats) => {
    if (err) return callback(null, 'file')
    type = (stats && stats.isDirectory()) ? 'dir' : 'file'
    callback(null, type)
  })
}

function symlinkTypeSync (srcpath, type) {
  let stats

  if (type) return type
  try {
    stats = fs.lstatSync(srcpath)
  } catch {
    return 'file'
  }
  return (stats && stats.isDirectory()) ? 'dir' : 'file'
}

module.exports = {
  symlinkType,
  symlinkTypeSync
}
'use strict'

const u = require('universalify').fromCallback
const path = require('path')
const fs = require('../fs')
const _mkdirs = require('../mkdirs')
const mkdirs = _mkdirs.mkdirs
const mkdirsSync = _mkdirs.mkdirsSync

const _symlinkPaths = require('./symlink-paths')
const symlinkPaths = _symlinkPaths.symlinkPaths
const symlinkPathsSync = _symlinkPaths.symlinkPathsSync

const _symlinkType = require('./symlink-type')
const symlinkType = _symlinkType.symlinkType
const symlinkTypeSync = _symlinkType.symlinkTypeSync

const pathExists = require('../path-exists').pathExists

const { areIdentical } = require('../util/stat')

function createSymlink (srcpath, dstpath, type, callback) {
  callback = (typeof type === 'function') ? type : callback
  type = (typeof type === 'function') ? false : type

  fs.lstat(dstpath, (err, stats) => {
    if (!err && stats.isSymbolicLink()) {
      Promise.all([
        fs.stat(srcpath),
        fs.stat(dstpath)
      ]).then(([srcStat, dstStat]) => {
        if (areIdentical(srcStat, dstStat)) return callback(null)
        _createSymlink(srcpath, dstpath, type, callback)
      })
    } else _createSymlink(srcpath, dstpath, type, callback)
  })
}

function _createSymlink (srcpath, dstpath, type, callback) {
  symlinkPaths(srcpath, dstpath, (err, relative) => {
    if (err) return callback(err)
    srcpath = relative.toDst
    symlinkType(relative.toCwd, type, (err, type) => {
      if (err) return callback(err)
      const dir = path.dirname(dstpath)
      pathExists(dir, (err, dirExists) => {
        if (err) return callback(err)
        if (dirExists) return fs.symlink(srcpath, dstpath, type, callback)
        mkdirs(dir, err => {
          if (err) return callback(err)
          fs.symlink(srcpath, dstpath, type, callback)
        })
      })
    })
  })
}

function createSymlinkSync (srcpath, dstpath, type) {
  let stats
  try {
    stats = fs.lstatSync(dstpath)
  } catch {}
  if (stats && stats.isSymbolicLink()) {
    const srcStat = fs.statSync(srcpath)
    const dstStat = fs.statSync(dstpath)
    if (areIdentical(srcStat, dstStat)) return
  }

  const relative = symlinkPathsSync(srcpath, dstpath)
  srcpath = relative.toDst
  type = symlinkTypeSync(relative.toCwd, type)
  const dir = path.dirname(dstpath)
  const exists = fs.existsSync(dir)
  if (exists) return fs.symlinkSync(srcpath, dstpath, type)
  mkdirsSync(dir)
  return fs.symlinkSync(srcpath, dstpath, type)
}

module.exports = {
  createSymlink: u(createSymlink),
  createSymlinkSync
}
'use strict'

const u = require('universalify').fromPromise
const fs = require('../fs')
const path = require('path')
const mkdir = require('../mkdirs')
const remove = require('../remove')

const emptyDir = u(async function emptyDir (dir) {
  let items
  try {
    items = await fs.readdir(dir)
  } catch {
    return mkdir.mkdirs(dir)
  }

  return Promise.all(items.map(item => remove.remove(path.join(dir, item))))
})

function emptyDirSync (dir) {
  let items
  try {
    items = fs.readdirSync(dir)
  } catch {
    return mkdir.mkdirsSync(dir)
  }

  items.forEach(item => {
    item = path.join(dir, item)
    remove.removeSync(item)
  })
}

module.exports = {
  emptyDirSync,
  emptydirSync: emptyDirSync,
  emptyDir,
  emptydir: emptyDir
}
'use strict'

const fs = require('graceful-fs')
const path = require('path')
const mkdirsSync = require('../mkdirs').mkdirsSync
const utimesMillisSync = require('../util/utimes').utimesMillisSync
const stat = require('../util/stat')

function copySync (src, dest, opts) {
  if (typeof opts === 'function') {
    opts = { filter: opts }
  }

  opts = opts || {}
  opts.clobber = 'clobber' in opts ? !!opts.clobber : true // default to true for now
  opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber // overwrite falls back to clobber

  // Warn about using preserveTimestamps on 32-bit node
  if (opts.preserveTimestamps && process.arch === 'ia32') {
    process.emitWarning(
      'Using the preserveTimestamps option in 32-bit node is not recommended;\n\n' +
      '\tsee https://github.com/jprichardson/node-fs-extra/issues/269',
      'Warning', 'fs-extra-WARN0002'
    )
  }

  const { srcStat, destStat } = stat.checkPathsSync(src, dest, 'copy', opts)
  stat.checkParentPathsSync(src, srcStat, dest, 'copy')
  return handleFilterAndCopy(destStat, src, dest, opts)
}

function handleFilterAndCopy (destStat, src, dest, opts) {
  if (opts.filter && !opts.filter(src, dest)) return
  const destParent = path.dirname(dest)
  if (!fs.existsSync(destParent)) mkdirsSync(destParent)
  return getStats(destStat, src, dest, opts)
}

function startCopy (destStat, src, dest, opts) {
  if (opts.filter && !opts.filter(src, dest)) return
  return getStats(destStat, src, dest, opts)
}

function getStats (destStat, src, dest, opts) {
  const statSync = opts.dereference ? fs.statSync : fs.lstatSync
  const srcStat = statSync(src)

  if (srcStat.isDirectory()) return onDir(srcStat, destStat, src, dest, opts)
  else if (srcStat.isFile() ||
           srcStat.isCharacterDevice() ||
           srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts)
  else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts)
  else if (srcStat.isSocket()) throw new Error(`Cannot copy a socket file: ${src}`)
  else if (srcStat.isFIFO()) throw new Error(`Cannot copy a FIFO pipe: ${src}`)
  throw new Error(`Unknown file: ${src}`)
}

function onFile (srcStat, destStat, src, dest, opts) {
  if (!destStat) return copyFile(srcStat, src, dest, opts)
  return mayCopyFile(srcStat, src, dest, opts)
}

function mayCopyFile (srcStat, src, dest, opts) {
  if (opts.overwrite) {
    fs.unlinkSync(dest)
    return copyFile(srcStat, src, dest, opts)
  } else if (opts.errorOnExist) {
    throw new Error(`'${dest}' already exists`)
  }
}

function copyFile (srcStat, src, dest, opts) {
  fs.copyFileSync(src, dest)
  if (opts.preserveTimestamps) handleTimestamps(srcStat.mode, src, dest)
  return setDestMode(dest, srcStat.mode)
}

function handleTimestamps (srcMode, src, dest) {
  // Make sure the file is writable before setting the timestamp
  // otherwise open fails with EPERM when invoked with 'r+'
  // (through utimes call)
  if (fileIsNotWritable(srcMode)) makeFileWritable(dest, srcMode)
  return setDestTimestamps(src, dest)
}

function fileIsNotWritable (srcMode) {
  return (srcMode & 0o200) === 0
}

function makeFileWritable (dest, srcMode) {
  return setDestMode(dest, srcMode | 0o200)
}

function setDestMode (dest, srcMode) {
  return fs.chmodSync(dest, srcMode)
}

function setDestTimestamps (src, dest) {
  // The initial srcStat.atime cannot be trusted
  // because it is modified by the read(2) system call
  // (See https://nodejs.org/api/fs.html#fs_stat_time_values)
  const updatedSrcStat = fs.statSync(src)
  return utimesMillisSync(dest, updatedSrcStat.atime, updatedSrcStat.mtime)
}

function onDir (srcStat, destStat, src, dest, opts) {
  if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts)
  return copyDir(src, dest, opts)
}

function mkDirAndCopy (srcMode, src, dest, opts) {
  fs.mkdirSync(dest)
  copyDir(src, dest, opts)
  return setDestMode(dest, srcMode)
}

function copyDir (src, dest, opts) {
  fs.readdirSync(src).forEach(item => copyDirItem(item, src, dest, opts))
}

function copyDirItem (item, src, dest, opts) {
  const srcItem = path.join(src, item)
  const destItem = path.join(dest, item)
  const { destStat } = stat.checkPathsSync(srcItem, destItem, 'copy', opts)
  return startCopy(destStat, srcItem, destItem, opts)
}

function onLink (destStat, src, dest, opts) {
  let resolvedSrc = fs.readlinkSync(src)
  if (opts.dereference) {
    resolvedSrc = path.resolve(process.cwd(), resolvedSrc)
  }

  if (!destStat) {
    return fs.symlinkSync(resolvedSrc, dest)
  } else {
    let resolvedDest
    try {
      resolvedDest = fs.readlinkSync(dest)
    } catch (err) {
      // dest exists and is a regular file or directory,
      // Windows may throw UNKNOWN error. If dest already exists,
      // fs throws error anyway, so no need to guard against it here.
      if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return fs.symlinkSync(resolvedSrc, dest)
      throw err
    }
    if (opts.dereference) {
      resolvedDest = path.resolve(process.cwd(), resolvedDest)
    }
    if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) {
      throw new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`)
    }

    // prevent copy if src is a subdir of dest since unlinking
    // dest in this case would result in removing src contents
    // and therefore a broken symlink would be created.
    if (fs.statSync(dest).isDirectory() && stat.isSrcSubdir(resolvedDest, resolvedSrc)) {
      throw new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`)
    }
    return copyLink(resolvedSrc, dest)
  }
}

function copyLink (resolvedSrc, dest) {
  fs.unlinkSync(dest)
  return fs.symlinkSync(resolvedSrc, dest)
}

module.exports = copySync
'use strict'

const fs = require('graceful-fs')
const path = require('path')
const mkdirs = require('../mkdirs').mkdirs
const pathExists = require('../path-exists').pathExists
const utimesMillis = require('../util/utimes').utimesMillis
const stat = require('../util/stat')

function copy (src, dest, opts, cb) {
  if (typeof opts === 'function' && !cb) {
    cb = opts
    opts = {}
  } else if (typeof opts === 'function') {
    opts = { filter: opts }
  }

  cb = cb || function () {}
  opts = opts || {}

  opts.clobber = 'clobber' in opts ? !!opts.clobber : true // default to true for now
  opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber // overwrite falls back to clobber

  // Warn about using preserveTimestamps on 32-bit node
  if (opts.preserveTimestamps && process.arch === 'ia32') {
    process.emitWarning(
      'Using the preserveTimestamps option in 32-bit node is not recommended;\n\n' +
      '\tsee https://github.com/jprichardson/node-fs-extra/issues/269',
      'Warning', 'fs-extra-WARN0001'
    )
  }

  stat.checkPaths(src, dest, 'copy', opts, (err, stats) => {
    if (err) return cb(err)
    const { srcStat, destStat } = stats
    stat.checkParentPaths(src, srcStat, dest, 'copy', err => {
      if (err) return cb(err)
      if (opts.filter) return handleFilter(checkParentDir, destStat, src, dest, opts, cb)
      return checkParentDir(destStat, src, dest, opts, cb)
    })
  })
}

function checkParentDir (destStat, src, dest, opts, cb) {
  const destParent = path.dirname(dest)
  pathExists(destParent, (err, dirExists) => {
    if (err) return cb(err)
    if (dirExists) return getStats(destStat, src, dest, opts, cb)
    mkdirs(destParent, err => {
      if (err) return cb(err)
      return getStats(destStat, src, dest, opts, cb)
    })
  })
}

function handleFilter (onInclude, destStat, src, dest, opts, cb) {
  Promise.resolve(opts.filter(src, dest)).then(include => {
    if (include) return onInclude(destStat, src, dest, opts, cb)
    return cb()
  }, error => cb(error))
}

function startCopy (destStat, src, dest, opts, cb) {
  if (opts.filter) return handleFilter(getStats, destStat, src, dest, opts, cb)
  return getStats(destStat, src, dest, opts, cb)
}

function getStats (destStat, src, dest, opts, cb) {
  const stat = opts.dereference ? fs.stat : fs.lstat
  stat(src, (err, srcStat) => {
    if (err) return cb(err)

    if (srcStat.isDirectory()) return onDir(srcStat, destStat, src, dest, opts, cb)
    else if (srcStat.isFile() ||
             srcStat.isCharacterDevice() ||
             srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts, cb)
    else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts, cb)
    else if (srcStat.isSocket()) return cb(new Error(`Cannot copy a socket file: ${src}`))
    else if (srcStat.isFIFO()) return cb(new Error(`Cannot copy a FIFO pipe: ${src}`))
    return cb(new Error(`Unknown file: ${src}`))
  })
}

function onFile (srcStat, destStat, src, dest, opts, cb) {
  if (!destStat) return copyFile(srcStat, src, dest, opts, cb)
  return mayCopyFile(srcStat, src, dest, opts, cb)
}

function mayCopyFile (srcStat, src, dest, opts, cb) {
  if (opts.overwrite) {
    fs.unlink(dest, err => {
      if (err) return cb(err)
      return copyFile(srcStat, src, dest, opts, cb)
    })
  } else if (opts.errorOnExist) {
    return cb(new Error(`'${dest}' already exists`))
  } else return cb()
}

function copyFile (srcStat, src, dest, opts, cb) {
  fs.copyFile(src, dest, err => {
    if (err) return cb(err)
    if (opts.preserveTimestamps) return handleTimestampsAndMode(srcStat.mode, src, dest, cb)
    return setDestMode(dest, srcStat.mode, cb)
  })
}

function handleTimestampsAndMode (srcMode, src, dest, cb) {
  // Make sure the file is writable before setting the timestamp
  // otherwise open fails with EPERM when invoked with 'r+'
  // (through utimes call)
  if (fileIsNotWritable(srcMode)) {
    return makeFileWritable(dest, srcMode, err => {
      if (err) return cb(err)
      return setDestTimestampsAndMode(srcMode, src, dest, cb)
    })
  }
  return setDestTimestampsAndMode(srcMode, src, dest, cb)
}

function fileIsNotWritable (srcMode) {
  return (srcMode & 0o200) === 0
}

function makeFileWritable (dest, srcMode, cb) {
  return setDestMode(dest, srcMode | 0o200, cb)
}

function setDestTimestampsAndMode (srcMode, src, dest, cb) {
  setDestTimestamps(src, dest, err => {
    if (err) return cb(err)
    return setDestMode(dest, srcMode, cb)
  })
}

function setDestMode (dest, srcMode, cb) {
  return fs.chmod(dest, srcMode, cb)
}

function setDestTimestamps (src, dest, cb) {
  // The initial srcStat.atime cannot be trusted
  // because it is modified by the read(2) system call
  // (See https://nodejs.org/api/fs.html#fs_stat_time_values)
  fs.stat(src, (err, updatedSrcStat) => {
    if (err) return cb(err)
    return utimesMillis(dest, updatedSrcStat.atime, updatedSrcStat.mtime, cb)
  })
}

function onDir (srcStat, destStat, src, dest, opts, cb) {
  if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts, cb)
  return copyDir(src, dest, opts, cb)
}

function mkDirAndCopy (srcMode, src, dest, opts, cb) {
  fs.mkdir(dest, err => {
    if (err) return cb(err)
    copyDir(src, dest, opts, err => {
      if (err) return cb(err)
      return setDestMode(dest, srcMode, cb)
    })
  })
}

function copyDir (src, dest, opts, cb) {
  fs.readdir(src, (err, items) => {
    if (err) return cb(err)
    return copyDirItems(items, src, dest, opts, cb)
  })
}

function copyDirItems (items, src, dest, opts, cb) {
  const item = items.pop()
  if (!item) return cb()
  return copyDirItem(items, item, src, dest, opts, cb)
}

function copyDirItem (items, item, src, dest, opts, cb) {
  const srcItem = path.join(src, item)
  const destItem = path.join(dest, item)
  stat.checkPaths(srcItem, destItem, 'copy', opts, (err, stats) => {
    if (err) return cb(err)
    const { destStat } = stats
    startCopy(destStat, srcItem, destItem, opts, err => {
      if (err) return cb(err)
      return copyDirItems(items, src, dest, opts, cb)
    })
  })
}

function onLink (destStat, src, dest, opts, cb) {
  fs.readlink(src, (err, resolvedSrc) => {
    if (err) return cb(err)
    if (opts.dereference) {
      resolvedSrc = path.resolve(process.cwd(), resolvedSrc)
    }

    if (!destStat) {
      return fs.symlink(resolvedSrc, dest, cb)
    } else {
      fs.readlink(dest, (err, resolvedDest) => {
        if (err) {
          // dest exists and is a regular file or directory,
          // Windows may throw UNKNOWN error. If dest already exists,
          // fs throws error anyway, so no need to guard against it here.
          if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return fs.symlink(resolvedSrc, dest, cb)
          return cb(err)
        }
        if (opts.dereference) {
          resolvedDest = path.resolve(process.cwd(), resolvedDest)
        }
        if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) {
          return cb(new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`))
        }

        // do not copy if src is a subdir of dest since unlinking
        // dest in this case would result in removing src contents
        // and therefore a broken symlink would be created.
        if (destStat.isDirectory() && stat.isSrcSubdir(resolvedDest, resolvedSrc)) {
          return cb(new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`))
        }
        return copyLink(resolvedSrc, dest, cb)
      })
    }
  })
}

function copyLink (resolvedSrc, dest, cb) {
  fs.unlink(dest, err => {
    if (err) return cb(err)
    return fs.symlink(resolvedSrc, dest, cb)
  })
}

module.exports = copy
'use strict'

const u = require('universalify').fromCallback
module.exports = {
  copy: u(require('./copy')),
  copySync: require('./copy-sync')
}
(The MIT License)

Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
 merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
let _fs
try {
  _fs = require('graceful-fs')
} catch (_) {
  _fs = require('fs')
}
const universalify = require('universalify')
const { stringify, stripBom } = require('./utils')

async function _readFile (file, options = {}) {
  if (typeof options === 'string') {
    options = { encoding: options }
  }

  const fs = options.fs || _fs

  const shouldThrow = 'throws' in options ? options.throws : true

  let data = await universalify.fromCallback(fs.readFile)(file, options)

  data = stripBom(data)

  let obj
  try {
    obj = JSON.parse(data, options ? options.reviver : null)
  } catch (err) {
    if (shouldThrow) {
      err.message = `${file}: ${err.message}`
      throw err
    } else {
      return null
    }
  }

  return obj
}

const readFile = universalify.fromPromise(_readFile)

function readFileSync (file, options = {}) {
  if (typeof options === 'string') {
    options = { encoding: options }
  }

  const fs = options.fs || _fs

  const shouldThrow = 'throws' in options ? options.throws : true

  try {
    let content = fs.readFileSync(file, options)
    content = stripBom(content)
    return JSON.parse(content, options.reviver)
  } catch (err) {
    if (shouldThrow) {
      err.message = `${file}: ${err.message}`
      throw err
    } else {
      return null
    }
  }
}

async function _writeFile (file, obj, options = {}) {
  const fs = options.fs || _fs

  const str = stringify(obj, options)

  await universalify.fromCallback(fs.writeFile)(file, str, options)
}

const writeFile = universalify.fromPromise(_writeFile)

function writeFileSync (file, obj, options = {}) {
  const fs = options.fs || _fs

  const str = stringify(obj, options)
  // not sure if fs.writeFileSync returns anything, but just in case
  return fs.writeFileSync(file, str, options)
}

// NOTE: do not change this export format; required for ESM compat
// see https://github.com/jprichardson/node-jsonfile/pull/162 for details
module.exports = {
  readFile,
  readFileSync,
  writeFile,
  writeFileSync
}
{
  "name": "jsonfile",
  "version": "6.2.1",
  "description": "Easily read/write JSON files.",
  "repository": {
    "type": "git",
    "url": "git@github.com:jprichardson/node-jsonfile.git"
  },
  "author": "JP Richardson <jprichardson@gmail.com>",
  "license": "MIT",
  "dependencies": {
    "universalify": "^2.0.0"
  },
  "optionalDependencies": {
    "graceful-fs": "^4.1.6"
  },
  "devDependencies": {
    "mocha": "^8.2.0",
    "rimraf": "^2.4.0",
    "standard": "^16.0.1"
  },
  "main": "index.js",
  "files": [
    "index.js",
    "utils.js"
  ]
}function stringify (obj, { EOL = '\n', finalEOL = true, replacer = null, spaces } = {}) {
  const EOF = finalEOL ? EOL : ''
  const str = JSON.stringify(obj, replacer, spaces)

  if (str === undefined) {
    throw new TypeError(`Converting ${typeof obj} value to JSON is not supported`)
  }

  return str.replace(/\n/g, EOL) + EOF
}

function stripBom (content) {
  // we do this because JSON.parse would convert it to a utf8 string if encoding wasn't specified
  if (Buffer.isBuffer(content)) content = content.toString('utf8')
  return content.replace(/^\uFEFF/, '')
}

module.exports = { stringify, stripBom }
The ISC License

Copyright (c) Isaac Z. Schlueter and Contributors

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
'use strict'

// just pre-load all the stuff that index.js lazily exports
const internalRe = require('./internal/re')
const constants = require('./internal/constants')
const SemVer = require('./classes/semver')
const identifiers = require('./internal/identifiers')
const parse = require('./functions/parse')
const valid = require('./functions/valid')
const clean = require('./functions/clean')
const inc = require('./functions/inc')
const diff = require('./functions/diff')
const major = require('./functions/major')
const minor = require('./functions/minor')
const patch = require('./functions/patch')
const prerelease = require('./functions/prerelease')
const compare = require('./functions/compare')
const rcompare = require('./functions/rcompare')
const compareLoose = require('./functions/compare-loose')
const compareBuild = require('./functions/compare-build')
const sort = require('./functions/sort')
const rsort = require('./functions/rsort')
const gt = require('./functions/gt')
const lt = require('./functions/lt')
const eq = require('./functions/eq')
const neq = require('./functions/neq')
const gte = require('./functions/gte')
const lte = require('./functions/lte')
const cmp = require('./functions/cmp')
const coerce = require('./functions/coerce')
const Comparator = require('./classes/comparator')
const Range = require('./classes/range')
const satisfies = require('./functions/satisfies')
const toComparators = require('./ranges/to-comparators')
const maxSatisfying = require('./ranges/max-satisfying')
const minSatisfying = require('./ranges/min-satisfying')
const minVersion = require('./ranges/min-version')
const validRange = require('./ranges/valid')
const outside = require('./ranges/outside')
const gtr = require('./ranges/gtr')
const ltr = require('./ranges/ltr')
const intersects = require('./ranges/intersects')
const simplifyRange = require('./ranges/simplify')
const subset = require('./ranges/subset')
module.exports = {
  parse,
  valid,
  clean,
  inc,
  diff,
  major,
  minor,
  patch,
  prerelease,
  compare,
  rcompare,
  compareLoose,
  compareBuild,
  sort,
  rsort,
  gt,
  lt,
  eq,
  neq,
  gte,
  lte,
  cmp,
  coerce,
  Comparator,
  Range,
  satisfies,
  toComparators,
  maxSatisfying,
  minSatisfying,
  minVersion,
  validRange,
  outside,
  gtr,
  ltr,
  intersects,
  simplifyRange,
  subset,
  SemVer,
  re: internalRe.re,
  src: internalRe.src,
  tokens: internalRe.t,
  SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION,
  RELEASE_TYPES: constants.RELEASE_TYPES,
  compareIdentifiers: identifiers.compareIdentifiers,
  rcompareIdentifiers: identifiers.rcompareIdentifiers,
}
{
  "name": "semver",
  "version": "7.7.4",
  "description": "The semantic version parser used by npm.",
  "main": "index.js",
  "devDependencies": {
    "@npmcli/eslint-config": "^6.0.0",
    "@npmcli/template-oss": "4.29.0",
    "benchmark": "^2.1.4",
    "tap": "^16.0.0"
  },
  "license": "ISC",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/npm/node-semver.git"
  },
  "bin": {
    "semver": "bin/semver.js"
  },
  "files": [
    "bin/",
    "lib/",
    "classes/",
    "functions/",
    "internal/",
    "ranges/",
    "index.js",
    "preload.js",
    "range.bnf"
  ],
  "tap": {
    "timeout": 30,
    "coverage-map": "map.js",
    "nyc-arg": [
      "--exclude",
      "tap-snapshots/**"
    ]
  },
  "engines": {
    "node": ">=10"
  },
  "author": "GitHub Inc.",
  "templateOSS": {
    "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
    "version": "4.29.0",
    "engines": ">=10",
    "distPaths": [
      "classes/",
      "functions/",
      "internal/",
      "ranges/",
      "index.js",
      "preload.js",
      "range.bnf"
    ],
    "allowPaths": [
      "/classes/",
      "/functions/",
      "/internal/",
      "/ranges/",
      "/index.js",
      "/preload.js",
      "/range.bnf",
      "/benchmarks"
    ],
    "publish": "true"
  }
}'use strict'

// XXX remove in v8 or beyond
module.exports = require('./index.js')
range-set  ::= range ( logical-or range ) *
logical-or ::= ( ' ' ) * '||' ( ' ' ) *
range      ::= hyphen | simple ( ' ' simple ) * | ''
hyphen     ::= partial ' - ' partial
simple     ::= primitive | partial | tilde | caret
primitive  ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
partial    ::= xr ( '.' xr ( '.' xr qualifier ? )? )?
xr         ::= 'x' | 'X' | '*' | nr
nr         ::= '0' | [1-9] ( [0-9] ) *
tilde      ::= '~' partial
caret      ::= '^' partial
qualifier  ::= ( '-' pre )? ( '+' build )?
pre        ::= parts
build      ::= parts
parts      ::= part ( '.' part ) *
part       ::= nr | [-0-9A-Za-z]+
'use strict'

// Determine if version is greater than all the versions possible in the range.
const outside = require('./outside')
const gtr = (version, range, options) => outside(version, range, '>', options)
module.exports = gtr
'use strict'

const Range = require('../classes/range')
const intersects = (r1, r2, options) => {
  r1 = new Range(r1, options)
  r2 = new Range(r2, options)
  return r1.intersects(r2, options)
}
module.exports = intersects
'use strict'

const outside = require('./outside')
// Determine if version is less than all the versions possible in the range
const ltr = (version, range, options) => outside(version, range, '<', options)
module.exports = ltr
'use strict'

const SemVer = require('../classes/semver')
const Range = require('../classes/range')

const maxSatisfying = (versions, range, options) => {
  let max = null
  let maxSV = null
  let rangeObj = null
  try {
    rangeObj = new Range(range, options)
  } catch (er) {
    return null
  }
  versions.forEach((v) => {
    if (rangeObj.test(v)) {
      // satisfies(v, range, options)
      if (!max || maxSV.compare(v) === -1) {
        // compare(max, v, true)
        max = v
        maxSV = new SemVer(max, options)
      }
    }
  })
  return max
}
module.exports = maxSatisfying
'use strict'

const SemVer = require('../classes/semver')
const Range = require('../classes/range')
const minSatisfying = (versions, range, options) => {
  let min = null
  let minSV = null
  let rangeObj = null
  try {
    rangeObj = new Range(range, options)
  } catch (er) {
    return null
  }
  versions.forEach((v) => {
    if (rangeObj.test(v)) {
      // satisfies(v, range, options)
      if (!min || minSV.compare(v) === 1) {
        // compare(min, v, true)
        min = v
        minSV = new SemVer(min, options)
      }
    }
  })
  return min
}
module.exports = minSatisfying
'use strict'

const SemVer = require('../classes/semver')
const Range = require('../classes/range')
const gt = require('../functions/gt')

const minVersion = (range, loose) => {
  range = new Range(range, loose)

  let minver = new SemVer('0.0.0')
  if (range.test(minver)) {
    return minver
  }

  minver = new SemVer('0.0.0-0')
  if (range.test(minver)) {
    return minver
  }

  minver = null
  for (let i = 0; i < range.set.length; ++i) {
    const comparators = range.set[i]

    let setMin = null
    comparators.forEach((comparator) => {
      // Clone to avoid manipulating the comparator's semver object.
      const compver = new SemVer(comparator.semver.version)
      switch (comparator.operator) {
        case '>':
          if (compver.prerelease.length === 0) {
            compver.patch++
          } else {
            compver.prerelease.push(0)
          }
          compver.raw = compver.format()
          /* fallthrough */
        case '':
        case '>=':
          if (!setMin || gt(compver, setMin)) {
            setMin = compver
          }
          break
        case '<':
        case '<=':
          /* Ignore maximum versions */
          break
        /* istanbul ignore next */
        default:
          throw new Error(`Unexpected operation: ${comparator.operator}`)
      }
    })
    if (setMin && (!minver || gt(minver, setMin))) {
      minver = setMin
    }
  }

  if (minver && range.test(minver)) {
    return minver
  }

  return null
}
module.exports = minVersion
'use strict'

const SemVer = require('../classes/semver')
const Comparator = require('../classes/comparator')
const { ANY } = Comparator
const Range = require('../classes/range')
const satisfies = require('../functions/satisfies')
const gt = require('../functions/gt')
const lt = require('../functions/lt')
const lte = require('../functions/lte')
const gte = require('../functions/gte')

const outside = (version, range, hilo, options) => {
  version = new SemVer(version, options)
  range = new Range(range, options)

  let gtfn, ltefn, ltfn, comp, ecomp
  switch (hilo) {
    case '>':
      gtfn = gt
      ltefn = lte
      ltfn = lt
      comp = '>'
      ecomp = '>='
      break
    case '<':
      gtfn = lt
      ltefn = gte
      ltfn = gt
      comp = '<'
      ecomp = '<='
      break
    default:
      throw new TypeError('Must provide a hilo val of "<" or ">"')
  }

  // If it satisfies the range it is not outside
  if (satisfies(version, range, options)) {
    return false
  }

  // From now on, variable terms are as if we're in "gtr" mode.
  // but note that everything is flipped for the "ltr" function.

  for (let i = 0; i < range.set.length; ++i) {
    const comparators = range.set[i]

    let high = null
    let low = null

    comparators.forEach((comparator) => {
      if (comparator.semver === ANY) {
        comparator = new Comparator('>=0.0.0')
      }
      high = high || comparator
      low = low || comparator
      if (gtfn(comparator.semver, high.semver, options)) {
        high = comparator
      } else if (ltfn(comparator.semver, low.semver, options)) {
        low = comparator
      }
    })

    // If the edge version comparator has a operator then our version
    // isn't outside it
    if (high.operator === comp || high.operator === ecomp) {
      return false
    }

    // If the lowest version comparator has an operator and our version
    // is less than it then it isn't higher than the range
    if ((!low.operator || low.operator === comp) &&
        ltefn(version, low.semver)) {
      return false
    } else if (low.operator === ecomp && ltfn(version, low.semver)) {
      return false
    }
  }
  return true
}

module.exports = outside
'use strict'

// given a set of versions and a range, create a "simplified" range
// that includes the same versions that the original range does
// If the original range is shorter than the simplified one, return that.
const satisfies = require('../functions/satisfies.js')
const compare = require('../functions/compare.js')
module.exports = (versions, range, options) => {
  const set = []
  let first = null
  let prev = null
  const v = versions.sort((a, b) => compare(a, b, options))
  for (const version of v) {
    const included = satisfies(version, range, options)
    if (included) {
      prev = version
      if (!first) {
        first = version
      }
    } else {
      if (prev) {
        set.push([first, prev])
      }
      prev = null
      first = null
    }
  }
  if (first) {
    set.push([first, null])
  }

  const ranges = []
  for (const [min, max] of set) {
    if (min === max) {
      ranges.push(min)
    } else if (!max && min === v[0]) {
      ranges.push('*')
    } else if (!max) {
      ranges.push(`>=${min}`)
    } else if (min === v[0]) {
      ranges.push(`<=${max}`)
    } else {
      ranges.push(`${min} - ${max}`)
    }
  }
  const simplified = ranges.join(' || ')
  const original = typeof range.raw === 'string' ? range.raw : String(range)
  return simplified.length < original.length ? simplified : range
}
'use strict'

const Range = require('../classes/range.js')
const Comparator = require('../classes/comparator.js')
const { ANY } = Comparator
const satisfies = require('../functions/satisfies.js')
const compare = require('../functions/compare.js')

// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff:
// - Every simple range `r1, r2, ...` is a null set, OR
// - Every simple range `r1, r2, ...` which is not a null set is a subset of
//   some `R1, R2, ...`
//
// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff:
// - If c is only the ANY comparator
//   - If C is only the ANY comparator, return true
//   - Else if in prerelease mode, return false
//   - else replace c with `[>=0.0.0]`
// - If C is only the ANY comparator
//   - if in prerelease mode, return true
//   - else replace C with `[>=0.0.0]`
// - Let EQ be the set of = comparators in c
// - If EQ is more than one, return true (null set)
// - Let GT be the highest > or >= comparator in c
// - Let LT be the lowest < or <= comparator in c
// - If GT and LT, and GT.semver > LT.semver, return true (null set)
// - If any C is a = range, and GT or LT are set, return false
// - If EQ
//   - If GT, and EQ does not satisfy GT, return true (null set)
//   - If LT, and EQ does not satisfy LT, return true (null set)
//   - If EQ satisfies every C, return true
//   - Else return false
// - If GT
//   - If GT.semver is lower than any > or >= comp in C, return false
//   - If GT is >=, and GT.semver does not satisfy every C, return false
//   - If GT.semver has a prerelease, and not in prerelease mode
//     - If no C has a prerelease and the GT.semver tuple, return false
// - If LT
//   - If LT.semver is greater than any < or <= comp in C, return false
//   - If LT is <=, and LT.semver does not satisfy every C, return false
//   - If LT.semver has a prerelease, and not in prerelease mode
//     - If no C has a prerelease and the LT.semver tuple, return false
// - Else return true

const subset = (sub, dom, options = {}) => {
  if (sub === dom) {
    return true
  }

  sub = new Range(sub, options)
  dom = new Range(dom, options)
  let sawNonNull = false

  OUTER: for (const simpleSub of sub.set) {
    for (const simpleDom of dom.set) {
      const isSub = simpleSubset(simpleSub, simpleDom, options)
      sawNonNull = sawNonNull || isSub !== null
      if (isSub) {
        continue OUTER
      }
    }
    // the null set is a subset of everything, but null simple ranges in
    // a complex range should be ignored.  so if we saw a non-null range,
    // then we know this isn't a subset, but if EVERY simple range was null,
    // then it is a subset.
    if (sawNonNull) {
      return false
    }
  }
  return true
}

const minimumVersionWithPreRelease = [new Comparator('>=0.0.0-0')]
const minimumVersion = [new Comparator('>=0.0.0')]

const simpleSubset = (sub, dom, options) => {
  if (sub === dom) {
    return true
  }

  if (sub.length === 1 && sub[0].semver === ANY) {
    if (dom.length === 1 && dom[0].semver === ANY) {
      return true
    } else if (options.includePrerelease) {
      sub = minimumVersionWithPreRelease
    } else {
      sub = minimumVersion
    }
  }

  if (dom.length === 1 && dom[0].semver === ANY) {
    if (options.includePrerelease) {
      return true
    } else {
      dom = minimumVersion
    }
  }

  const eqSet = new Set()
  let gt, lt
  for (const c of sub) {
    if (c.operator === '>' || c.operator === '>=') {
      gt = higherGT(gt, c, options)
    } else if (c.operator === '<' || c.operator === '<=') {
      lt = lowerLT(lt, c, options)
    } else {
      eqSet.add(c.semver)
    }
  }

  if (eqSet.size > 1) {
    return null
  }

  let gtltComp
  if (gt && lt) {
    gtltComp = compare(gt.semver, lt.semver, options)
    if (gtltComp > 0) {
      return null
    } else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<=')) {
      return null
    }
  }

  // will iterate one or zero times
  for (const eq of eqSet) {
    if (gt && !satisfies(eq, String(gt), options)) {
      return null
    }

    if (lt && !satisfies(eq, String(lt), options)) {
      return null
    }

    for (const c of dom) {
      if (!satisfies(eq, String(c), options)) {
        return false
      }
    }

    return true
  }

  let higher, lower
  let hasDomLT, hasDomGT
  // if the subset has a prerelease, we need a comparator in the superset
  // with the same tuple and a prerelease, or it's not a subset
  let needDomLTPre = lt &&
    !options.includePrerelease &&
    lt.semver.prerelease.length ? lt.semver : false
  let needDomGTPre = gt &&
    !options.includePrerelease &&
    gt.semver.prerelease.length ? gt.semver : false
  // exception: <1.2.3-0 is the same as <1.2.3
  if (needDomLTPre && needDomLTPre.prerelease.length === 1 &&
      lt.operator === '<' && needDomLTPre.prerelease[0] === 0) {
    needDomLTPre = false
  }

  for (const c of dom) {
    hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='
    hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='
    if (gt) {
      if (needDomGTPre) {
        if (c.semver.prerelease && c.semver.prerelease.length &&
            c.semver.major === needDomGTPre.major &&
            c.semver.minor === needDomGTPre.minor &&
            c.semver.patch === needDomGTPre.patch) {
          needDomGTPre = false
        }
      }
      if (c.operator === '>' || c.operator === '>=') {
        higher = higherGT(gt, c, options)
        if (higher === c && higher !== gt) {
          return false
        }
      } else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options)) {
        return false
      }
    }
    if (lt) {
      if (needDomLTPre) {
        if (c.semver.prerelease && c.semver.prerelease.length &&
            c.semver.major === needDomLTPre.major &&
            c.semver.minor === needDomLTPre.minor &&
            c.semver.patch === needDomLTPre.patch) {
          needDomLTPre = false
        }
      }
      if (c.operator === '<' || c.operator === '<=') {
        lower = lowerLT(lt, c, options)
        if (lower === c && lower !== lt) {
          return false
        }
      } else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options)) {
        return false
      }
    }
    if (!c.operator && (lt || gt) && gtltComp !== 0) {
      return false
    }
  }

  // if there was a < or >, and nothing in the dom, then must be false
  // UNLESS it was limited by another range in the other direction.
  // Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0
  if (gt && hasDomLT && !lt && gtltComp !== 0) {
    return false
  }

  if (lt && hasDomGT && !gt && gtltComp !== 0) {
    return false
  }

  // we needed a prerelease range in a specific tuple, but didn't get one
  // then this isn't a subset.  eg >=1.2.3-pre is not a subset of >=1.0.0,
  // because it includes prereleases in the 1.2.3 tuple
  if (needDomGTPre || needDomLTPre) {
    return false
  }

  return true
}

// >=1.2.3 is lower than >1.2.3
const higherGT = (a, b, options) => {
  if (!a) {
    return b
  }
  const comp = compare(a.semver, b.semver, options)
  return comp > 0 ? a
    : comp < 0 ? b
    : b.operator === '>' && a.operator === '>=' ? b
    : a
}

// <=1.2.3 is higher than <1.2.3
const lowerLT = (a, b, options) => {
  if (!a) {
    return b
  }
  const comp = compare(a.semver, b.semver, options)
  return comp < 0 ? a
    : comp > 0 ? b
    : b.operator === '<' && a.operator === '<=' ? b
    : a
}

module.exports = subset
'use strict'

const Range = require('../classes/range')

// Mostly just for testing and legacy API reasons
const toComparators = (range, options) =>
  new Range(range, options).set
    .map(comp => comp.map(c => c.value).join(' ').trim().split(' '))

module.exports = toComparators
'use strict'

const Range = require('../classes/range')
const validRange = (range, options) => {
  try {
    // Return '*' instead of '' so that truthiness works.
    // This will throw if it's invalid anyway
    return new Range(range, options).range || '*'
  } catch (er) {
    return null
  }
}
module.exports = validRange
'use strict'

// Note: this is the semver.org version of the spec that it implements
// Not necessarily the package version of this code.
const SEMVER_SPEC_VERSION = '2.0.0'

const MAX_LENGTH = 256
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
/* istanbul ignore next */ 9007199254740991

// Max safe segment length for coercion.
const MAX_SAFE_COMPONENT_LENGTH = 16

// Max safe length for a build identifier. The max length minus 6 characters for
// the shortest version with a build 0.0.0+BUILD.
const MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6

const RELEASE_TYPES = [
  'major',
  'premajor',
  'minor',
  'preminor',
  'patch',
  'prepatch',
  'prerelease',
]

module.exports = {
  MAX_LENGTH,
  MAX_SAFE_COMPONENT_LENGTH,
  MAX_SAFE_BUILD_LENGTH,
  MAX_SAFE_INTEGER,
  RELEASE_TYPES,
  SEMVER_SPEC_VERSION,
  FLAG_INCLUDE_PRERELEASE: 0b001,
  FLAG_LOOSE: 0b010,
}
'use strict'

const debug = (
  typeof process === 'object' &&
  process.env &&
  process.env.NODE_DEBUG &&
  /\bsemver\b/i.test(process.env.NODE_DEBUG)
) ? (...args) => console.error('SEMVER', ...args)
  : () => {}

module.exports = debug
'use strict'

const numeric = /^[0-9]+$/
const compareIdentifiers = (a, b) => {
  if (typeof a === 'number' && typeof b === 'number') {
    return a === b ? 0 : a < b ? -1 : 1
  }

  const anum = numeric.test(a)
  const bnum = numeric.test(b)

  if (anum && bnum) {
    a = +a
    b = +b
  }

  return a === b ? 0
    : (anum && !bnum) ? -1
    : (bnum && !anum) ? 1
    : a < b ? -1
    : 1
}

const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a)

module.exports = {
  compareIdentifiers,
  rcompareIdentifiers,
}
'use strict'

class LRUCache {
  constructor () {
    this.max = 1000
    this.map = new Map()
  }

  get (key) {
    const value = this.map.get(key)
    if (value === undefined) {
      return undefined
    } else {
      // Remove the key from the map and add it to the end
      this.map.delete(key)
      this.map.set(key, value)
      return value
    }
  }

  delete (key) {
    return this.map.delete(key)
  }

  set (key, value) {
    const deleted = this.delete(key)

    if (!deleted && value !== undefined) {
      // If cache is full, delete the least recently used item
      if (this.map.size >= this.max) {
        const firstKey = this.map.keys().next().value
        this.delete(firstKey)
      }

      this.map.set(key, value)
    }

    return this
  }
}

module.exports = LRUCache
'use strict'

// parse out just the options we care about
const looseOption = Object.freeze({ loose: true })
const emptyOpts = Object.freeze({ })
const parseOptions = options => {
  if (!options) {
    return emptyOpts
  }

  if (typeof options !== 'object') {
    return looseOption
  }

  return options
}
module.exports = parseOptions
'use strict'

const {
  MAX_SAFE_COMPONENT_LENGTH,
  MAX_SAFE_BUILD_LENGTH,
  MAX_LENGTH,
} = require('./constants')
const debug = require('./debug')
exports = module.exports = {}

// The actual regexps go on exports.re
const re = exports.re = []
const safeRe = exports.safeRe = []
const src = exports.src = []
const safeSrc = exports.safeSrc = []
const t = exports.t = {}
let R = 0

const LETTERDASHNUMBER = '[a-zA-Z0-9-]'

// Replace some greedy regex tokens to prevent regex dos issues. These regex are
// used internally via the safeRe object since all inputs in this library get
// normalized first to trim and collapse all extra whitespace. The original
// regexes are exported for userland consumption and lower level usage. A
// future breaking change could export the safer regex only with a note that
// all input should have extra whitespace removed.
const safeRegexReplacements = [
  ['\\s', 1],
  ['\\d', MAX_LENGTH],
  [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
]

const makeSafeRegex = (value) => {
  for (const [token, max] of safeRegexReplacements) {
    value = value
      .split(`${token}*`).join(`${token}{0,${max}}`)
      .split(`${token}+`).join(`${token}{1,${max}}`)
  }
  return value
}

const createToken = (name, value, isGlobal) => {
  const safe = makeSafeRegex(value)
  const index = R++
  debug(name, index, value)
  t[name] = index
  src[index] = value
  safeSrc[index] = safe
  re[index] = new RegExp(value, isGlobal ? 'g' : undefined)
  safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined)
}

// The following Regular Expressions can be used for tokenizing,
// validating, and parsing SemVer version strings.

// ## Numeric Identifier
// A single `0`, or a non-zero digit followed by zero or more digits.

createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*')
createToken('NUMERICIDENTIFIERLOOSE', '\\d+')

// ## Non-numeric Identifier
// Zero or more digits, followed by a letter or hyphen, and then zero or
// more letters, digits, or hyphens.

createToken('NONNUMERICIDENTIFIER', `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`)

// ## Main Version
// Three dot-separated numeric identifiers.

createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` +
                   `(${src[t.NUMERICIDENTIFIER]})\\.` +
                   `(${src[t.NUMERICIDENTIFIER]})`)

createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
                        `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
                        `(${src[t.NUMERICIDENTIFIERLOOSE]})`)

// ## Pre-release Version Identifier
// A numeric identifier, or a non-numeric identifier.
// Non-numeric identifiers include numeric identifiers but can be longer.
// Therefore non-numeric identifiers must go first.

createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NONNUMERICIDENTIFIER]
}|${src[t.NUMERICIDENTIFIER]})`)

createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NONNUMERICIDENTIFIER]
}|${src[t.NUMERICIDENTIFIERLOOSE]})`)

// ## Pre-release Version
// Hyphen, followed by one or more dot-separated pre-release version
// identifiers.

createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]
}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`)

createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]
}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`)

// ## Build Metadata Identifier
// Any combination of digits, letters, or hyphens.

createToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`)

// ## Build Metadata
// Plus sign, followed by one or more period-separated build metadata
// identifiers.

createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER]
}(?:\\.${src[t.BUILDIDENTIFIER]})*))`)

// ## Full Version String
// A main version, followed optionally by a pre-release version and
// build metadata.

// Note that the only major, minor, patch, and pre-release sections of
// the version string are capturing groups.  The build metadata is not a
// capturing group, because it should not ever be used in version
// comparison.

createToken('FULLPLAIN', `v?${src[t.MAINVERSION]
}${src[t.PRERELEASE]}?${
  src[t.BUILD]}?`)

createToken('FULL', `^${src[t.FULLPLAIN]}$`)

// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
// common in the npm registry.
createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE]
}${src[t.PRERELEASELOOSE]}?${
  src[t.BUILD]}?`)

createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`)

createToken('GTLT', '((?:<|>)?=?)')

// Something like "2.*" or "1.2.x".
// Note that "x.x" is a valid xRange identifer, meaning "any version"
// Only the first item is strictly required.
createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`)
createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`)

createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` +
                   `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
                   `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
                   `(?:${src[t.PRERELEASE]})?${
                     src[t.BUILD]}?` +
                   `)?)?`)

createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +
                        `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
                        `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
                        `(?:${src[t.PRERELEASELOOSE]})?${
                          src[t.BUILD]}?` +
                        `)?)?`)

createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`)
createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`)

// Coercion.
// Extract anything that could conceivably be a part of a valid semver
createToken('COERCEPLAIN', `${'(^|[^\\d])' +
              '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
              `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
              `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`)
createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`)
createToken('COERCEFULL', src[t.COERCEPLAIN] +
              `(?:${src[t.PRERELEASE]})?` +
              `(?:${src[t.BUILD]})?` +
              `(?:$|[^\\d])`)
createToken('COERCERTL', src[t.COERCE], true)
createToken('COERCERTLFULL', src[t.COERCEFULL], true)

// Tilde ranges.
// Meaning is "reasonably at or greater than"
createToken('LONETILDE', '(?:~>?)')

createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true)
exports.tildeTrimReplace = '$1~'

createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`)
createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`)

// Caret ranges.
// Meaning is "at least and backwards compatible with"
createToken('LONECARET', '(?:\\^)')

createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true)
exports.caretTrimReplace = '$1^'

createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`)
createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`)

// A simple gt/lt/eq thing, or just "" to indicate "any version"
createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`)
createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`)

// An expression to strip any whitespace between the gtlt and the thing
// it modifies, so that `> 1.2.3` ==> `>1.2.3`
createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT]
}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true)
exports.comparatorTrimReplace = '$1$2$3'

// Something like `1.2.3 - 1.2.4`
// Note that these all use the loose form, because they'll be
// checked against either the strict or loose comparator form
// later.
createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` +
                   `\\s+-\\s+` +
                   `(${src[t.XRANGEPLAIN]})` +
                   `\\s*$`)

createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
                        `\\s+-\\s+` +
                        `(${src[t.XRANGEPLAINLOOSE]})` +
                        `\\s*$`)

// Star ranges basically just allow anything at all.
createToken('STAR', '(<|>)?=?\\s*\\*')
// >=0.0.0 is like a star
createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$')
createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$')
'use strict'

const parse = require('./parse')
const clean = (version, options) => {
  const s = parse(version.trim().replace(/^[=v]+/, ''), options)
  return s ? s.version : null
}
module.exports = clean
'use strict'

const eq = require('./eq')
const neq = require('./neq')
const gt = require('./gt')
const gte = require('./gte')
const lt = require('./lt')
const lte = require('./lte')

const cmp = (a, op, b, loose) => {
  switch (op) {
    case '===':
      if (typeof a === 'object') {
        a = a.version
      }
      if (typeof b === 'object') {
        b = b.version
      }
      return a === b

    case '!==':
      if (typeof a === 'object') {
        a = a.version
      }
      if (typeof b === 'object') {
        b = b.version
      }
      return a !== b

    case '':
    case '=':
    case '==':
      return eq(a, b, loose)

    case '!=':
      return neq(a, b, loose)

    case '>':
      return gt(a, b, loose)

    case '>=':
      return gte(a, b, loose)

    case '<':
      return lt(a, b, loose)

    case '<=':
      return lte(a, b, loose)

    default:
      throw new TypeError(`Invalid operator: ${op}`)
  }
}
module.exports = cmp
'use strict'

const SemVer = require('../classes/semver')
const parse = require('./parse')
const { safeRe: re, t } = require('../internal/re')

const coerce = (version, options) => {
  if (version instanceof SemVer) {
    return version
  }

  if (typeof version === 'number') {
    version = String(version)
  }

  if (typeof version !== 'string') {
    return null
  }

  options = options || {}

  let match = null
  if (!options.rtl) {
    match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE])
  } else {
    // Find the right-most coercible string that does not share
    // a terminus with a more left-ward coercible string.
    // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4'
    // With includePrerelease option set, '1.2.3.4-rc' wants to coerce '2.3.4-rc', not '2.3.4'
    //
    // Walk through the string checking with a /g regexp
    // Manually set the index so as to pick up overlapping matches.
    // Stop when we get a match that ends at the string end, since no
    // coercible string can be more right-ward without the same terminus.
    const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]
    let next
    while ((next = coerceRtlRegex.exec(version)) &&
        (!match || match.index + match[0].length !== version.length)
    ) {
      if (!match ||
            next.index + next[0].length !== match.index + match[0].length) {
        match = next
      }
      coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length
    }
    // leave it in a clean state
    coerceRtlRegex.lastIndex = -1
  }

  if (match === null) {
    return null
  }

  const major = match[2]
  const minor = match[3] || '0'
  const patch = match[4] || '0'
  const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : ''
  const build = options.includePrerelease && match[6] ? `+${match[6]}` : ''

  return parse(`${major}.${minor}.${patch}${prerelease}${build}`, options)
}
module.exports = coerce
'use strict'

const SemVer = require('../classes/semver')
const compareBuild = (a, b, loose) => {
  const versionA = new SemVer(a, loose)
  const versionB = new SemVer(b, loose)
  return versionA.compare(versionB) || versionA.compareBuild(versionB)
}
module.exports = compareBuild
'use strict'

const compare = require('./compare')
const compareLoose = (a, b) => compare(a, b, true)
module.exports = compareLoose
'use strict'

const SemVer = require('../classes/semver')
const compare = (a, b, loose) =>
  new SemVer(a, loose).compare(new SemVer(b, loose))

module.exports = compare
'use strict'

const parse = require('./parse.js')

const diff = (version1, version2) => {
  const v1 = parse(version1, null, true)
  const v2 = parse(version2, null, true)
  const comparison = v1.compare(v2)

  if (comparison === 0) {
    return null
  }

  const v1Higher = comparison > 0
  const highVersion = v1Higher ? v1 : v2
  const lowVersion = v1Higher ? v2 : v1
  const highHasPre = !!highVersion.prerelease.length
  const lowHasPre = !!lowVersion.prerelease.length

  if (lowHasPre && !highHasPre) {
    // Going from prerelease -> no prerelease requires some special casing

    // If the low version has only a major, then it will always be a major
    // Some examples:
    // 1.0.0-1 -> 1.0.0
    // 1.0.0-1 -> 1.1.1
    // 1.0.0-1 -> 2.0.0
    if (!lowVersion.patch && !lowVersion.minor) {
      return 'major'
    }

    // If the main part has no difference
    if (lowVersion.compareMain(highVersion) === 0) {
      if (lowVersion.minor && !lowVersion.patch) {
        return 'minor'
      }
      return 'patch'
    }
  }

  // add the `pre` prefix if we are going to a prerelease version
  const prefix = highHasPre ? 'pre' : ''

  if (v1.major !== v2.major) {
    return prefix + 'major'
  }

  if (v1.minor !== v2.minor) {
    return prefix + 'minor'
  }

  if (v1.patch !== v2.patch) {
    return prefix + 'patch'
  }

  // high and low are prereleases
  return 'prerelease'
}

module.exports = diff
'use strict'

const compare = require('./compare')
const eq = (a, b, loose) => compare(a, b, loose) === 0
module.exports = eq
'use strict'

const compare = require('./compare')
const gt = (a, b, loose) => compare(a, b, loose) > 0
module.exports = gt
'use strict'

const compare = require('./compare')
const gte = (a, b, loose) => compare(a, b, loose) >= 0
module.exports = gte
'use strict'

const SemVer = require('../classes/semver')

const inc = (version, release, options, identifier, identifierBase) => {
  if (typeof (options) === 'string') {
    identifierBase = identifier
    identifier = options
    options = undefined
  }

  try {
    return new SemVer(
      version instanceof SemVer ? version.version : version,
      options
    ).inc(release, identifier, identifierBase).version
  } catch (er) {
    return null
  }
}
module.exports = inc
'use strict'

const compare = require('./compare')
const lt = (a, b, loose) => compare(a, b, loose) < 0
module.exports = lt
'use strict'

const compare = require('./compare')
const lte = (a, b, loose) => compare(a, b, loose) <= 0
module.exports = lte
'use strict'

const SemVer = require('../classes/semver')
const major = (a, loose) => new SemVer(a, loose).major
module.exports = major
'use strict'

const SemVer = require('../classes/semver')
const minor = (a, loose) => new SemVer(a, loose).minor
module.exports = minor
'use strict'

const compare = require('./compare')
const neq = (a, b, loose) => compare(a, b, loose) !== 0
module.exports = neq
'use strict'

const SemVer = require('../classes/semver')
const parse = (version, options, throwErrors = false) => {
  if (version instanceof SemVer) {
    return version
  }
  try {
    return new SemVer(version, options)
  } catch (er) {
    if (!throwErrors) {
      return null
    }
    throw er
  }
}

module.exports = parse
'use strict'

const SemVer = require('../classes/semver')
const patch = (a, loose) => new SemVer(a, loose).patch
module.exports = patch
'use strict'

const parse = require('./parse')
const prerelease = (version, options) => {
  const parsed = parse(version, options)
  return (parsed && parsed.prerelease.length) ? parsed.prerelease : null
}
module.exports = prerelease
'use strict'

const compare = require('./compare')
const rcompare = (a, b, loose) => compare(b, a, loose)
module.exports = rcompare
'use strict'

const compareBuild = require('./compare-build')
const rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose))
module.exports = rsort
'use strict'

const Range = require('../classes/range')
const satisfies = (version, range, options) => {
  try {
    range = new Range(range, options)
  } catch (er) {
    return false
  }
  return range.test(version)
}
module.exports = satisfies
'use strict'

const compareBuild = require('./compare-build')
const sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose))
module.exports = sort
'use strict'

const parse = require('./parse')
const valid = (version, options) => {
  const v = parse(version, options)
  return v ? v.version : null
}
module.exports = valid
'use strict'

const ANY = Symbol('SemVer ANY')
// hoisted class for cyclic dependency
class Comparator {
  static get ANY () {
    return ANY
  }

  constructor (comp, options) {
    options = parseOptions(options)

    if (comp instanceof Comparator) {
      if (comp.loose === !!options.loose) {
        return comp
      } else {
        comp = comp.value
      }
    }

    comp = comp.trim().split(/\s+/).join(' ')
    debug('comparator', comp, options)
    this.options = options
    this.loose = !!options.loose
    this.parse(comp)

    if (this.semver === ANY) {
      this.value = ''
    } else {
      this.value = this.operator + this.semver.version
    }

    debug('comp', this)
  }

  parse (comp) {
    const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]
    const m = comp.match(r)

    if (!m) {
      throw new TypeError(`Invalid comparator: ${comp}`)
    }

    this.operator = m[1] !== undefined ? m[1] : ''
    if (this.operator === '=') {
      this.operator = ''
    }

    // if it literally is just '>' or '' then allow anything.
    if (!m[2]) {
      this.semver = ANY
    } else {
      this.semver = new SemVer(m[2], this.options.loose)
    }
  }

  toString () {
    return this.value
  }

  test (version) {
    debug('Comparator.test', version, this.options.loose)

    if (this.semver === ANY || version === ANY) {
      return true
    }

    if (typeof version === 'string') {
      try {
        version = new SemVer(version, this.options)
      } catch (er) {
        return false
      }
    }

    return cmp(version, this.operator, this.semver, this.options)
  }

  intersects (comp, options) {
    if (!(comp instanceof Comparator)) {
      throw new TypeError('a Comparator is required')
    }

    if (this.operator === '') {
      if (this.value === '') {
        return true
      }
      return new Range(comp.value, options).test(this.value)
    } else if (comp.operator === '') {
      if (comp.value === '') {
        return true
      }
      return new Range(this.value, options).test(comp.semver)
    }

    options = parseOptions(options)

    // Special cases where nothing can possibly be lower
    if (options.includePrerelease &&
      (this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) {
      return false
    }
    if (!options.includePrerelease &&
      (this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) {
      return false
    }

    // Same direction increasing (> or >=)
    if (this.operator.startsWith('>') && comp.operator.startsWith('>')) {
      return true
    }
    // Same direction decreasing (< or <=)
    if (this.operator.startsWith('<') && comp.operator.startsWith('<')) {
      return true
    }
    // same SemVer and both sides are inclusive (<= or >=)
    if (
      (this.semver.version === comp.semver.version) &&
      this.operator.includes('=') && comp.operator.includes('=')) {
      return true
    }
    // opposite directions less than
    if (cmp(this.semver, '<', comp.semver, options) &&
      this.operator.startsWith('>') && comp.operator.startsWith('<')) {
      return true
    }
    // opposite directions greater than
    if (cmp(this.semver, '>', comp.semver, options) &&
      this.operator.startsWith('<') && comp.operator.startsWith('>')) {
      return true
    }
    return false
  }
}

module.exports = Comparator

const parseOptions = require('../internal/parse-options')
const { safeRe: re, t } = require('../internal/re')
const cmp = require('../functions/cmp')
const debug = require('../internal/debug')
const SemVer = require('./semver')
const Range = require('./range')
'use strict'

module.exports = {
  SemVer: require('./semver.js'),
  Range: require('./range.js'),
  Comparator: require('./comparator.js'),
}
'use strict'

const SPACE_CHARACTERS = /\s+/g

// hoisted class for cyclic dependency
class Range {
  constructor (range, options) {
    options = parseOptions(options)

    if (range instanceof Range) {
      if (
        range.loose === !!options.loose &&
        range.includePrerelease === !!options.includePrerelease
      ) {
        return range
      } else {
        return new Range(range.raw, options)
      }
    }

    if (range instanceof Comparator) {
      // just put it in the set and return
      this.raw = range.value
      this.set = [[range]]
      this.formatted = undefined
      return this
    }

    this.options = options
    this.loose = !!options.loose
    this.includePrerelease = !!options.includePrerelease

    // First reduce all whitespace as much as possible so we do not have to rely
    // on potentially slow regexes like \s*. This is then stored and used for
    // future error messages as well.
    this.raw = range.trim().replace(SPACE_CHARACTERS, ' ')

    // First, split on ||
    this.set = this.raw
      .split('||')
      // map the range to a 2d array of comparators
      .map(r => this.parseRange(r.trim()))
      // throw out any comparator lists that are empty
      // this generally means that it was not a valid range, which is allowed
      // in loose mode, but will still throw if the WHOLE range is invalid.
      .filter(c => c.length)

    if (!this.set.length) {
      throw new TypeError(`Invalid SemVer Range: ${this.raw}`)
    }

    // if we have any that are not the null set, throw out null sets.
    if (this.set.length > 1) {
      // keep the first one, in case they're all null sets
      const first = this.set[0]
      this.set = this.set.filter(c => !isNullSet(c[0]))
      if (this.set.length === 0) {
        this.set = [first]
      } else if (this.set.length > 1) {
        // if we have any that are *, then the range is just *
        for (const c of this.set) {
          if (c.length === 1 && isAny(c[0])) {
            this.set = [c]
            break
          }
        }
      }
    }

    this.formatted = undefined
  }

  get range () {
    if (this.formatted === undefined) {
      this.formatted = ''
      for (let i = 0; i < this.set.length; i++) {
        if (i > 0) {
          this.formatted += '||'
        }
        const comps = this.set[i]
        for (let k = 0; k < comps.length; k++) {
          if (k > 0) {
            this.formatted += ' '
          }
          this.formatted += comps[k].toString().trim()
        }
      }
    }
    return this.formatted
  }

  format () {
    return this.range
  }

  toString () {
    return this.range
  }

  parseRange (range) {
    // memoize range parsing for performance.
    // this is a very hot path, and fully deterministic.
    const memoOpts =
      (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) |
      (this.options.loose && FLAG_LOOSE)
    const memoKey = memoOpts + ':' + range
    const cached = cache.get(memoKey)
    if (cached) {
      return cached
    }

    const loose = this.options.loose
    // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
    const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]
    range = range.replace(hr, hyphenReplace(this.options.includePrerelease))
    debug('hyphen replace', range)

    // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
    range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace)
    debug('comparator trim', range)

    // `~ 1.2.3` => `~1.2.3`
    range = range.replace(re[t.TILDETRIM], tildeTrimReplace)
    debug('tilde trim', range)

    // `^ 1.2.3` => `^1.2.3`
    range = range.replace(re[t.CARETTRIM], caretTrimReplace)
    debug('caret trim', range)

    // At this point, the range is completely trimmed and
    // ready to be split into comparators.

    let rangeList = range
      .split(' ')
      .map(comp => parseComparator(comp, this.options))
      .join(' ')
      .split(/\s+/)
      // >=0.0.0 is equivalent to *
      .map(comp => replaceGTE0(comp, this.options))

    if (loose) {
      // in loose mode, throw out any that are not valid comparators
      rangeList = rangeList.filter(comp => {
        debug('loose invalid filter', comp, this.options)
        return !!comp.match(re[t.COMPARATORLOOSE])
      })
    }
    debug('range list', rangeList)

    // if any comparators are the null set, then replace with JUST null set
    // if more than one comparator, remove any * comparators
    // also, don't include the same comparator more than once
    const rangeMap = new Map()
    const comparators = rangeList.map(comp => new Comparator(comp, this.options))
    for (const comp of comparators) {
      if (isNullSet(comp)) {
        return [comp]
      }
      rangeMap.set(comp.value, comp)
    }
    if (rangeMap.size > 1 && rangeMap.has('')) {
      rangeMap.delete('')
    }

    const result = [...rangeMap.values()]
    cache.set(memoKey, result)
    return result
  }

  intersects (range, options) {
    if (!(range instanceof Range)) {
      throw new TypeError('a Range is required')
    }

    return this.set.some((thisComparators) => {
      return (
        isSatisfiable(thisComparators, options) &&
        range.set.some((rangeComparators) => {
          return (
            isSatisfiable(rangeComparators, options) &&
            thisComparators.every((thisComparator) => {
              return rangeComparators.every((rangeComparator) => {
                return thisComparator.intersects(rangeComparator, options)
              })
            })
          )
        })
      )
    })
  }

  // if ANY of the sets match ALL of its comparators, then pass
  test (version) {
    if (!version) {
      return false
    }

    if (typeof version === 'string') {
      try {
        version = new SemVer(version, this.options)
      } catch (er) {
        return false
      }
    }

    for (let i = 0; i < this.set.length; i++) {
      if (testSet(this.set[i], version, this.options)) {
        return true
      }
    }
    return false
  }
}

module.exports = Range

const LRU = require('../internal/lrucache')
const cache = new LRU()

const parseOptions = require('../internal/parse-options')
const Comparator = require('./comparator')
const debug = require('../internal/debug')
const SemVer = require('./semver')
const {
  safeRe: re,
  t,
  comparatorTrimReplace,
  tildeTrimReplace,
  caretTrimReplace,
} = require('../internal/re')
const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require('../internal/constants')

const isNullSet = c => c.value === '<0.0.0-0'
const isAny = c => c.value === ''

// take a set of comparators and determine whether there
// exists a version which can satisfy it
const isSatisfiable = (comparators, options) => {
  let result = true
  const remainingComparators = comparators.slice()
  let testComparator = remainingComparators.pop()

  while (result && remainingComparators.length) {
    result = remainingComparators.every((otherComparator) => {
      return testComparator.intersects(otherComparator, options)
    })

    testComparator = remainingComparators.pop()
  }

  return result
}

// comprised of xranges, tildes, stars, and gtlt's at this point.
// already replaced the hyphen ranges
// turn into a set of JUST comparators.
const parseComparator = (comp, options) => {
  comp = comp.replace(re[t.BUILD], '')
  debug('comp', comp, options)
  comp = replaceCarets(comp, options)
  debug('caret', comp)
  comp = replaceTildes(comp, options)
  debug('tildes', comp)
  comp = replaceXRanges(comp, options)
  debug('xrange', comp)
  comp = replaceStars(comp, options)
  debug('stars', comp)
  return comp
}

const isX = id => !id || id.toLowerCase() === 'x' || id === '*'

// ~, ~> --> * (any, kinda silly)
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0
// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0
// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0
// ~0.0.1 --> >=0.0.1 <0.1.0-0
const replaceTildes = (comp, options) => {
  return comp
    .trim()
    .split(/\s+/)
    .map((c) => replaceTilde(c, options))
    .join(' ')
}

const replaceTilde = (comp, options) => {
  const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]
  return comp.replace(r, (_, M, m, p, pr) => {
    debug('tilde', comp, _, M, m, p, pr)
    let ret

    if (isX(M)) {
      ret = ''
    } else if (isX(m)) {
      ret = `>=${M}.0.0 <${+M + 1}.0.0-0`
    } else if (isX(p)) {
      // ~1.2 == >=1.2.0 <1.3.0-0
      ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`
    } else if (pr) {
      debug('replaceTilde pr', pr)
      ret = `>=${M}.${m}.${p}-${pr
      } <${M}.${+m + 1}.0-0`
    } else {
      // ~1.2.3 == >=1.2.3 <1.3.0-0
      ret = `>=${M}.${m}.${p
      } <${M}.${+m + 1}.0-0`
    }

    debug('tilde return', ret)
    return ret
  })
}

// ^ --> * (any, kinda silly)
// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0
// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0
// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0
// ^1.2.3 --> >=1.2.3 <2.0.0-0
// ^1.2.0 --> >=1.2.0 <2.0.0-0
// ^0.0.1 --> >=0.0.1 <0.0.2-0
// ^0.1.0 --> >=0.1.0 <0.2.0-0
const replaceCarets = (comp, options) => {
  return comp
    .trim()
    .split(/\s+/)
    .map((c) => replaceCaret(c, options))
    .join(' ')
}

const replaceCaret = (comp, options) => {
  debug('caret', comp, options)
  const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]
  const z = options.includePrerelease ? '-0' : ''
  return comp.replace(r, (_, M, m, p, pr) => {
    debug('caret', comp, _, M, m, p, pr)
    let ret

    if (isX(M)) {
      ret = ''
    } else if (isX(m)) {
      ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`
    } else if (isX(p)) {
      if (M === '0') {
        ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`
      } else {
        ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`
      }
    } else if (pr) {
      debug('replaceCaret pr', pr)
      if (M === '0') {
        if (m === '0') {
          ret = `>=${M}.${m}.${p}-${pr
          } <${M}.${m}.${+p + 1}-0`
        } else {
          ret = `>=${M}.${m}.${p}-${pr
          } <${M}.${+m + 1}.0-0`
        }
      } else {
        ret = `>=${M}.${m}.${p}-${pr
        } <${+M + 1}.0.0-0`
      }
    } else {
      debug('no pr')
      if (M === '0') {
        if (m === '0') {
          ret = `>=${M}.${m}.${p
          }${z} <${M}.${m}.${+p + 1}-0`
        } else {
          ret = `>=${M}.${m}.${p
          }${z} <${M}.${+m + 1}.0-0`
        }
      } else {
        ret = `>=${M}.${m}.${p
        } <${+M + 1}.0.0-0`
      }
    }

    debug('caret return', ret)
    return ret
  })
}

const replaceXRanges = (comp, options) => {
  debug('replaceXRanges', comp, options)
  return comp
    .split(/\s+/)
    .map((c) => replaceXRange(c, options))
    .join(' ')
}

const replaceXRange = (comp, options) => {
  comp = comp.trim()
  const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]
  return comp.replace(r, (ret, gtlt, M, m, p, pr) => {
    debug('xRange', comp, ret, gtlt, M, m, p, pr)
    const xM = isX(M)
    const xm = xM || isX(m)
    const xp = xm || isX(p)
    const anyX = xp

    if (gtlt === '=' && anyX) {
      gtlt = ''
    }

    // if we're including prereleases in the match, then we need
    // to fix this to -0, the lowest possible prerelease value
    pr = options.includePrerelease ? '-0' : ''

    if (xM) {
      if (gtlt === '>' || gtlt === '<') {
        // nothing is allowed
        ret = '<0.0.0-0'
      } else {
        // nothing is forbidden
        ret = '*'
      }
    } else if (gtlt && anyX) {
      // we know patch is an x, because we have any x at all.
      // replace X with 0
      if (xm) {
        m = 0
      }
      p = 0

      if (gtlt === '>') {
        // >1 => >=2.0.0
        // >1.2 => >=1.3.0
        gtlt = '>='
        if (xm) {
          M = +M + 1
          m = 0
          p = 0
        } else {
          m = +m + 1
          p = 0
        }
      } else if (gtlt === '<=') {
        // <=0.7.x is actually <0.8.0, since any 0.7.x should
        // pass.  Similarly, <=7.x is actually <8.0.0, etc.
        gtlt = '<'
        if (xm) {
          M = +M + 1
        } else {
          m = +m + 1
        }
      }

      if (gtlt === '<') {
        pr = '-0'
      }

      ret = `${gtlt + M}.${m}.${p}${pr}`
    } else if (xm) {
      ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`
    } else if (xp) {
      ret = `>=${M}.${m}.0${pr
      } <${M}.${+m + 1}.0-0`
    }

    debug('xRange return', ret)

    return ret
  })
}

// Because * is AND-ed with everything else in the comparator,
// and '' means "any version", just remove the *s entirely.
const replaceStars = (comp, options) => {
  debug('replaceStars', comp, options)
  // Looseness is ignored here.  star is always as loose as it gets!
  return comp
    .trim()
    .replace(re[t.STAR], '')
}

const replaceGTE0 = (comp, options) => {
  debug('replaceGTE0', comp, options)
  return comp
    .trim()
    .replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], '')
}

// This function is passed to string.replace(re[t.HYPHENRANGE])
// M, m, patch, prerelease, build
// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
// 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do
// 1.2 - 3.4 => >=1.2.0 <3.5.0-0
// TODO build?
const hyphenReplace = incPr => ($0,
  from, fM, fm, fp, fpr, fb,
  to, tM, tm, tp, tpr) => {
  if (isX(fM)) {
    from = ''
  } else if (isX(fm)) {
    from = `>=${fM}.0.0${incPr ? '-0' : ''}`
  } else if (isX(fp)) {
    from = `>=${fM}.${fm}.0${incPr ? '-0' : ''}`
  } else if (fpr) {
    from = `>=${from}`
  } else {
    from = `>=${from}${incPr ? '-0' : ''}`
  }

  if (isX(tM)) {
    to = ''
  } else if (isX(tm)) {
    to = `<${+tM + 1}.0.0-0`
  } else if (isX(tp)) {
    to = `<${tM}.${+tm + 1}.0-0`
  } else if (tpr) {
    to = `<=${tM}.${tm}.${tp}-${tpr}`
  } else if (incPr) {
    to = `<${tM}.${tm}.${+tp + 1}-0`
  } else {
    to = `<=${to}`
  }

  return `${from} ${to}`.trim()
}

const testSet = (set, version, options) => {
  for (let i = 0; i < set.length; i++) {
    if (!set[i].test(version)) {
      return false
    }
  }

  if (version.prerelease.length && !options.includePrerelease) {
    // Find the set of versions that are allowed to have prereleases
    // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
    // That should allow `1.2.3-pr.2` to pass.
    // However, `1.2.4-alpha.notready` should NOT be allowed,
    // even though it's within the range set by the comparators.
    for (let i = 0; i < set.length; i++) {
      debug(set[i].semver)
      if (set[i].semver === Comparator.ANY) {
        continue
      }

      if (set[i].semver.prerelease.length > 0) {
        const allowed = set[i].semver
        if (allowed.major === version.major &&
            allowed.minor === version.minor &&
            allowed.patch === version.patch) {
          return true
        }
      }
    }

    // Version has a -pre, but it's not one of the ones we like.
    return false
  }

  return true
}
'use strict'

const debug = require('../internal/debug')
const { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants')
const { safeRe: re, t } = require('../internal/re')

const parseOptions = require('../internal/parse-options')
const { compareIdentifiers } = require('../internal/identifiers')
class SemVer {
  constructor (version, options) {
    options = parseOptions(options)

    if (version instanceof SemVer) {
      if (version.loose === !!options.loose &&
        version.includePrerelease === !!options.includePrerelease) {
        return version
      } else {
        version = version.version
      }
    } else if (typeof version !== 'string') {
      throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`)
    }

    if (version.length > MAX_LENGTH) {
      throw new TypeError(
        `version is longer than ${MAX_LENGTH} characters`
      )
    }

    debug('SemVer', version, options)
    this.options = options
    this.loose = !!options.loose
    // this isn't actually relevant for versions, but keep it so that we
    // don't run into trouble passing this.options around.
    this.includePrerelease = !!options.includePrerelease

    const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL])

    if (!m) {
      throw new TypeError(`Invalid Version: ${version}`)
    }

    this.raw = version

    // these are actually numbers
    this.major = +m[1]
    this.minor = +m[2]
    this.patch = +m[3]

    if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
      throw new TypeError('Invalid major version')
    }

    if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
      throw new TypeError('Invalid minor version')
    }

    if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
      throw new TypeError('Invalid patch version')
    }

    // numberify any prerelease numeric ids
    if (!m[4]) {
      this.prerelease = []
    } else {
      this.prerelease = m[4].split('.').map((id) => {
        if (/^[0-9]+$/.test(id)) {
          const num = +id
          if (num >= 0 && num < MAX_SAFE_INTEGER) {
            return num
          }
        }
        return id
      })
    }

    this.build = m[5] ? m[5].split('.') : []
    this.format()
  }

  format () {
    this.version = `${this.major}.${this.minor}.${this.patch}`
    if (this.prerelease.length) {
      this.version += `-${this.prerelease.join('.')}`
    }
    return this.version
  }

  toString () {
    return this.version
  }

  compare (other) {
    debug('SemVer.compare', this.version, this.options, other)
    if (!(other instanceof SemVer)) {
      if (typeof other === 'string' && other === this.version) {
        return 0
      }
      other = new SemVer(other, this.options)
    }

    if (other.version === this.version) {
      return 0
    }

    return this.compareMain(other) || this.comparePre(other)
  }

  compareMain (other) {
    if (!(other instanceof SemVer)) {
      other = new SemVer(other, this.options)
    }

    if (this.major < other.major) {
      return -1
    }
    if (this.major > other.major) {
      return 1
    }
    if (this.minor < other.minor) {
      return -1
    }
    if (this.minor > other.minor) {
      return 1
    }
    if (this.patch < other.patch) {
      return -1
    }
    if (this.patch > other.patch) {
      return 1
    }
    return 0
  }

  comparePre (other) {
    if (!(other instanceof SemVer)) {
      other = new SemVer(other, this.options)
    }

    // NOT having a prerelease is > having one
    if (this.prerelease.length && !other.prerelease.length) {
      return -1
    } else if (!this.prerelease.length && other.prerelease.length) {
      return 1
    } else if (!this.prerelease.length && !other.prerelease.length) {
      return 0
    }

    let i = 0
    do {
      const a = this.prerelease[i]
      const b = other.prerelease[i]
      debug('prerelease compare', i, a, b)
      if (a === undefined && b === undefined) {
        return 0
      } else if (b === undefined) {
        return 1
      } else if (a === undefined) {
        return -1
      } else if (a === b) {
        continue
      } else {
        return compareIdentifiers(a, b)
      }
    } while (++i)
  }

  compareBuild (other) {
    if (!(other instanceof SemVer)) {
      other = new SemVer(other, this.options)
    }

    let i = 0
    do {
      const a = this.build[i]
      const b = other.build[i]
      debug('build compare', i, a, b)
      if (a === undefined && b === undefined) {
        return 0
      } else if (b === undefined) {
        return 1
      } else if (a === undefined) {
        return -1
      } else if (a === b) {
        continue
      } else {
        return compareIdentifiers(a, b)
      }
    } while (++i)
  }

  // preminor will bump the version up to the next minor release, and immediately
  // down to pre-release. premajor and prepatch work the same way.
  inc (release, identifier, identifierBase) {
    if (release.startsWith('pre')) {
      if (!identifier && identifierBase === false) {
        throw new Error('invalid increment argument: identifier is empty')
      }
      // Avoid an invalid semver results
      if (identifier) {
        const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE])
        if (!match || match[1] !== identifier) {
          throw new Error(`invalid identifier: ${identifier}`)
        }
      }
    }

    switch (release) {
      case 'premajor':
        this.prerelease.length = 0
        this.patch = 0
        this.minor = 0
        this.major++
        this.inc('pre', identifier, identifierBase)
        break
      case 'preminor':
        this.prerelease.length = 0
        this.patch = 0
        this.minor++
        this.inc('pre', identifier, identifierBase)
        break
      case 'prepatch':
        // If this is already a prerelease, it will bump to the next version
        // drop any prereleases that might already exist, since they are not
        // relevant at this point.
        this.prerelease.length = 0
        this.inc('patch', identifier, identifierBase)
        this.inc('pre', identifier, identifierBase)
        break
      // If the input is a non-prerelease version, this acts the same as
      // prepatch.
      case 'prerelease':
        if (this.prerelease.length === 0) {
          this.inc('patch', identifier, identifierBase)
        }
        this.inc('pre', identifier, identifierBase)
        break
      case 'release':
        if (this.prerelease.length === 0) {
          throw new Error(`version ${this.raw} is not a prerelease`)
        }
        this.prerelease.length = 0
        break

      case 'major':
        // If this is a pre-major version, bump up to the same major version.
        // Otherwise increment major.
        // 1.0.0-5 bumps to 1.0.0
        // 1.1.0 bumps to 2.0.0
        if (
          this.minor !== 0 ||
          this.patch !== 0 ||
          this.prerelease.length === 0
        ) {
          this.major++
        }
        this.minor = 0
        this.patch = 0
        this.prerelease = []
        break
      case 'minor':
        // If this is a pre-minor version, bump up to the same minor version.
        // Otherwise increment minor.
        // 1.2.0-5 bumps to 1.2.0
        // 1.2.1 bumps to 1.3.0
        if (this.patch !== 0 || this.prerelease.length === 0) {
          this.minor++
        }
        this.patch = 0
        this.prerelease = []
        break
      case 'patch':
        // If this is not a pre-release version, it will increment the patch.
        // If it is a pre-release it will bump up to the same patch version.
        // 1.2.0-5 patches to 1.2.0
        // 1.2.0 patches to 1.2.1
        if (this.prerelease.length === 0) {
          this.patch++
        }
        this.prerelease = []
        break
      // This probably shouldn't be used publicly.
      // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.
      case 'pre': {
        const base = Number(identifierBase) ? 1 : 0

        if (this.prerelease.length === 0) {
          this.prerelease = [base]
        } else {
          let i = this.prerelease.length
          while (--i >= 0) {
            if (typeof this.prerelease[i] === 'number') {
              this.prerelease[i]++
              i = -2
            }
          }
          if (i === -1) {
            // didn't increment anything
            if (identifier === this.prerelease.join('.') && identifierBase === false) {
              throw new Error('invalid increment argument: identifier already exists')
            }
            this.prerelease.push(base)
          }
        }
        if (identifier) {
          // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
          // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
          let prerelease = [identifier, base]
          if (identifierBase === false) {
            prerelease = [identifier]
          }
          if (compareIdentifiers(this.prerelease[0], identifier) === 0) {
            if (isNaN(this.prerelease[1])) {
              this.prerelease = prerelease
            }
          } else {
            this.prerelease = prerelease
          }
        }
        break
      }
      default:
        throw new Error(`invalid increment argument: ${release}`)
    }
    this.raw = this.format()
    if (this.build.length) {
      this.raw += `+${this.build.join('.')}`
    }
    return this
  }
}

module.exports = SemVer
#!/usr/bin/env node
// Standalone semver comparison program.
// Exits successfully and prints matching version(s) if
// any supplied version is valid and passes all tests.

'use strict'

const argv = process.argv.slice(2)

let versions = []

const range = []

let inc = null

const version = require('../package.json').version

let loose = false

let includePrerelease = false

let coerce = false

let rtl = false

let identifier

let identifierBase

const semver = require('../')
const parseOptions = require('../internal/parse-options')

let reverse = false

let options = {}

const main = () => {
  if (!argv.length) {
    return help()
  }
  while (argv.length) {
    let a = argv.shift()
    const indexOfEqualSign = a.indexOf('=')
    if (indexOfEqualSign !== -1) {
      const value = a.slice(indexOfEqualSign + 1)
      a = a.slice(0, indexOfEqualSign)
      argv.unshift(value)
    }
    switch (a) {
      case '-rv': case '-rev': case '--rev': case '--reverse':
        reverse = true
        break
      case '-l': case '--loose':
        loose = true
        break
      case '-p': case '--include-prerelease':
        includePrerelease = true
        break
      case '-v': case '--version':
        versions.push(argv.shift())
        break
      case '-i': case '--inc': case '--increment':
        switch (argv[0]) {
          case 'major': case 'minor': case 'patch': case 'prerelease':
          case 'premajor': case 'preminor': case 'prepatch':
          case 'release':
            inc = argv.shift()
            break
          default:
            inc = 'patch'
            break
        }
        break
      case '--preid':
        identifier = argv.shift()
        break
      case '-r': case '--range':
        range.push(argv.shift())
        break
      case '-n':
        identifierBase = argv.shift()
        if (identifierBase === 'false') {
          identifierBase = false
        }
        break
      case '-c': case '--coerce':
        coerce = true
        break
      case '--rtl':
        rtl = true
        break
      case '--ltr':
        rtl = false
        break
      case '-h': case '--help': case '-?':
        return help()
      default:
        versions.push(a)
        break
    }
  }

  options = parseOptions({ loose, includePrerelease, rtl })

  versions = versions.map((v) => {
    return coerce ? (semver.coerce(v, options) || { version: v }).version : v
  }).filter((v) => {
    return semver.valid(v, options)
  })
  if (!versions.length) {
    return fail()
  }
  if (inc && (versions.length !== 1 || range.length)) {
    return failInc()
  }

  for (let i = 0, l = range.length; i < l; i++) {
    versions = versions.filter((v) => {
      return semver.satisfies(v, range[i], options)
    })
    if (!versions.length) {
      return fail()
    }
  }
  versions
    .sort((a, b) => semver[reverse ? 'rcompare' : 'compare'](a, b, options))
    .map(v => semver.clean(v, options))
    .map(v => inc ? semver.inc(v, inc, options, identifier, identifierBase) : v)
    .forEach(v => console.log(v))
}

const failInc = () => {
  console.error('--inc can only be used on a single version with no range')
  fail()
}

const fail = () => process.exit(1)

const help = () => console.log(
`SemVer ${version}

A JavaScript implementation of the https://semver.org/ specification
Copyright Isaac Z. Schlueter

Usage: semver [options] <version> [<version> [...]]
Prints valid versions sorted by SemVer precedence

Options:
-r --range <range>
        Print versions that match the specified range.

-i --increment [<level>]
        Increment a version by the specified level.  Level can
        be one of: major, minor, patch, premajor, preminor,
        prepatch, prerelease, or release.  Default level is 'patch'.
        Only one version may be specified.

--preid <identifier>
        Identifier to be used to prefix premajor, preminor,
        prepatch or prerelease version increments.

-l --loose
        Interpret versions and ranges loosely

-p --include-prerelease
        Always include prerelease versions in range matching

-c --coerce
        Coerce a string into SemVer if possible
        (does not imply --loose)

--rtl
        Coerce version strings right to left

--ltr
        Coerce version strings left to right (default)

-n <base>
        Base number to be used for the prerelease identifier.
        Can be either 0 or 1, or false to omit the number altogether.
        Defaults to 0.

Program exits successfully if any valid version satisfies
all supplied ranges, and prints all satisfying versions.

If no satisfying versions are found, then exits failure.

Versions are printed in ascending order, so supplying
multiple versions to the utility will just sort them.`)

main()
(The MIT License)

Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the 'Software'), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict'

exports.fromCallback = function (fn) {
  return Object.defineProperty(function (...args) {
    if (typeof args[args.length - 1] === 'function') fn.apply(this, args)
    else {
      return new Promise((resolve, reject) => {
        args.push((err, res) => (err != null) ? reject(err) : resolve(res))
        fn.apply(this, args)
      })
    }
  }, 'name', { value: fn.name })
}

exports.fromPromise = function (fn) {
  return Object.defineProperty(function (...args) {
    const cb = args[args.length - 1]
    if (typeof cb !== 'function') return fn.apply(this, args)
    else {
      args.pop()
      fn.apply(this, args).then(r => cb(null, r), cb)
    }
  }, 'name', { value: fn.name })
}
{
  "name": "universalify",
  "version": "2.0.1",
  "description": "Make a callback- or promise-based function support both promises and callbacks.",
  "homepage": "https://github.com/RyanZim/universalify#readme",
  "license": "MIT",
  "author": "Ryan Zimmerman <opensrc@ryanzim.com>",
  "files": [
    "index.js"
  ],
  "repository": {
    "type": "git",
    "url": "git+https://github.com/RyanZim/universalify.git"
  },
  "devDependencies": {
    "colortape": "^0.1.2",
    "coveralls": "^3.0.1",
    "nyc": "^15.0.0",
    "standard": "^14.3.1",
    "tape": "^5.0.1"
  },
  "engines": {
    "node": ">= 10.0.0"
  }
}