diff --git a/package-lock.json b/package-lock.json index 0f4eba8..853cf86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@adobe/helix-admin-support": "5.0.3", "@adobe/helix-config": "5.8.0", "@adobe/helix-google-support": "4.0.1", + "@adobe/helix-html2md": "1.1.0", "@adobe/helix-mediahandler": "2.9.5", "@adobe/helix-onedrive-support": "12.1.7", "@adobe/helix-shared-body-data": "2.2.3", @@ -236,6 +237,592 @@ "node": "20 || >=22" } }, + "node_modules/@adobe/helix-html2md": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@adobe/helix-html2md/-/helix-html2md-1.1.0.tgz", + "integrity": "sha512-+by/8htM1P3deLpQw+7hLMBpPp2Bfncmiux9yQ7HsghAMH1wqj6HMvyERNFX3UcvVKP9i6xVNTkYqz8hVk5uIQ==", + "license": "Apache-2.0", + "dependencies": { + "@adobe/helix-markdown-support": "7.1.16", + "@adobe/helix-mediahandler": "2.9.5", + "@adobe/helix-shared-process-queue": "3.1.3", + "@adobe/helix-shared-string": "2.2.0", + "@adobe/micromark-extension-gridtables": "2.0.4", + "@adobe/remark-gridtables": "3.0.15", + "hast-util-select": "6.0.4", + "hast-util-to-mdast": "10.1.2", + "hast-util-to-string": "3.0.1", + "rehype-parse": "9.0.1", + "remark-gfm": "4.0.1", + "remark-stringify": "11.0.0", + "unified": "11.0.5", + "unist-util-visit": "5.0.0" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/@adobe/helix-markdown-support": { + "version": "7.1.16", + "resolved": "https://registry.npmjs.org/@adobe/helix-markdown-support/-/helix-markdown-support-7.1.16.tgz", + "integrity": "sha512-Qpe1rP/RA3TKIuSgLkMJbFJuJmbSD+1WUsLT7JrlLo/N8mOlNM+ZIG8tbFpd3v5muVzjekt4ggRRLQlKdBmLjQ==", + "license": "Apache-2.0", + "dependencies": { + "hast-util-to-html": "9.0.5", + "js-yaml": "4.1.1", + "mdast-util-gfm-footnote": "2.1.0", + "mdast-util-gfm-strikethrough": "2.0.0", + "mdast-util-gfm-table": "2.0.0", + "mdast-util-gfm-task-list-item": "2.0.0", + "mdast-util-phrasing": "4.1.0", + "mdast-util-to-hast": "13.2.0", + "micromark-extension-gfm-footnote": "2.1.0", + "micromark-extension-gfm-strikethrough": "2.1.0", + "micromark-extension-gfm-table": "2.1.1", + "micromark-extension-gfm-tagfilter": "2.0.0", + "micromark-extension-gfm-task-list-item": "2.1.0", + "micromark-util-character": "2.1.1", + "micromark-util-combine-extensions": "2.0.1", + "micromark-util-symbol": "2.0.1", + "unist-util-find": "3.0.0", + "unist-util-visit": "5.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "unified": "11.x" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@adobe/helix-html2md/node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/helix-html2md/node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/@adobe/helix-mediahandler": { "version": "2.9.5", "resolved": "https://registry.npmjs.org/@adobe/helix-mediahandler/-/helix-mediahandler-2.9.5.tgz", @@ -607,29 +1194,280 @@ "@adobe/fetch": "^4.1.10" } }, - "node_modules/@adobe/helix-universal": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@adobe/helix-universal/-/helix-universal-5.3.0.tgz", - "integrity": "sha512-1eKFpKZMNamJHhq6eFm9gMLhgQunsf34mEFbaqg9ChEXZYk18SYgUu5GeNTvzk5Rzo0h9AuSwLtnI2Up2OSiSA==", - "devOptional": true, - "license": "Apache-2.0", - "peer": true, + "node_modules/@adobe/helix-universal": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@adobe/helix-universal/-/helix-universal-5.3.0.tgz", + "integrity": "sha512-1eKFpKZMNamJHhq6eFm9gMLhgQunsf34mEFbaqg9ChEXZYk18SYgUu5GeNTvzk5Rzo0h9AuSwLtnI2Up2OSiSA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@adobe/fetch": "4.2.3", + "aws4": "1.13.2" + } + }, + "node_modules/@adobe/helix-universal-devserver": { + "version": "1.1.145", + "resolved": "https://registry.npmjs.org/@adobe/helix-universal-devserver/-/helix-universal-devserver-1.1.145.tgz", + "integrity": "sha512-22v9zmyP5iCUb9QXawpn2FPVo2HbZ8rDEOB0RJgxoecQUbSqEKPtdtJ0q3rESCPlPU4toOffRUuLYSuFJsiAVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@adobe/helix-deploy": "^13.0.0", + "@adobe/helix-universal": "^5.1.0", + "express": "5.2.1", + "fs-extra": "11.3.3" + } + }, + "node_modules/@adobe/mdast-util-gridtables": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@adobe/mdast-util-gridtables/-/mdast-util-gridtables-4.0.14.tgz", + "integrity": "sha512-qBXNrWsVyejpqjcZyK7Z0IxHQ2Rhed7DaoiGU9dIJtxVpq5BbTReIq9Nc+373HxJnB36qIO57YKoIop2MAqDwg==", + "license": "Apache-2.0", + "dependencies": { + "@adobe/micromark-extension-gridtables": "^2.0.4", + "mdast-util-from-markdown": "2.0.2", + "mdast-util-to-hast": "13.2.0", + "mdast-util-to-markdown": "2.1.2", + "unist-util-visit": "5.0.0" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@adobe/mdast-util-gridtables/node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@adobe/micromark-extension-gridtables": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@adobe/micromark-extension-gridtables/-/micromark-extension-gridtables-2.0.4.tgz", + "integrity": "sha512-mzyRI2d0StuUv75VFnffYsHXRUo8J9RlK1EvjfmgHahwda1gNwe1Fqh4AYEZSWChf1HD/QBRcL6hEnxj9hedMg==", + "license": "Apache-2.0", + "dependencies": { + "micromark": "^4.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/@adobe/micromark-extension-gridtables/node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", "dependencies": { - "@adobe/fetch": "4.2.3", - "aws4": "1.13.2" + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/@adobe/helix-universal-devserver": { - "version": "1.1.145", - "resolved": "https://registry.npmjs.org/@adobe/helix-universal-devserver/-/helix-universal-devserver-1.1.145.tgz", - "integrity": "sha512-22v9zmyP5iCUb9QXawpn2FPVo2HbZ8rDEOB0RJgxoecQUbSqEKPtdtJ0q3rESCPlPU4toOffRUuLYSuFJsiAVw==", - "dev": true, + "node_modules/@adobe/remark-gridtables": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@adobe/remark-gridtables/-/remark-gridtables-3.0.15.tgz", + "integrity": "sha512-WJkRv5Ws8c5jzCVj8tXn/Ib186uetP/IfwPknYUf0wsKpLfUP4a+SLVFSufKqZQIclETGxDITGbD/stIIhK/0A==", "license": "Apache-2.0", "dependencies": { - "@adobe/helix-deploy": "^13.0.0", - "@adobe/helix-universal": "^5.1.0", - "express": "5.2.1", - "fs-extra": "11.3.3" + "@adobe/mdast-util-gridtables": "4.0.14", + "@adobe/micromark-extension-gridtables": "2.0.4" } }, "node_modules/@adobe/semantic-release-coralogix": { @@ -957,7 +1795,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.957.0.tgz", "integrity": "sha512-UvKQ9CpqzJxMjSjFpBaeWFAnR2sQChQH2jJEhsCFkAvrz1KDrU7sjOqUAPUH+ytsP5xghx1AZhfK2rVE/+JS0Q==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", @@ -3498,7 +4335,6 @@ "integrity": "sha512-t54CUOsFMappY1Jbzb7fetWeO0n6K0k/4+/ZpkS+3Joz8I4VcvY9OiEBFRYISqaI2fq5sCiPtAjRDOzVYG8m+Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.2", @@ -5133,6 +5969,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", @@ -5173,6 +6018,12 @@ "@types/unist": "^2" } }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, "node_modules/@types/node": { "version": "24.7.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.7.2.tgz", @@ -5255,7 +6106,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5457,7 +6307,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, "license": "Python-2.0" }, "node_modules/argv-formatter": { @@ -7062,6 +7911,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decode-named-character-reference/node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -7818,7 +8690,6 @@ "integrity": "sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -9599,6 +10470,20 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-embedded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", + "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-from-html": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", @@ -9756,6 +10641,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-is-body-ok-link": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", + "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-is-element": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", @@ -9769,6 +10667,42 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-minify-whitespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", + "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-minify-whitespace/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/hast-util-minify-whitespace/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-parse-selector": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", @@ -9782,6 +10716,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-is-body-ok-link": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-select": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", @@ -9815,7 +10766,162 @@ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, - "node_modules/hast-util-select/node_modules/unist-util-is": { + "node_modules/hast-util-select/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-select/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-select/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-select/node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/hast-util-to-html/node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-to-html/node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-to-mdast": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/hast-util-to-mdast/-/hast-util-to-mdast-10.1.2.tgz", + "integrity": "sha512-FiCRI7NmOvM4y+f5w32jPRzcxDIz+PUqDwEqn1A+1q2cdp3B8Gx7aVrXORdOKjMNDQsD1ogOr896+0jJHW1EFQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "hast-util-to-text": "^4.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-minify-whitespace": "^6.0.0", + "trim-trailing-lines": "^2.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-mdast/node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/hast-util-to-mdast/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/hast-util-to-mdast/node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-mdast/node_modules/unist-util-is": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", @@ -9828,7 +10934,7 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-select/node_modules/unist-util-visit": { + "node_modules/hast-util-to-mdast/node_modules/unist-util-visit": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", @@ -9843,7 +10949,7 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-select/node_modules/unist-util-visit-parents": { + "node_modules/hast-util-to-mdast/node_modules/unist-util-visit-parents": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", @@ -9857,65 +10963,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-select/node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-to-html": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", - "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-html/node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/hast-util-to-html/node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-to-html/node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/hast-util-to-string": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", @@ -11058,10 +12105,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -11579,6 +12625,12 @@ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "license": "MIT" }, + "node_modules/lodash.iteratee": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.iteratee/-/lodash.iteratee-4.7.0.tgz", + "integrity": "sha512-yv3cSQZmfpbIKo4Yo45B1taEvxjNvcpF1CEOc0Y6dEyvhPIfEJE3twDwPgWTPQubcSgXyBwBKG6wpQvWMDOf6Q==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -11804,7 +12856,6 @@ "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", "dev": true, "license": "MIT", - "peer": true, "bin": { "marked": "bin/marked.js" }, @@ -11911,6 +12962,206 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/mdast-util-gfm-footnote/node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/mdast-util-gfm-strikethrough": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.3.tgz", @@ -11940,14 +13191,56 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz", - "integrity": "sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A==", - "dev": true, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz", + "integrity": "sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-to-markdown": "~0.6.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing/node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/mdast-util-phrasing/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/mdast-util-phrasing/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "dependencies": { - "mdast-util-to-markdown": "~0.6.0" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", @@ -12163,100 +13456,414 @@ ], "license": "MIT", "dependencies": { - "debug": "^4.0.0", - "parse-entities": "^2.0.0" + "debug": "^4.0.0", + "parse-entities": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-0.3.3.tgz", + "integrity": "sha512-oVN4zv5/tAIA+l3GbMi7lWeYpJ14oQyJ3uEim20ktYFAcfX1x3LNlFGGlmrZHt7u9YlKExmyJdDGaTt6cMSR/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark": "~2.11.0", + "micromark-extension-gfm-autolink-literal": "~0.5.0", + "micromark-extension-gfm-strikethrough": "~0.6.5", + "micromark-extension-gfm-table": "~0.4.0", + "micromark-extension-gfm-tagfilter": "~0.3.0", + "micromark-extension-gfm-task-list-item": "~0.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz", + "integrity": "sha512-ePiDGH0/lhcngCe8FtH4ARFoxKTUelMp4L7Gg2pujYD5CSMb9PbblnyL+AAMud/SNMyusbS2XDSiPIRcQoNFAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark": "~2.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.5.tgz", + "integrity": "sha512-PpOKlgokpQRwUesRwWEp+fHjGGkZEejj83k9gU5iXCbDG+XBA92BqnRKYJdfqfkrRcZRgGuPuXb7DaK/DmxOhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark": "~2.11.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.3.tgz", + "integrity": "sha512-hVGvESPq0fk6ALWtomcwmgLvH8ZSVpcPjzi0AjPclB9FsVRgMtGZkUcpE0zgjOCFAznKepF4z3hX8z6e3HODdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark": "~2.11.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz", + "integrity": "sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz", + "integrity": "sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark": "~2.11.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-extension-gfm": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-0.3.3.tgz", - "integrity": "sha512-oVN4zv5/tAIA+l3GbMi7lWeYpJ14oQyJ3uEim20ktYFAcfX1x3LNlFGGlmrZHt7u9YlKExmyJdDGaTt6cMSR/A==", - "dev": true, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "micromark": "~2.11.0", - "micromark-extension-gfm-autolink-literal": "~0.5.0", - "micromark-extension-gfm-strikethrough": "~0.6.5", - "micromark-extension-gfm-table": "~0.4.0", - "micromark-extension-gfm-tagfilter": "~0.3.0", - "micromark-extension-gfm-task-list-item": "~0.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz", - "integrity": "sha512-ePiDGH0/lhcngCe8FtH4ARFoxKTUelMp4L7Gg2pujYD5CSMb9PbblnyL+AAMud/SNMyusbS2XDSiPIRcQoNFAw==", - "dev": true, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "micromark": "~2.11.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.5.tgz", - "integrity": "sha512-PpOKlgokpQRwUesRwWEp+fHjGGkZEejj83k9gU5iXCbDG+XBA92BqnRKYJdfqfkrRcZRgGuPuXb7DaK/DmxOhw==", - "dev": true, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "micromark": "~2.11.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-extension-gfm-table": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.3.tgz", - "integrity": "sha512-hVGvESPq0fk6ALWtomcwmgLvH8ZSVpcPjzi0AjPclB9FsVRgMtGZkUcpE0zgjOCFAznKepF4z3hX8z6e3HODdA==", - "dev": true, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "micromark": "~2.11.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz", - "integrity": "sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz", - "integrity": "sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark": "~2.11.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", "funding": [ { "type": "GitHub Sponsors", @@ -12269,14 +13876,13 @@ ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-util-encode": { + "node_modules/micromark-util-resolve-all": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", "funding": [ { "type": "GitHub Sponsors", @@ -12287,7 +13893,10 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT" + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } }, "node_modules/micromark-util-sanitize-uri": { "version": "2.0.1", @@ -12310,6 +13919,28 @@ "micromark-util-symbol": "^2.0.0" } }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, "node_modules/micromark-util-symbol": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", @@ -15033,7 +16664,6 @@ "dev": true, "inBundle": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -16249,6 +17879,20 @@ "node": ">=14" } }, + "node_modules/rehype-minify-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/rehype-minify-whitespace/-/rehype-minify-whitespace-6.0.2.tgz", + "integrity": "sha512-Zk0pyQ06A3Lyxhe9vGtOtzz3Z0+qZ5+7icZ/PL/2x1SHPbKao5oB/g/rlc6BCTajqBb33JcOe71Ye1oFsuYbnw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-parse": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", @@ -16648,7 +18292,6 @@ "integrity": "sha512-6qGjWccl5yoyugHt3jTgztJ9Y0JVzyH8/Voc/D8PlLat9pwxQYXz7W1Dpnq5h0/G5GCYGUaDSlYcyk3AMh5A6g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@semantic-release/commit-analyzer": "^13.0.1", "@semantic-release/error": "^4.0.0", @@ -18297,7 +19940,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -18400,6 +20042,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/trim-trailing-lines": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-2.1.0.tgz", + "integrity": "sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/trough": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", @@ -18706,6 +20358,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-find": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find/-/unist-util-find-3.0.0.tgz", + "integrity": "sha512-T7ZqS7immLjYyC4FCp2hDo3ksZ1v+qcbb+e5+iWxc2jONgHOLXPCpms1L8VV4hVxCXgWTxmBHDztuEZFVwC+Gg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "lodash.iteratee": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-find-after": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", @@ -18739,6 +20406,54 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-find/node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/unist-util-find/node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-find/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-find/node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-is": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", diff --git a/package.json b/package.json index 1947263..80fdeb0 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "@adobe/helix-admin-support": "5.0.3", "@adobe/helix-config": "5.8.0", "@adobe/helix-google-support": "4.0.1", + "@adobe/helix-html2md": "1.1.0", "@adobe/helix-mediahandler": "2.9.5", "@adobe/helix-onedrive-support": "12.1.7", "@adobe/helix-shared-body-data": "2.2.3", diff --git a/src/contentproxy/Forest.js b/src/contentproxy/Forest.js index 463cda1..64b64d6 100644 --- a/src/contentproxy/Forest.js +++ b/src/contentproxy/Forest.js @@ -90,11 +90,21 @@ export /* abstract */ class Forest { const folderPath = path.substring(0, idx); let items = folders[folderPath]; if (!items) { - // eslint-disable-next-line no-await-in-loop - items = await this.listFolder(rootItem, '', folderPath); - if (!items) { + try { + // eslint-disable-next-line no-await-in-loop + items = await this.listFolder(rootItem, '', folderPath); + if (!items) { + const infoPath = `${folderPath}/*`; + itemList.set(infoPath, { status: 404, path: infoPath }); + items = []; + } + } catch (e) { const infoPath = `${folderPath}/*`; - itemList.set(infoPath, { status: 404, path: infoPath }); + itemList.set(infoPath, { + status: e.$metadata.httpStatusCode ?? 500, + path: infoPath, + error: String(e), + }); items = []; } folders[folderPath] = items; diff --git a/src/contentproxy/errors.js b/src/contentproxy/errors.js index c7f300d..177562d 100644 --- a/src/contentproxy/errors.js +++ b/src/contentproxy/errors.js @@ -58,6 +58,10 @@ const errors = [ code: 'AEM_BACKEND_FILE_TOO_BIG', template: 'Unable to preview \'$1\': Documents larger than 100mb not supported: $2', }, + { + code: 'AEM_BACKEND_TOO_MANY_IMAGES', + template: 'Unable to preview \'$1\': Documents has more than $2 images: $3', + }, { code: 'AEM_BACKEND_RESOURCE_TOO_BIG', template: 'Files larger than 500mb are not supported: $1', diff --git a/src/contentproxy/google-list.js b/src/contentproxy/google-list.js index 1ecb2e0..a9b4f21 100644 --- a/src/contentproxy/google-list.js +++ b/src/contentproxy/google-list.js @@ -116,7 +116,7 @@ export class GoogleForest extends Forest { * @param {ProgressCallback} progressCB * @returns {Promise} the list of resources */ -export async function list(context, paths, progressCB) { +export async function list(context, info, paths, progressCB) { const { config: { content: { contentBusId, source } }, log } = context; const client = await context.getGoogleClient(contentBusId); @@ -133,7 +133,7 @@ export async function list(context, paths, progressCB) { source: { name: item.name, id: item.id, - mimeType: item.mimeType || 'application/octet-stream', + contentType: item.mimeType || 'application/octet-stream', lastModified: Date.parse(item.modifiedTime), size: item.size, type: 'gdrive', diff --git a/src/contentproxy/index.js b/src/contentproxy/index.js index ce95ceb..a9464b9 100644 --- a/src/contentproxy/index.js +++ b/src/contentproxy/index.js @@ -17,6 +17,7 @@ import { error } from './errors.js'; import google from './google.js'; import markup from './markup.js'; import onedrive from './onedrive.js'; +import sourcebus from './sourcebus.js'; /** * @type {import('./contentproxy').ContentSourceHandler[]} @@ -25,6 +26,7 @@ export const HANDLERS = { // exported for testing only google, onedrive, markup, + sourcebus, }; /** @@ -34,7 +36,11 @@ export const HANDLERS = { // exported for testing only * @return {import('./contentproxy').ContentSourceHandler} handler */ export function getContentSourceHandler(source) { - return HANDLERS[source.type]; + let { type } = source; + if (source.url?.startsWith('https://api.aem.live/')) { + type = 'sourcebus'; + } + return HANDLERS[type]; } /** diff --git a/src/contentproxy/markup-json.js b/src/contentproxy/markup-json.js index 10efe72..5f222fd 100644 --- a/src/contentproxy/markup-json.js +++ b/src/contentproxy/markup-json.js @@ -13,23 +13,14 @@ import { AbortError, Response } from '@adobe/fetch'; import { HelixStorage } from '@adobe/helix-shared-storage'; import { errorResponse } from '../support/utils.js'; import { - getContentSourceHeaders, assertValidSheetJSON, computeSourceUrl, - updateMarkupSourceInfo, addLastModified, + addLastModified, + computeSourceUrl, + getContentSourceHeaders, + parseSheetJSON, + updateMarkupSourceInfo, } from './utils.js'; import { error } from './errors.js'; -function parseSheetJSON(data) { - let json; - try { - json = JSON.parse(data); - } catch { - throw Error('invalid sheet json; failed to parse'); - } - - assertValidSheetJSON(json); - return json; -} - /** * Fetch timeout for markup source. */ diff --git a/src/contentproxy/sourcebus-file.js b/src/contentproxy/sourcebus-file.js new file mode 100644 index 0000000..a1a6c16 --- /dev/null +++ b/src/contentproxy/sourcebus-file.js @@ -0,0 +1,50 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +import { Response } from '@adobe/fetch'; +import { HelixStorage } from '@adobe/helix-shared-storage'; +import { validateSource } from './sourcebus-utils.js'; + +/** + * Fetches file data from the source bus + * + * @param {import('../support/AdminContext').AdminContext} ctx context + * @param {import('../support/RequestInfo').RequestInfo} info request info + * @param {object} [opts] options + * @param {object} [opts.source] content source + * @param {string} [opts.lastModified] last modified + * @param {number} [opts.fetchTimeout] fetch timeout + * @returns {Promise} response + */ +export async function handleFile(ctx, info, opts) { + const { + org, site, sourcePath, error: errorResp, + } = await validateSource(ctx, info, opts); + if (errorResp) { + return errorResp; + } + + // load content from source bus + const sourceBus = HelixStorage.fromContext(ctx).sourceBus(); + const meta = {}; + const body = await sourceBus.get(`${org}/${site}${sourcePath}`, meta); + if (!body) { + return new Response('', { status: 404 }); + } + + return new Response(body, { + status: 200, + headers: { + 'content-type': meta.ContentType, + 'last-modified': meta.LastModified?.toUTCString(), + }, + }); +} diff --git a/src/contentproxy/sourcebus-json.js b/src/contentproxy/sourcebus-json.js new file mode 100644 index 0000000..408b7a9 --- /dev/null +++ b/src/contentproxy/sourcebus-json.js @@ -0,0 +1,65 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +import { Response } from '@adobe/fetch'; +import { HelixStorage } from '@adobe/helix-shared-storage'; +import { errorResponse } from '../support/utils.js'; +import { parseSheetJSON } from './utils.js'; +import { validateSource } from './sourcebus-utils.js'; +import { error } from './errors.js'; + +/** + * Fetches a JSON as sheet/multisheet from the source bus + * + * @param {import('../support/AdminContext').AdminContext} ctx context + * @param {import('../support/RequestInfo').RequestInfo} info request info + * @param {object} [opts] options + * @param {object} [opts.source] content source + * @param {string} [opts.lastModified] last modified + * @param {number} [opts.fetchTimeout] fetch timeout + * @returns {Promise} response + */ +export async function handleJSON(ctx, info, opts) { + const { log } = ctx; + const { + org, site, sourcePath, error: errorResp, + } = await validateSource(ctx, info, opts); + if (errorResp) { + return errorResp; + } + + // load content from source bus + const sourceBus = HelixStorage.fromContext(ctx).sourceBus(); + const meta = {}; + const body = await sourceBus.get(`${org}/${site}${sourcePath}`, meta); + if (!body) { + return new Response('', { status: 404 }); + } + + let json; + try { + json = parseSheetJSON(body); + } catch (e) { + return errorResponse(log, 400, error( + 'JSON fetched from markup \'$1\' is invalid: $2', + sourcePath, + e.message, + )); + } + + return new Response(JSON.stringify(json), { + status: 200, + headers: { + 'content-type': 'application/json', + 'last-modified': meta.LastModified?.toUTCString(), + }, + }); +} diff --git a/src/contentproxy/sourcebus-list.js b/src/contentproxy/sourcebus-list.js new file mode 100644 index 0000000..c3ba41a --- /dev/null +++ b/src/contentproxy/sourcebus-list.js @@ -0,0 +1,109 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +import { splitByExtension } from '@adobe/helix-shared-string'; +import { HelixStorage } from '@adobe/helix-shared-storage'; +import { basename, dirname } from 'path'; +import { Forest } from './Forest.js'; +import { StatusCodeError } from '../support/StatusCodeError.js'; +import { validateSource } from './sourcebus-utils.js'; + +export class SourceForest extends Forest { + constructor(ctx, info) { + super(ctx.log); + this.ctx = ctx; + this.bucket = HelixStorage.fromContext(ctx).sourceBus(); + this.org = info.org; + this.site = info.site; + } + + /** + * List items below a root item. + * @returns {Promise} + */ + async listFolder(source, rootPath, relPath) { + const key = `${this.org}/${this.site}${relPath}`; + const listing = await this.bucket.list(key); + return listing.map((item) => { + /* + "key": "org/site/documents/index.html", + "lastModified": "2025-01-01T12:34:56.000Z", + "contentLength": 32768, + "contentType": "text/html", + "path": "/index.html" + */ + const path = `${rootPath}${relPath}${item.path}`; + const name = basename(item.path); + if (name === '.props') { + return null; + } + const [baseName, ext] = splitByExtension(path); // eg: /documents/index , .html + const ret = { + ...item, + path, + file: true, + resourcePath: path, + name, + ext, + }; + if (name === 'index.html') { + ret.path = `${dirname(path)}/`; + ret.resourcePath = `${baseName}.md`; + ret.ext = '.md'; + } else if (ext === 'html') { + ret.path = baseName; + ret.resourcePath = `${baseName}.md`; + ret.ext = '.md'; + } + return ret; + }).filter((item) => !!item); + } +} +/** + * Fetches file data from the external source. + * the paths can specify the files that should be included in the list. if a path ends with `/*` + * its entire subtree is retrieved. + * + * @type {import('./contentproxy.js').FetchList} + * @param {import('../support/AdminContext').AdminContext} ctx context + * @param {PathInfo} info + * @param {import('../support/RequestInfo').RequestInfo} info request info + * @param {string[]} paths + * @param {ProgressCallback} progressCB + * @returns {Promise} the list of resources + */ +export async function list(ctx, info, paths, progressCB) { + const { config: { content: { source } } } = ctx; + const { error } = await validateSource(ctx, info); + if (error) { + throw new StatusCodeError(error.headers.get('x-error'), error.status); + } + + const forest = new SourceForest(ctx, info); + const itemList = await forest.generate(source, paths, progressCB); + + return itemList.map((item) => { + if (item.status) { + return item; + } + return { + path: item.path, + resourcePath: item.resourcePath, + source: { + name: item.name, + contentType: item.contentType, + lastModified: Date.parse(item.lastModified), + size: item.contentLength, + type: 'source', + }, + }; + }); +} diff --git a/src/contentproxy/sourcebus-utils.js b/src/contentproxy/sourcebus-utils.js new file mode 100644 index 0000000..e570f6f --- /dev/null +++ b/src/contentproxy/sourcebus-utils.js @@ -0,0 +1,67 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +import { errorResponse } from '../support/utils.js'; +import { error } from './errors.js'; + +/** + * @typedef ValidationResult + * @property {string} org + * @property {string} site + * @property {URL} sourceUrl + * @property {string} sourcePath + * @property {Response} error + */ + +/** + * Validates if the content source is properly configured and if org/site match. + * + * @param {import('../support/AdminContext').AdminContext} ctx context + * @param {import('../support/RequestInfo').RequestInfo} info request info + * @param {object} [opts] options + * @param {object} [opts.source] content source + * @param {string} [opts.lastModified] last modified + * @param {number} [opts.fetchTimeout] fetch timeout + * @returns {Promise} the validation result + */ +export function validateSource(ctx, info, opts) { + const { config: { content }, log } = ctx; + const source = opts?.source ?? content.source; + const sourceUrl = new URL(source.url); + const ret = { + sourceUrl, + org: info.org, + site: info.site, + sourcePath: info.resourcePath, + error: null, + }; + + // extract org and site from url.pathname, format: https://api.aem.live//sites//source + // e.g. /adobe/sites/foo/source + const { org, site } = sourceUrl.pathname.match(/^\/(?[^/]+)\/sites\/(?[^/]+)\/source$/)?.groups ?? {}; + if (org !== info.org || site !== info.site) { + if (org && site) { + ret.error = errorResponse(log, 400, error( + 'Source bus is not allowed for org: $1, site: $2', + info.org, + info.site, + )); + } else { + ret.error = errorResponse(log, 400, error( + 'Source url must be in the format: https://api.aem.live//sites//source. Got: $1', + sourceUrl.href, + )); + } + } + + // for now, only allow source bus from the same org and site + return ret; +} diff --git a/src/contentproxy/sourcebus.js b/src/contentproxy/sourcebus.js new file mode 100644 index 0000000..d48c8af --- /dev/null +++ b/src/contentproxy/sourcebus.js @@ -0,0 +1,146 @@ +/* + * Copyright 2025 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +import { HelixStorage } from '@adobe/helix-shared-storage'; +import { MediaHandler, SizeTooLargeException } from '@adobe/helix-mediahandler'; +import { html2md, TooManyImagesError } from '@adobe/helix-html2md'; +import { Response } from '@adobe/fetch'; +import { handleJSON } from './sourcebus-json.js'; +import { handleFile } from './sourcebus-file.js'; +import { list } from './sourcebus-list.js'; +import { validateSource } from './sourcebus-utils.js'; +import { errorResponse } from '../support/utils.js'; +import { error } from './errors.js'; + +const DEFAULT_MAX_IMAGE_SIZE = 20 * 1024 * 1024; // 20mb + +const DEFAULT_MAX_IMAGES = 200; + +/** + * Retrieves a file from source bus. + * + * @param {import('../support/AdminContext').AdminContext} ctx context + * @param {import('../support/RequestInfo').RequestInfo} info request info + * @param {object} [opts] options + * @param {object} [opts.source] content source + * @param {string} [opts.lastModified] last modified + * @param {number} [opts.fetchTimeout] fetch timeout + * @returns {Promise} response + */ +async function handle(ctx, info, opts) { + const { config: { content, limits }, log } = ctx; + const { + org, site, sourceUrl, error: errorResp, + } = await validateSource(ctx, info, opts); + if (errorResp) { + return errorResp; + } + + // the source is stored as .html files in the source bus + let sourcePath = info.resourcePath; + if (info.ext === '.md') { + sourcePath = `${sourcePath.substring(0, sourcePath.length - '.md'.length)}.html`; + /* c8 ignore next 7 */ + } else { + // this should never happen, since all resourcePaths are properly mapped before + return errorResponse(log, 400, error( + 'unexpected file extension: $1', + info.ext, + )); + } + + // load content from source bus + const sourceBus = HelixStorage.fromContext(ctx).sourceBus(); + const meta = {}; + const body = await sourceBus.get(`${org}/${site}${sourcePath}`, meta); + if (!body) { + return new Response('', { status: 404 }); + } + + const { + MEDIAHANDLER_NOCACHE: noCache, + CLOUDFLARE_ACCOUNT_ID: r2AccountId, + CLOUDFLARE_R2_ACCESS_KEY_ID: r2AccessKeyId, + CLOUDFLARE_R2_SECRET_ACCESS_KEY: r2SecretAccessKey, + } = ctx.env; + + const mediaHandler = new MediaHandler({ + r2AccountId, + r2AccessKeyId, + r2SecretAccessKey, + bucketId: ctx.attributes.bucketMap.media, + owner: org, + repo: site, + ref: 'main', + contentBusId: content.contentBusId, + log, + noCache, + fetchTimeout: 5000, // limit image fetches to 5s + forceHttp1: true, + maxSize: limits?.html2md?.maxImageSize ?? DEFAULT_MAX_IMAGE_SIZE, + }); + + const maxImages = limits?.html2md?.maxImages ?? DEFAULT_MAX_IMAGES; + try { + // convert to md + const md = await html2md(body, { + mediaHandler, + log, + url: sourceUrl.href + sourcePath, // only used for logging + org, + site, + unspreadLists: true, + maxImages, + externalImageUrlPrefixes: [`https://main--${site}--${org}.aem.page/`], + }); + + return new Response(md, { + status: 200, + headers: { + 'content-type': 'text/markdown', + 'last-modified': meta.LastModified?.toUTCString(), + }, + }); + } catch (e) { + if (e instanceof TooManyImagesError) { + return errorResponse(log, 409, error( + 'Unable to preview \'$1\': Documents has more than $2 images: $3', + sourcePath, + maxImages, + e.message, // todo: include num images in error + )); + } + if (e instanceof SizeTooLargeException) { + return errorResponse(log, 409, error( + 'Unable to preview \'$1\': $2', + sourcePath, + e.message, + )); + } + /* c8 ignore next 6 */ + return errorResponse(log, 500, error( + 'Unable to preview \'$1\': $2', + sourcePath, + e.message, + )); + } +} + +/** + * @type {import('./contentproxy.js').ContentSourceHandler} + */ +export default { + name: 'sourcebus', + handle, + handleJSON, + handleFile, + list, +}; diff --git a/src/contentproxy/utils.js b/src/contentproxy/utils.js index 0d94d10..9878a38 100644 --- a/src/contentproxy/utils.js +++ b/src/contentproxy/utils.js @@ -260,3 +260,22 @@ export function addLastModified(headers, value) { } return headers; } + +/** + * Parses a JSON string and validates it as a sheet JSON. + * Throws an error if parsing fails or the JSON is invalid. + * + * @param {string} data - The JSON string to parse. + * @returns {object} The validated sheet JSON object. + */ +export function parseSheetJSON(data) { + let json; + try { + json = JSON.parse(data); + } catch { + throw Error('invalid sheet json; failed to parse'); + } + + assertValidSheetJSON(json); + return json; +} diff --git a/test/contentproxy/fixtures/google-list-result.json b/test/contentproxy/fixtures/google-list-result.json index 0c21e5c..12b1623 100644 --- a/test/contentproxy/fixtures/google-list-result.json +++ b/test/contentproxy/fixtures/google-list-result.json @@ -5,7 +5,7 @@ "source": { "name": "index", "id": "5HfH4hk3VuCH9PF1BAaL4118Qw1biyEnPcSDXmwcLpzU", - "mimeType": "application/vnd.google-apps.document", + "contentType": "application/vnd.google-apps.document", "lastModified": 1698757554968, "size": 1024, "type": "gdrive" @@ -17,7 +17,7 @@ "source": { "name": "document", "id": "1HfH4hk3VuCH9PF1BAaL4118Qw1biyEnPcSDXmwcLpzU", - "mimeType": "application/vnd.google-apps.document", + "contentType": "application/vnd.google-apps.document", "lastModified": 1698757554968, "size": 1024, "type": "gdrive" @@ -29,7 +29,7 @@ "source": { "name": "Copy of helix-learnings-2022.pdf", "id": "1CrsvMdio9WXRS1XzkSUxJi2HZ-tPqCP9", - "mimeType": "application/pdf", + "contentType": "application/pdf", "lastModified": 1698754020000, "size": 3232437, "type": "gdrive" @@ -41,7 +41,7 @@ "source": { "name": "document-one", "id": "14WWbTHbCbbjlNxinNW-4CXyagpZWsKVAnSC5oyDAhoI", - "mimeType": "application/vnd.google-apps.document", + "contentType": "application/vnd.google-apps.document", "lastModified": 1698757728537, "size": 1024, "type": "gdrive" @@ -53,7 +53,7 @@ "source": { "name": "helix-learnings-2022.pdf", "id": "1_EKUoWcF9znjp1ZIkHePIzIiUuqM07bj", - "mimeType": "application/pdf", + "contentType": "application/pdf", "lastModified": 1698754020000, "size": 3232437, "type": "gdrive" @@ -65,7 +65,7 @@ "source": { "name": "sample.png", "id": "1-BljmlemrIiENu2p5hYlPj1i_AlXQxsX", - "mimeType": "image/png", + "contentType": "image/png", "lastModified": 1698754020000, "size": 3873, "type": "gdrive" @@ -77,7 +77,7 @@ "source": { "name": "sample.svg", "id": "1LwH2LFWRqI6cRRSS-Tl5Nb5imTSjESDl", - "mimeType": "image/svg+xml", + "contentType": "image/svg+xml", "lastModified": 1698754020000, "size": 1595, "type": "gdrive" @@ -89,7 +89,7 @@ "source": { "name": "simple phases", "id": "1yBOCRhnmw3WKTwW50A5ohk3V18tZ6MdPBcP0CGzSha4", - "mimeType": "application/vnd.google-apps.spreadsheet", + "contentType": "application/vnd.google-apps.spreadsheet", "lastModified": 1698757696990, "size": 1024, "type": "gdrive" @@ -101,7 +101,7 @@ "source": { "name": "sample.png", "id": "199eVwhIRttJCxGKo-B1IocE4apc3f1NT", - "mimeType": "image/png", + "contentType": "image/png", "lastModified": 1698754020000, "size": 3873, "type": "gdrive" @@ -113,7 +113,7 @@ "source": { "name": "sample.svg", "id": "1IQB86rZ5LhY7Crrt_lA5CPTvjHiHajwq", - "mimeType": "image/svg+xml", + "contentType": "image/svg+xml", "lastModified": 1698754020000, "size": 1595, "type": "gdrive" @@ -125,7 +125,7 @@ "source": { "name": "helix-learnings-2022.pdf", "id": "1xkum0nDsiWe1yx-szogxOy6gnePwkf_z", - "mimeType": "application/pdf", + "contentType": "application/pdf", "lastModified": 1698754020000, "size": 3232437, "type": "gdrive" @@ -141,7 +141,7 @@ "source": { "name": "sample.png", "id": "1vFvxScNLJDrleRZy-z25pYefRlcNKvFR", - "mimeType": "application/octet-stream", + "contentType": "application/octet-stream", "lastModified": 1698754020000, "size": 3873, "type": "gdrive" @@ -153,7 +153,7 @@ "source": { "name": "sample.svg", "id": "1JmSbTnOXM1t2zJiuokp3EBUtXMVreVOM", - "mimeType": "image/svg+xml", + "contentType": "image/svg+xml", "lastModified": 1698754020000, "size": 1595, "type": "gdrive" @@ -165,7 +165,7 @@ "source": { "name": "test", "id": "1FREVtyDzwkxCD0l_PFAM5yg5AoJWnyeMY6T1Nm8KTwg", - "mimeType": "application/vnd.google-apps.document", + "contentType": "application/vnd.google-apps.document", "lastModified": 1698757587061, "size": 1024, "type": "gdrive" @@ -177,7 +177,7 @@ "source": { "name": "unsafe.svg", "id": "1YvrkuFYscNdR87hTvt1V6X-gh4loCJPB", - "mimeType": "image/svg+xml", + "contentType": "image/svg+xml", "lastModified": 1698754020000, "size": 1632, "type": "gdrive" diff --git a/test/contentproxy/fixtures/sourcebus/300.png b/test/contentproxy/fixtures/sourcebus/300.png new file mode 100644 index 0000000..4c1d595 Binary files /dev/null and b/test/contentproxy/fixtures/sourcebus/300.png differ diff --git a/test/contentproxy/fixtures/sourcebus/gallery.html b/test/contentproxy/fixtures/sourcebus/gallery.html new file mode 100644 index 0000000..9fdb0e5 --- /dev/null +++ b/test/contentproxy/fixtures/sourcebus/gallery.html @@ -0,0 +1,14 @@ + + + +
+
+

Hello, world.

+

source bus images.

+ + + +
+
+ + \ No newline at end of file diff --git a/test/contentproxy/fixtures/sourcebus/index.html b/test/contentproxy/fixtures/sourcebus/index.html new file mode 100644 index 0000000..36e19bb --- /dev/null +++ b/test/contentproxy/fixtures/sourcebus/index.html @@ -0,0 +1,11 @@ + + + +
+
+

Hello, world.

+

Testing, source bus.

+
+
+ + \ No newline at end of file diff --git a/test/contentproxy/fixtures/sourcebus/list-documents-result.json b/test/contentproxy/fixtures/sourcebus/list-documents-result.json new file mode 100644 index 0000000..e222495 --- /dev/null +++ b/test/contentproxy/fixtures/sourcebus/list-documents-result.json @@ -0,0 +1,77 @@ +[ + { + "error": "Unknown: UnknownError", + "path": "/blog/*", + "status": 500 + }, + { + "path": "/blog/post1", + "status": 404 + }, + { + "path": "/documents/", + "resourcePath": "/documents/index.md", + "source": { + "name": "index.html", + "contentType": "text/html", + "lastModified": 1735734896000, + "size": 32768, + "type": "source" + } + }, + { + "path": "/documents/document", + "resourcePath": "/documents/document.md", + "source": { + "name": "document.html", + "contentType": "text/html", + "lastModified": 1735734896000, + "size": 32768, + "type": "source" + } + }, + { + "path": "/documents/folder/data.json", + "resourcePath": "/documents/folder/data.json", + "source": { + "name": "data.json", + "contentType": "application/json", + "lastModified": 1640912461000, + "size": 123, + "type": "source" + } + }, + { + "path": "/documents/folder/sample.png", + "resourcePath": "/documents/folder/sample.png", + "source": { + "name": "sample.png", + "contentType": "image/png", + "lastModified": 1640912461000, + "size": 123, + "type": "source" + } + }, + { + "path": "/documents/news/", + "resourcePath": "/documents/news/index.md", + "source": { + "name": "index.html", + "contentType": "text/html", + "lastModified": 1735734896000, + "size": 32768, + "type": "source" + } + }, + { + "path": "/documents/report.pdf", + "resourcePath": "/documents/report.pdf", + "source": { + "name": "report.pdf", + "contentType": "application/pdf", + "lastModified": 978310861000, + "size": 88888, + "type": "source" + } + } +] diff --git a/test/contentproxy/fixtures/sourcebus/list-documents.xml b/test/contentproxy/fixtures/sourcebus/list-documents.xml new file mode 100644 index 0000000..ee68377 --- /dev/null +++ b/test/contentproxy/fixtures/sourcebus/list-documents.xml @@ -0,0 +1,53 @@ + + helix-source-bus + org/site/documents/ + + 1000 + false + + org/site/documents/index.html + 2025-01-01T12:34:56.000Z + 32768 + + + org/site/documents/document.html + 2025-01-01T12:34:56.000Z + 32768 + + + org/site/documents/news/index.html + 2025-01-01T12:34:56.000Z + 32768 + + + org/site/documents/news/.props + 2021-12-31T01:01:01.001Z + 3 + + + org/site/documents/report.pdf + 2001-01-01T01:01:01.001Z + 88888 + + + org/site/documents/folder/.props + 2021-12-31T01:01:01.001Z + 3 + + + org/site/documents/folder/data.json + 2021-12-31T01:01:01.001Z + 123 + + + org/site/documents/folder/sample.png + 2021-12-31T01:01:01.001Z + 123 + + + org/site/documents/news/ + + + org/site/documents/folder/ + + diff --git a/test/contentproxy/fixtures/sourcebus/welcome.html b/test/contentproxy/fixtures/sourcebus/welcome.html new file mode 100644 index 0000000..36e19bb --- /dev/null +++ b/test/contentproxy/fixtures/sourcebus/welcome.html @@ -0,0 +1,11 @@ + + + +
+
+

Hello, world.

+

Testing, source bus.

+
+
+ + \ No newline at end of file diff --git a/test/contentproxy/google-list.test.js b/test/contentproxy/google-list.test.js index 0d43c04..6222689 100644 --- a/test/contentproxy/google-list.test.js +++ b/test/contentproxy/google-list.test.js @@ -84,8 +84,8 @@ describe('Google Integration Tests (list)', () => { 'content-type': 'application/json', }); - const { context } = setupTest('/'); - const result = await list(context, ['/documents/*', '/documents/not-found']); + const { context, info } = setupTest('/'); + const result = await list(context, info, ['/documents/*', '/documents/not-found']); assert.deepStrictEqual(result, JSON.parse(await readFile(specPath('google-list-result.json')))); }); @@ -95,8 +95,8 @@ describe('Google Integration Tests (list)', () => { .user() .folders([]); - const { context } = setupTest('/'); - const result = await list(context, ['/documents/*']); + const { context, info } = setupTest('/'); + const result = await list(context, info, ['/documents/*']); assert.deepStrictEqual(result, []); }); diff --git a/test/contentproxy/sourcebus-file.test.js b/test/contentproxy/sourcebus-file.test.js new file mode 100644 index 0000000..714d1cb --- /dev/null +++ b/test/contentproxy/sourcebus-file.test.js @@ -0,0 +1,130 @@ +/* + * Copyright 2025 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env mocha */ +import assert from 'assert'; +import { resolve } from 'path'; +import { Request } from '@adobe/fetch'; +import { AuthInfo } from '../../src/auth/auth-info.js'; +import { main } from '../../src/index.js'; +import { Nock, SITE_CONFIG } from '../utils.js'; + +const SITE_MUP_CONFIG = (url = 'https://api.aem.live/org/sites/site/source') => ({ + ...SITE_CONFIG, + content: { + ...SITE_CONFIG.content, + source: { + type: 'markup', + url, + }, + }, +}); + +describe('Source Bus Content Proxy Tests (JSON)', () => { + /** @type {import('../utils.js').NockEnv} */ + let nock; + + beforeEach(() => { + nock = new Nock().env({ + HELIX_STORAGE_DISABLE_R2: 'true', + }); + }); + + afterEach(() => { + nock.done(); + }); + + function setupTest(path = '/', { + config = SITE_MUP_CONFIG(), data, + authInfo = AuthInfo.Default().withAuthenticated(true), + } = {}) { + nock.siteConfig(config); + + const suffix = `/org/sites/site/contentproxy${path}`; + const query = new URLSearchParams(data); + + const request = new Request(`https://api.aem.live${suffix}?${query}`, { + headers: { + 'x-request-id': 'rid', + }, + }); + const context = { + pathInfo: { suffix }, + attributes: { + authInfo, + maxAttempts: 1, + }, + runtime: { region: 'us-east-1' }, + env: { + HLX_CONFIG_SERVICE_TOKEN: 'token', + MEDIAHANDLER_NOCACHE: 'true', + }, + }; + return { request, context }; + } + + it('Retrieves pdf from source bus', async () => { + nock.source() + .getObject('/org/site/empty.pdf') + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/empty.pdf'), { + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + 'content-type': 'application/pdf', + }); + + const { request, context } = setupTest('/empty.pdf'); + const response = await main(request, context); + + assert.strictEqual(response.status, 200); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'application/pdf', + 'cache-control': 'no-store, private, must-revalidate', + vary: 'Accept-Encoding', + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + }); + }); + + it('Rejects preview if source.url has the correct format', async () => { + const { request, context } = setupTest('/data.pdf', { + config: { + ...SITE_MUP_CONFIG('https://api.aem.live/org/sites/status'), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 400); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'text/plain; charset=utf-8', + 'cache-control': 'no-store, private, must-revalidate', + 'x-error': 'Source url must be in the format: https://api.aem.live//sites//source. Got: https://api.aem.live/org/sites/status', + }); + }); + + it('Returns 404 if resource is not found in source bus', async () => { + nock.source() + .getObject('/org/site/missing.pdf') + .reply(404); + + const { request, context } = setupTest('/missing.pdf', { + config: { + ...SITE_MUP_CONFIG(), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 404); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'text/plain; charset=utf-8', + 'cache-control': 'no-store, private, must-revalidate', + vary: 'Accept-Encoding', + }); + }); +}); diff --git a/test/contentproxy/sourcebus-json.test.js b/test/contentproxy/sourcebus-json.test.js new file mode 100644 index 0000000..2e54a21 --- /dev/null +++ b/test/contentproxy/sourcebus-json.test.js @@ -0,0 +1,182 @@ +/* + * Copyright 2025 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env mocha */ +import assert from 'assert'; +import { Request } from '@adobe/fetch'; +import { AuthInfo } from '../../src/auth/auth-info.js'; +import { main } from '../../src/index.js'; +import { Nock, SITE_CONFIG } from '../utils.js'; +import { validSheet } from './utils.js'; + +const SITE_MUP_CONFIG = (url = 'https://api.aem.live/org/sites/site/source') => ({ + ...SITE_CONFIG, + content: { + ...SITE_CONFIG.content, + source: { + type: 'markup', + url, + }, + }, +}); + +describe('Source Bus Content Proxy Tests (JSON)', () => { + /** @type {import('../utils.js').NockEnv} */ + let nock; + + beforeEach(() => { + nock = new Nock().env({ + HELIX_STORAGE_DISABLE_R2: 'true', + }); + }); + + afterEach(() => { + nock.done(); + }); + + function setupTest(path = '/', { + config = SITE_MUP_CONFIG(), data, + authInfo = AuthInfo.Default().withAuthenticated(true), + } = {}) { + nock.siteConfig(config); + + const suffix = `/org/sites/site/contentproxy${path}`; + const query = new URLSearchParams(data); + + const request = new Request(`https://api.aem.live${suffix}?${query}`, { + headers: { + 'x-request-id': 'rid', + }, + }); + const context = { + pathInfo: { suffix }, + attributes: { + authInfo, + maxAttempts: 1, + }, + runtime: { region: 'us-east-1' }, + env: { + HLX_CONFIG_SERVICE_TOKEN: 'token', + MEDIAHANDLER_NOCACHE: 'true', + }, + }; + return { request, context }; + } + + it('Retrieves json from source bus', async () => { + const sheet = validSheet(); + nock.source() + .getObject('/org/site/data.json') + .reply(200, sheet, { + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + 'content-type': 'text/html', + }); + + const { request, context } = setupTest('/data.json', { + config: { + ...SITE_MUP_CONFIG(), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 200); + assert.deepStrictEqual(await response.json(), sheet); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'application/json', + 'cache-control': 'no-store, private, must-revalidate', + vary: 'Accept-Encoding', + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + }); + }); + + it('Rejects preview if source.url has the correct format', async () => { + const { request, context } = setupTest('/data.json', { + config: { + ...SITE_MUP_CONFIG('https://api.aem.live/org/sites/status'), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 400); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'text/plain; charset=utf-8', + 'cache-control': 'no-store, private, must-revalidate', + 'x-error': 'Source url must be in the format: https://api.aem.live//sites//source. Got: https://api.aem.live/org/sites/status', + }); + }); + + it('Returns 404 if resource is not found in source bus', async () => { + nock.source() + .getObject('/org/site/missing.json') + .reply(404); + + const { request, context } = setupTest('/missing.json', { + config: { + ...SITE_MUP_CONFIG(), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 404); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'text/plain; charset=utf-8', + 'cache-control': 'no-store, private, must-revalidate', + vary: 'Accept-Encoding', + }); + }); + + it('Rejects preview if json is invalid', async () => { + nock.source() + .getObject('/org/site/data.json') + .reply(200, 'not valid json', { + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + 'content-type': 'application/json', + }); + + const { request, context } = setupTest('/data.json', { + config: { + ...SITE_MUP_CONFIG(), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 400); + assert.deepStrictEqual(response.headers.plain(), { + 'cache-control': 'no-store, private, must-revalidate', + 'content-type': 'text/plain; charset=utf-8', + 'x-error': "JSON fetched from markup '/data.json' is invalid: invalid sheet json; failed to parse", + }); + }); + + it('Rejects preview if json is not valid sheet', async () => { + nock.source() + .getObject('/org/site/data.json') + .reply(200, '[1,2,3]', { + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + 'content-type': 'application/json', + }); + + const { request, context } = setupTest('/data.json', { + config: { + ...SITE_MUP_CONFIG(), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 400); + assert.deepStrictEqual(response.headers.plain(), { + 'cache-control': 'no-store, private, must-revalidate', + 'content-type': 'text/plain; charset=utf-8', + 'x-error': "JSON fetched from markup '/data.json' is invalid: invalid sheet; expecting object", + }); + }); +}); diff --git a/test/contentproxy/sourcebus-list.test.js b/test/contentproxy/sourcebus-list.test.js new file mode 100644 index 0000000..4f8c243 --- /dev/null +++ b/test/contentproxy/sourcebus-list.test.js @@ -0,0 +1,105 @@ +/* + * Copyright 2025 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env mocha */ +import assert from 'assert'; +import { resolve } from 'path'; +import { readFile } from 'fs/promises'; +import { list } from '../../src/contentproxy/sourcebus-list.js'; +import { + Nock, SITE_CONFIG, createContext, createInfo, +} from '../utils.js'; +import { StatusCodeError } from '../../src/support/StatusCodeError.js'; + +const SITE_MUP_CONFIG = (url = 'https://api.aem.live/org/sites/site/source') => ({ + ...SITE_CONFIG, + content: { + ...SITE_CONFIG.content, + source: { + type: 'markup', + url, + }, + }, +}); + +function specPath(spec) { + return resolve(__testdir, 'contentproxy', 'fixtures', spec); +} + +describe('Source Bus Content Proxy Tests (list)', () => { + /** @type {import('../utils.js').NockEnv} */ + let nock; + + beforeEach(() => { + nock = new Nock().env(); + }); + + afterEach(() => { + nock.done(); + }); + + function setupTest(suffix = '/org/sites/site/contentproxy/', { + config = SITE_MUP_CONFIG(), + } = {}) { + const context = createContext(suffix, { + attributes: { config }, + }); + const info = createInfo(suffix, { + 'x-workbook-session-id': 'test-session-id', + }).withCode('owner', 'repo'); + return { context, info }; + } + + it('Retrieves tree list from sourcebus', async () => { + nock.source() + .get('/') + .query({ + 'list-type': '2', + prefix: 'org/site/documents', + }) + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/sourcebus/list-documents.xml'), { + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + 'content-type': 'text/xml', + }) + .get('/') + .query({ + 'list-type': '2', + prefix: 'org/site/blog', + }) + .reply(500); + + const { context, info } = setupTest(); + const result = await list(context, info, [ + '/documents/*', + '/blog/post1', + ]); + + assert.deepStrictEqual(result, JSON.parse(await readFile(specPath('sourcebus/list-documents-result.json')))); + }); + + it('Rejects list if source.url has the correct format', async () => { + const { context, info } = setupTest(undefined, { + config: { + ...SITE_MUP_CONFIG('https://api.aem.live/org/sites/status'), + }, + }); + await assert.rejects(list(context, info, ['/documents/*']), new StatusCodeError('Source url must be in the format: https://api.aem.live//sites//source. Got: https://api.aem.live/org/sites/status', 400)); + }); + it('Rejects list if source.url is on wrong org/site', async () => { + const { context, info } = setupTest('/org/sites/othersite/contentproxy/', { + config: { + ...SITE_MUP_CONFIG('https://api.aem.live/org/sites/site/source'), + }, + }); + await assert.rejects(list(context, info, ['/documents/*']), new StatusCodeError('Source bus is not allowed for org: org, site: othersite', 400)); + }); +}); diff --git a/test/contentproxy/sourcebus.test.js b/test/contentproxy/sourcebus.test.js new file mode 100644 index 0000000..af5c38e --- /dev/null +++ b/test/contentproxy/sourcebus.test.js @@ -0,0 +1,287 @@ +/* + * Copyright 2025 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env mocha */ +import { resolve } from 'path'; +import assert from 'assert'; +import { Request } from '@adobe/fetch'; +import { AuthInfo } from '../../src/auth/auth-info.js'; +import { main } from '../../src/index.js'; +import { Nock, SITE_CONFIG } from '../utils.js'; + +const SITE_MUP_CONFIG = (url = 'https://api.aem.live/org/sites/site/source') => ({ + ...SITE_CONFIG, + content: { + ...SITE_CONFIG.content, + source: { + type: 'markup', + url, + }, + }, +}); + +describe('Source Bus Content Proxy Tests', () => { + /** @type {import('../utils.js').NockEnv} */ + let nock; + + beforeEach(() => { + nock = new Nock().env({ + HELIX_STORAGE_DISABLE_R2: 'true', + }); + }); + + afterEach(() => { + nock.done(); + }); + + function setupTest(path = '/', { + config = SITE_MUP_CONFIG(), data, + authInfo = AuthInfo.Default().withAuthenticated(true), + } = {}) { + nock.siteConfig(config); + + const suffix = `/org/sites/site/contentproxy${path}`; + const query = new URLSearchParams(data); + + const request = new Request(`https://api.aem.live${suffix}?${query}`, { + headers: { + 'x-request-id': 'rid', + }, + }); + const context = { + pathInfo: { suffix }, + attributes: { + authInfo, + maxAttempts: 1, + }, + runtime: { region: 'us-east-1' }, + env: { + HLX_CONFIG_SERVICE_TOKEN: 'token', + MEDIAHANDLER_NOCACHE: 'true', + }, + }; + return { request, context }; + } + + it('Retrieves root document from source bus', async () => { + nock.source() + .getObject('/org/site/index.html') + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/sourcebus/index.html'), { + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + 'content-type': 'text/html', + }); + + const { request, context } = setupTest('/', { + config: { + ...SITE_MUP_CONFIG(), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 200); + assert.strictEqual(await response.text(), '# Hello, world.\n\nTesting, source bus.\n'); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'text/markdown', + 'cache-control': 'no-store, private, must-revalidate', + vary: 'Accept-Encoding', + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + }); + }); + + it('Retrieves document from source bus', async () => { + nock.source() + .getObject('/org/site/welcome.html') + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/sourcebus/welcome.html'), { + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + 'content-type': 'text/html', + }); + + const { request, context } = setupTest('/welcome', { + config: { + ...SITE_MUP_CONFIG(), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 200); + assert.strictEqual(await response.text(), '# Hello, world.\n\nTesting, source bus.\n'); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'text/markdown', + 'cache-control': 'no-store, private, must-revalidate', + vary: 'Accept-Encoding', + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + }); + }); + + it('Returns 404 if resource is not found in source bus', async () => { + nock.source() + .getObject('/org/site/missing.html') + .reply(404); + + const { request, context } = setupTest('/missing', { + config: { + ...SITE_MUP_CONFIG(), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 404); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'text/plain; charset=utf-8', + 'cache-control': 'no-store, private, must-revalidate', + vary: 'Accept-Encoding', + }); + }); + + it('Rejects preview if source.url has the correct format', async () => { + const { request, context } = setupTest('/', { + config: { + ...SITE_MUP_CONFIG('https://api.aem.live/org/sites/status'), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 400); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'text/plain; charset=utf-8', + 'cache-control': 'no-store, private, must-revalidate', + 'x-error': 'Source url must be in the format: https://api.aem.live//sites//source. Got: https://api.aem.live/org/sites/status', + }); + }); + + it('Rejects preview if not the same org/site', async () => { + const { request, context } = setupTest('/', { + config: { + ...SITE_MUP_CONFIG('https://api.aem.live/org/sites/another/source'), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 400); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'text/plain; charset=utf-8', + 'cache-control': 'no-store, private, must-revalidate', + 'x-error': 'Source bus is not allowed for org: org, site: site', + }); + }); + + it('Retrieves document from source bus with external images', async () => { + nock.source() + .getObject('/org/site/gallery.html') + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/sourcebus/gallery.html'), { + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + 'content-type': 'text/html', + }); + nock('https://www.example.com') + .get('/image1.jpg') + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/sourcebus/300.png')) + .get('/image2.jpg') + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/sourcebus/300.png')); + nock.media('853bced1f82a05e9d27a8f63ecac59e70d9c14680dc5e417429f65e988f') + .head('/1c2e2c6c049ccf4b583431e14919687f3a39cc227') + .times(2) + .reply(404) + .putObject('/1c2e2c6c049ccf4b583431e14919687f3a39cc227') + .times(2) + .reply(201); + + const { request, context } = setupTest('/gallery', { + config: { + ...SITE_MUP_CONFIG(), + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 200); + assert.strictEqual(await response.text(), `# Hello, world. + +source bus images. + +![][image0] ![][image0] ![][image1] + +[image0]: https://main--site--org.aem.page/media_1c2e2c6c049ccf4b583431e14919687f3a39cc227.png#width=300&height=300 + +[image1]: https://main--site--org.aem.page/media_2c2e2c6c049ccf4b583431e14919687f3a39cc227.png#width=300&height=300 +`); + assert.deepStrictEqual(response.headers.plain(), { + 'content-type': 'text/markdown', + 'cache-control': 'no-store, private, must-revalidate', + vary: 'Accept-Encoding', + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + }); + }); + + it('Rejects document from source bus too many images', async () => { + nock.source() + .getObject('/org/site/gallery.html') + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/sourcebus/gallery.html'), { + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + 'content-type': 'text/html', + }); + + const { request, context } = setupTest('/gallery', { + config: { + ...SITE_MUP_CONFIG(), + limits: { + html2md: { + maxImages: 1, + }, + }, + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 409); + assert.strictEqual(await response.text(), ''); + assert.deepStrictEqual(response.headers.plain(), { + 'cache-control': 'no-store, private, must-revalidate', + 'content-type': 'text/plain; charset=utf-8', + 'x-error': "Unable to preview '/gallery.html': Documents has more than 1 images: maximum number of images reached: 2 of 1 max.", + 'x-error-code': 'AEM_BACKEND_TOO_MANY_IMAGES', + }); + }); + + it('Rejects document from source if image is too big', async () => { + nock.source() + .getObject('/org/site/gallery.html') + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/sourcebus/gallery.html'), { + 'last-modified': 'Thu, 11 Dec 2025 12:00:00 GMT', + 'content-type': 'text/html', + }); + + nock('https://www.example.com') + .get('/image1.jpg') + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/sourcebus/300.png')) + .get('/image2.jpg') + .replyWithFile(200, resolve(__testdir, 'contentproxy/fixtures/sourcebus/300.png')); + + const { request, context } = setupTest('/gallery', { + config: { + ...SITE_MUP_CONFIG(), + limits: { + html2md: { + maxImageSize: 100, + }, + }, + }, + }); + const response = await main(request, context); + + assert.strictEqual(response.status, 409); + assert.strictEqual(await response.text(), ''); + assert.deepStrictEqual(response.headers.plain(), { + 'cache-control': 'no-store, private, must-revalidate', + 'content-type': 'text/plain; charset=utf-8', + 'x-error': "Unable to preview '/gallery.html': Images 1 and 2 exceed allowed limit of 100B", + }); + }); +}); diff --git a/test/utils.d.ts b/test/utils.d.ts index 5b86b1b..60ae38f 100644 --- a/test/utils.d.ts +++ b/test/utils.d.ts @@ -52,6 +52,7 @@ declare interface Nock { code(ref?: string): S3Nock; content(contentBusId?: string): S3Nock; media(contentBusId?: string): S3Nock; + source(): S3Nock; sqs(queueName: string, entries?: any[]): nock.Scope; }