diff --git a/next.config.js b/next.config.js index e9c365f66d8d..830382a21c8d 100644 --- a/next.config.js +++ b/next.config.js @@ -8,6 +8,7 @@ const {patchWebpackConfig} = require('next-global-css'); const withTM = require('next-transpile-modules')([ '@gravity-ui/uikit', '@gravity-ui/page-constructor', + '@gravity-ui/blog-constructor', '@gravity-ui/components', '@gravity-ui/date-components', '@gravity-ui/navigation', @@ -15,6 +16,7 @@ const withTM = require('next-transpile-modules')([ '@gravity-ui/charts', '@gravity-ui/yagr', '@gravity-ui/markdown-editor', + 'swiper', ]); const {i18n} = require('./next-i18next.config'); diff --git a/package-lock.json b/package-lock.json index 8c43668cfb67..97993d3f4263 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "dependencies": { "@diplodoc/transform": "^4.18.0", + "@gravity-ui/blog-constructor": "^9.0.0-alpha.2", "@gravity-ui/chartkit": "^6.1.1", "@gravity-ui/charts": "^0.8.0", "@gravity-ui/components": "^4.16.0", @@ -18,7 +19,7 @@ "@gravity-ui/icons": "^2.16.0", "@gravity-ui/markdown-editor": "^15.1.0", "@gravity-ui/navigation": "^3.10.1", - "@gravity-ui/page-constructor": "^6.0.0-beta.6", + "@gravity-ui/page-constructor": "^8.0.0-alpha.3", "@gravity-ui/uikit": "^7.26.2", "@gravity-ui/uikit-themer": "^1.4.1", "@mdx-js/mdx": "^2.3.0", @@ -44,6 +45,7 @@ "next": "^14.2.24", "next-global-css": "^1.3.1", "next-i18next": "^15.2.0", + "node-html-parser": "^7.0.1", "prismjs": "^1.29.0", "react": "^18.2.0", "react-dom": "^18.3.1", @@ -3153,6 +3155,41 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==" }, + "node_modules/@gravity-ui/blog-constructor": { + "version": "9.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/@gravity-ui/blog-constructor/-/blog-constructor-9.0.0-alpha.2.tgz", + "integrity": "sha512-9HBTOslO4lQB9KH77BeCc9hnohVU8ul6tUqvXSLcBi0oNqZP9gK9hOf6/fPRaKtpKKiv5DSUzg9wMhwh3RQ8og==", + "dependencies": { + "@bem-react/classname": "^1.6.0", + "@gravity-ui/components": "^4.3.1", + "@gravity-ui/gulp-utils": "^1.0.1", + "@gravity-ui/i18n": "^1.7.0", + "lodash": "^4.17.21", + "react-helmet": "^6.1.0", + "ua-parser-js": "^0.7.28", + "url": "^0.11.0", + "utility-types": "^3.10.0", + "uuid": "^9.0.1" + }, + "peerDependencies": { + "@diplodoc/transform": "^4.10.7", + "@gravity-ui/page-constructor": "^8.0.0-alpha.1", + "@gravity-ui/uikit": "^7.1.1", + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@gravity-ui/blog-constructor/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@gravity-ui/chartkit": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/@gravity-ui/chartkit/-/chartkit-6.1.1.tgz", @@ -3241,27 +3278,6 @@ "lodash": "^4.17.0" } }, - "node_modules/@gravity-ui/dynamic-forms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@gravity-ui/dynamic-forms/-/dynamic-forms-5.1.0.tgz", - "integrity": "sha512-wZrAoIwSdTQM0Ejb1/G/VbVfshTY/1244H75pMnpf2clCwpjkVJlXOC/o0AjeqHtL1oMjqmn+7p1GYJ96b3llg==", - "dependencies": { - "@bem-react/classname": "^1.6.0", - "@gravity-ui/date-components": "^3.0.0", - "@gravity-ui/date-utils": "^2.5.5", - "@gravity-ui/i18n": "^1.2.0", - "@gravity-ui/icons": "^2.12.0", - "lodash": "^4.17.20" - }, - "peerDependencies": { - "@gravity-ui/uikit": "^7.0.0", - "final-form": "^4.20.2", - "react": "^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0", - "react-final-form": "^6.5.3", - "react-is": "^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/@gravity-ui/eslint-config": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@gravity-ui/eslint-config/-/eslint-config-2.0.0.tgz", @@ -3300,9 +3316,9 @@ } }, "node_modules/@gravity-ui/gulp-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@gravity-ui/gulp-utils/-/gulp-utils-1.0.1.tgz", - "integrity": "sha512-jdBcRcPFPeQIZCdJjpKDX+lDmGufNzkY00La6u80b0siy9sDzXP8Uh8IGj1Y5ykKeT7Ui21M0JcqxCEbmCZrNA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@gravity-ui/gulp-utils/-/gulp-utils-1.0.3.tgz", + "integrity": "sha512-0TfFGUMsjU8gCBjTD1OuRR9E44AoHHEBxhnrXXaaOREdCtrtAA63hHsoC+MiMnackC885w0ixIcVQOFFkpQidQ==", "dependencies": { "plugin-error": "^2.0.1", "through2": "^4.0.2", @@ -3449,7 +3465,6 @@ "version": "3.10.1", "resolved": "https://registry.npmjs.org/@gravity-ui/navigation/-/navigation-3.10.1.tgz", "integrity": "sha512-Lpmu8eAvEUdrlHpV5xhgAyhx1HqTbTsFqnQSyUEgsqoFOj6WOQszErd4rDdg1og2ciaF0lzHTgoep41mfnqa5A==", - "license": "MIT", "dependencies": { "@floating-ui/react": "^0.27.4", "react-transition-group": "^4.4.5", @@ -3464,27 +3479,22 @@ } }, "node_modules/@gravity-ui/page-constructor": { - "version": "6.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@gravity-ui/page-constructor/-/page-constructor-6.0.0-beta.6.tgz", - "integrity": "sha512-p54OiUwpMnVEFIcYNsEnSz0ZMA/i0pfKn8Nks1K6Ex7lV/9dRa/+0IS7T2RqHiYvV1plCprMtlqYndVPobBlmg==", + "version": "8.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/@gravity-ui/page-constructor/-/page-constructor-8.0.0-alpha.3.tgz", + "integrity": "sha512-MyZIHLPtKfv2bezfc2s7GyGDDlVmefQNCfBvXtkrWEm8vFnAL1s/B7EAE768qydb10Dq3d/8Y8Z3rLDjbNafCA==", "dependencies": { "@bem-react/classname": "^1.6.0", - "@gravity-ui/components": "^4.0.0", + "@gravity-ui/components": "^4.0.1", "@gravity-ui/dynamic-forms": "^5.0.0", - "@gravity-ui/gulp-utils": "^1.0.0", "@gravity-ui/i18n": "^1.7.0", "@react-spring/web": "^9.7.3", - "@testing-library/dom": "^10.4.0", "ajv": "^8.12.0", "ajv-keywords": "^5.1.0", "final-form": "^4.20.9", "github-buttons": "2.23.0", - "gulp-cli": "^3.0.0", - "gulp-sass": "^6.0.0", - "gulp-sourcemaps": "^3.0.0", "js-yaml-source-map": "^0.2.2", "lodash": "^4.17.21", - "monaco-editor": "^0.38.0", + "monaco-editor": "^0.52.2", "react-final-form": "^6.5.9", "react-monaco-editor": "^0.53.0", "react-player": "^2.9.0", @@ -3493,17 +3503,38 @@ "react-waypoint": "^10.1.0", "sanitize-html": "2.12.1", "snakecase-keys": "^5.1.0", - "swiper": "^6.8.4", + "swiper": "^10.2.0", "typograf": "^7.4.1", "utility-types": "^3.10.0", "uuid": "^9.0.0" }, "peerDependencies": { - "@diplodoc/transform": "^4.10.4", - "@gravity-ui/uikit": "^7.0.0", + "@diplodoc/transform": "^4.28.2", + "@gravity-ui/uikit": "^7.1.1", "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/@gravity-ui/page-constructor/node_modules/@gravity-ui/dynamic-forms": { + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/@gravity-ui/dynamic-forms/-/dynamic-forms-5.9.4.tgz", + "integrity": "sha512-91Cxuupunh0MaU9CWQebAQjhaXLp5/70xEPh1laeH9KMWV8UJLq9LDdnZuazVXcZbi4zkpCv2XQZP9xspdaBXw==", + "dependencies": { + "@bem-react/classname": "^1.6.0", + "@gravity-ui/date-components": "^3.0.0", + "@gravity-ui/date-utils": "^2.5.5", + "@gravity-ui/i18n": "^1.2.0", + "@gravity-ui/icons": "^2.12.0", + "lodash": "^4.17.20" + }, + "peerDependencies": { + "@gravity-ui/uikit": "^7.0.0", + "final-form": "^4.20.2", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-final-form": "^6.5.3", + "react-is": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@gravity-ui/page-constructor/node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -3535,28 +3566,10 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, - "node_modules/@gravity-ui/page-constructor/node_modules/swiper": { - "version": "6.8.4", - "resolved": "https://registry.npmjs.org/swiper/-/swiper-6.8.4.tgz", - "integrity": "sha512-O+buF9Q+sMA0H7luMS8R59hCaJKlpo8PXhQ6ZYu6Rn2v9OsFd4d1jmrv14QvxtQpKAvL/ZiovEeANI/uDGet7g==", - "funding": [ - { - "type": "patreon", - "url": "https://www.patreon.com/vladimirkharlampidi" - }, - { - "type": "open_collective", - "url": "http://opencollective.com/swiper" - } - ], - "hasInstallScript": true, - "dependencies": { - "dom7": "^3.0.0", - "ssr-window": "^3.0.0" - }, - "engines": { - "node": ">= 4.7.0" - } + "node_modules/@gravity-ui/page-constructor/node_modules/monaco-editor": { + "version": "0.52.2", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz", + "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==" }, "node_modules/@gravity-ui/page-constructor/node_modules/uuid": { "version": "9.0.1", @@ -3606,7 +3619,6 @@ "version": "7.26.2", "resolved": "https://registry.npmjs.org/@gravity-ui/uikit/-/uikit-7.26.2.tgz", "integrity": "sha512-J6macjTyM3baKIkSMrEau0/c7tMfSb/3KB9wCWodWaKpGtp8Sji3edUT6CNEbZNIRqG23iLy6RolTFecP1lk3w==", - "license": "MIT", "dependencies": { "@bem-react/classname": "^1.7.0", "@floating-ui/react": "^0.27.16", @@ -3649,142 +3661,6 @@ "node": ">=16.0.0" } }, - "node_modules/@gulp-sourcemaps/identity-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-2.0.1.tgz", - "integrity": "sha512-Tb+nSISZku+eQ4X1lAkevcQa+jknn/OVUgZ3XCxEKIsLsqYuPoJwJOPQeaOk75X3WPftb29GWY1eqE7GLsXb1Q==", - "dependencies": { - "acorn": "^6.4.1", - "normalize-path": "^3.0.0", - "postcss": "^7.0.16", - "source-map": "^0.6.0", - "through2": "^3.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/@gulp-sourcemaps/identity-map/node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/@gulp-sourcemaps/identity-map/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" - }, - "node_modules/@gulp-sourcemaps/identity-map/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/@gulp-sourcemaps/identity-map/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@gulp-sourcemaps/identity-map/node_modules/through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, - "node_modules/@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha512-o/EatdaGt8+x2qpb0vFLC/2Gug/xYPRXb6a+ET1wGYKozKN3krDWC/zZFZAtrzxJHuDL12mwdfEFKcKMNvc55A==", - "dependencies": { - "normalize-path": "^2.0.1", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/@gulp-sourcemaps/map-sources/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/@gulp-sourcemaps/map-sources/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@gulp-sourcemaps/map-sources/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/@gulp-sourcemaps/map-sources/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/@gulp-sourcemaps/map-sources/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/@gulp-sourcemaps/map-sources/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/@gulpjs/messages": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@gulpjs/messages/-/messages-1.1.0.tgz", - "integrity": "sha512-Ys9sazDatyTgZVb4xPlDufLweJ/Os2uHWOv+Caxvy2O85JcnT4M3vc73bi8pdLWlv3fdWQz3pdI9tVwo8rQQSg==", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@hello-pangea/dnd": { "version": "18.0.1", "resolved": "https://registry.npmjs.org/@hello-pangea/dnd/-/dnd-18.0.1.tgz", @@ -6388,6 +6264,7 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -7763,22 +7640,6 @@ "dequal": "^2.0.3" } }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", @@ -7795,14 +7656,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array-includes": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", @@ -7822,14 +7675,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -7906,14 +7751,6 @@ "node": ">=0.10.0" } }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ast-module-types": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ast-module-types/-/ast-module-types-6.0.1.tgz", @@ -7977,11 +7814,6 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/b4a": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", - "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" - }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", @@ -8037,10 +7869,17 @@ "dev": true }, "node_modules/bare-events": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", - "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", - "optional": true + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.1.tgz", + "integrity": "sha512-oxSAxTS1hRfnyit2CL5QpAOS5ixfBjj6ex3yTNvXyY/kE719jQ/IjuESJBK2w5v4wwQRAHGseVJXx9QBYOtFGQ==", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } }, "node_modules/base64-arraybuffer": { "version": "1.0.2", @@ -8797,32 +8636,6 @@ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", @@ -8831,11 +8644,6 @@ "node": ">=0.8" } }, - "node_modules/clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==" - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -8950,7 +8758,8 @@ "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true }, "node_modules/cookie": { "version": "0.7.2", @@ -8960,18 +8769,6 @@ "node": ">= 0.6" } }, - "node_modules/copy-props": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-4.0.0.tgz", - "integrity": "sha512-bVWtw1wQLzzKiYROtvNlbJgxgBYt2bMJpkCbKmXM3xyijvcjjWXEk5nyrrT3bgJ7ODb19ZohE2T0Y3FgNPyoTw==", - "dependencies": { - "each-props": "^3.0.0", - "is-plain-object": "^5.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/copy-to-clipboard": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", @@ -9003,11 +8800,6 @@ "url": "https://opencollective.com/core-js" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -9244,18 +9036,6 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, - "node_modules/d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", - "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", - "dependencies": { - "es5-ext": "^0.10.64", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/d3": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", @@ -9695,24 +9475,6 @@ } } }, - "node_modules/debug-fabulous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", - "dependencies": { - "debug": "3.X", - "memoizee": "0.4.X", - "object-assign": "4.X" - } - }, - "node_modules/debug-fabulous/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -9942,22 +9704,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha512-CwffZFvlJffUg9zZA0uqrjQayUTC8ob94pnr5sFwaVv3IOmkfUHcWH+jXaQK3askE51Cqe8/9Ql/0uXNwqZ8Zg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/detective-amd": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-6.0.1.tgz", @@ -10269,14 +10015,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/dom7": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz", - "integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==", - "dependencies": { - "ssr-window": "^3.0.0-alpha.1" - } - }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -10354,18 +10092,6 @@ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" }, - "node_modules/each-props": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-3.0.0.tgz", - "integrity": "sha512-IYf1hpuWrdzse/s/YJOrFmU15lyhSzxelNVAHTEG3DtP4QsLTWZUzcUL3HMXmKQxXpa4EIrBPpwRgj0aehdvAw==", - "dependencies": { - "is-plain-object": "^5.0.0", - "object.defaults": "^1.1.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -10387,7 +10113,8 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/emojis-list": { "version": "3.0.0", @@ -10650,58 +10377,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es5-ext": { - "version": "0.10.64", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", - "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "esniff": "^2.0.1", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", - "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", - "dependencies": { - "d": "^1.0.2", - "ext": "^1.7.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, "engines": { "node": ">=6" } @@ -11278,20 +10958,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/espree": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", @@ -11455,15 +11121,6 @@ "node": ">=0.10.0" } }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -11479,6 +11136,14 @@ "node": ">=0.8.x" } }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "dependencies": { + "bare-events": "^2.7.0" + } + }, "node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -11512,17 +11177,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/expect": { "version": "29.5.0", "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", @@ -11538,31 +11192,11 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dependencies": { - "type": "^2.7.2" - } - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/fast-content-type-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", @@ -11640,9 +11274,9 @@ "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==" }, "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "funding": [ { "type": "github", @@ -11918,48 +11552,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/findup-sync": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", - "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.3", - "micromatch": "^4.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/fined": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-2.0.0.tgz", - "integrity": "sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==", - "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^5.0.0", - "object.defaults": "^1.1.0", - "object.pick": "^1.3.0", - "parse-filepath": "^1.0.2" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/flag-icons": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/flag-icons/-/flag-icons-7.5.0.tgz", "integrity": "sha512-kd+MNXviFIg5hijH766tt+3x76ele1AXlo4zDdCxIvqWZhKt4T83bOtxUOOMlTx/EcFdUMH5yvQgYlFh1EqqFg==" }, - "node_modules/flagged-respawn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-2.0.0.tgz", - "integrity": "sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==", - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -12008,25 +11605,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/form-data": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", @@ -12080,6 +11658,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12137,6 +11716,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -12408,17 +11988,6 @@ "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", "dev": true }, - "node_modules/glogg": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-2.2.0.tgz", - "integrity": "sha512-eWv1ds/zAlz+M1ioHsyKJomfY7jbDDPpwSkv14KQj89bycx1nvK5/2Cj/T9g7kzJcX5Bc7Yv22FjfBZS/jl94A==", - "dependencies": { - "sparkles": "^2.1.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/gonzales-pe": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", @@ -12457,153 +12026,6 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, - "node_modules/gulp-cli": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-3.0.0.tgz", - "integrity": "sha512-RtMIitkT8DEMZZygHK2vEuLPqLPAFB4sntSxg4NoDta7ciwGZ18l7JuhCTiS5deOJi2IoK0btE+hs6R4sfj7AA==", - "dependencies": { - "@gulpjs/messages": "^1.1.0", - "chalk": "^4.1.2", - "copy-props": "^4.0.0", - "gulplog": "^2.2.0", - "interpret": "^3.1.1", - "liftoff": "^5.0.0", - "mute-stdout": "^2.0.0", - "replace-homedir": "^2.0.0", - "semver-greatest-satisfied-range": "^2.0.0", - "string-width": "^4.2.3", - "v8flags": "^4.0.0", - "yargs": "^16.2.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/gulp-sass": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-6.0.0.tgz", - "integrity": "sha512-FGb4Uab4jnH2GnSfBGd6uW3+imvNodAGfsjGcUhEtpNYPVx+TK2tp5uh7MO0sSR7aIf1Sm544werc+zV7ejHHw==", - "dependencies": { - "lodash.clonedeep": "^4.5.0", - "picocolors": "^1.0.0", - "plugin-error": "^1.0.1", - "replace-ext": "^2.0.0", - "strip-ansi": "^6.0.1", - "vinyl-sourcemaps-apply": "^0.2.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/gulp-sass/node_modules/plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dependencies": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/gulp-sourcemaps": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-3.0.0.tgz", - "integrity": "sha512-RqvUckJkuYqy4VaIH60RMal4ZtG0IbQ6PXMNkNsshEGJ9cldUPRb/YCgboYae+CLAs1HQNb4ADTKCx65HInquQ==", - "dependencies": { - "@gulp-sourcemaps/identity-map": "^2.0.1", - "@gulp-sourcemaps/map-sources": "^1.0.0", - "acorn": "^6.4.1", - "convert-source-map": "^1.0.0", - "css": "^3.0.0", - "debug-fabulous": "^1.0.0", - "detect-newline": "^2.0.0", - "graceful-fs": "^4.0.0", - "source-map": "^0.6.0", - "strip-bom-string": "^1.0.0", - "through2": "^2.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gulp-sourcemaps/node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/gulp-sourcemaps/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/gulp-sourcemaps/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/gulp-sourcemaps/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/gulp-sourcemaps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-sourcemaps/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/gulp-sourcemaps/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/gulplog": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-2.2.0.tgz", - "integrity": "sha512-V2FaKiOhpR3DRXZuYdRLn/qiY0yI5XmqbTKrYbdemJ+xOh2d2MOweI/XFgMzd/9+1twdvMwllnZbWZNJ+BOm4A==", - "dependencies": { - "glogg": "^2.2.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -12711,6 +12133,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -12817,6 +12240,14 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, "node_modules/highlight.js": { "version": "11.8.0", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.8.0.tgz", @@ -12838,17 +12269,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -13147,7 +12567,8 @@ "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true }, "node_modules/inline-style-parser": { "version": "0.1.1", @@ -13184,31 +12605,11 @@ "node": ">=12" } }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/intersects": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/intersects/-/intersects-2.7.2.tgz", "integrity": "sha512-/LtLDq40iFtvnjhouev9p2R+jP+raVONPiD1t8Mcj879pkrLiav99BTRPBkfMPwSYr5vTNws3USGoW+8usS45A==" }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -13309,6 +12710,7 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, "dependencies": { "hasown": "^2.0.2" }, @@ -13358,32 +12760,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extendable/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -13403,6 +12784,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "devOptional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -13498,11 +12880,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, "node_modules/is-reference": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.1.tgz", @@ -13529,20 +12906,9 @@ }, "node_modules/is-regexp": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dependencies": { - "is-unc-path": "^1.0.0" - }, + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -13615,17 +12981,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -13668,14 +13023,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -13699,14 +13046,6 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/javascript-time-ago": { "version": "2.5.9", "resolved": "https://registry.npmjs.org/javascript-time-ago/-/javascript-time-ago-2.5.9.tgz", @@ -14097,23 +13436,6 @@ "node": ">= 0.8.0" } }, - "node_modules/liftoff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-5.0.0.tgz", - "integrity": "sha512-a5BQjbCHnB+cy+gsro8lXJ4kZluzOijzJ1UVVfyJYZC+IP2pLv1h4+aysQeKuTmyO8NAqfyQAk4HWaP/HjcKTg==", - "dependencies": { - "extend": "^3.0.2", - "findup-sync": "^5.0.0", - "fined": "^2.0.0", - "flagged-respawn": "^2.0.0", - "is-plain-object": "^5.0.0", - "rechoir": "^0.8.0", - "resolve": "^1.20.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/lilconfig": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", @@ -14265,11 +13587,6 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" - }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -14451,14 +13768,6 @@ "yallist": "^3.0.2" } }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dependencies": { - "es5-ext": "~0.10.2" - } - }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -14537,14 +13846,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -15061,24 +14362,6 @@ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" }, - "node_modules/memoizee": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", - "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", - "dependencies": { - "d": "^1.0.2", - "es5-ext": "^0.10.64", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", @@ -15955,7 +15238,8 @@ "node_modules/monaco-editor": { "version": "0.38.0", "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.38.0.tgz", - "integrity": "sha512-11Fkh6yzEmwx7O0YoLxeae0qEGFwmyPRlVxpg7oF9czOOCB/iCjdJrG5I67da5WiXK3YJCxoz9TJFE8Tfq/v9A==" + "integrity": "sha512-11Fkh6yzEmwx7O0YoLxeae0qEGFwmyPRlVxpg7oF9czOOCB/iCjdJrG5I67da5WiXK3YJCxoz9TJFE8Tfq/v9A==", + "peer": true }, "node_modules/mri": { "version": "1.2.0", @@ -15978,14 +15262,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "node_modules/mute-stdout": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-2.0.0.tgz", - "integrity": "sha512-32GSKM3Wyc8dg/p39lWPKYu8zci9mJFzV1Np9Of0ZEpe6Fhssn/FbI7ywAMd40uX+p3ZKh3T5EeCFv81qS3HmQ==", - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/nano-css": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz", @@ -16198,11 +15474,6 @@ "dev": true, "license": "MIT" }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, "node_modules/next-transpile-modules": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/next-transpile-modules/-/next-transpile-modules-10.0.1.tgz", @@ -16221,6 +15492,15 @@ "tslib": "^2.0.3" } }, + "node_modules/node-html-parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-7.0.1.tgz", + "integrity": "sha512-KGtmPY2kS0thCWGK0VuPyOS+pBKhhe8gXztzA2ilAOhbUbxa9homF1bOyKvhGzMLXUoRds9IOmr/v5lr/lqNmA==", + "dependencies": { + "css-select": "^5.1.0", + "he": "1.2.0" + } + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -16291,6 +15571,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -16378,20 +15659,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", - "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object.entries": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", @@ -16436,17 +15703,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object.values": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", @@ -16692,19 +15948,6 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -16732,14 +15975,6 @@ "node": ">=6" } }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/parse-srcset": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", @@ -16837,26 +16072,8 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", @@ -17304,11 +16521,6 @@ "node": ">=6" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -17752,6 +16964,20 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-helmet": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", + "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", + "dependencies": { + "object-assign": "^4.1.1", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.1.1", + "react-side-effect": "^2.1.0" + }, + "peerDependencies": { + "react": ">=16.3.0" + } + }, "node_modules/react-hotkeys-hook": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.5.0.tgz", @@ -17801,9 +17027,9 @@ } }, "node_modules/react-player": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/react-player/-/react-player-2.16.0.tgz", - "integrity": "sha512-mAIPHfioD7yxO0GNYVFD1303QFtI3lyyQZLY229UEAp/a10cSW+hPcakg0Keq8uWJxT2OiT/4Gt+Lc9bD6bJmQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/react-player/-/react-player-2.16.1.tgz", + "integrity": "sha512-mxP6CqjSWjidtyDoMOSHVPdhX0pY16aSvw5fVr44EMaT7X5Xz46uQ4b/YBm1v2x+3hHkB9PmjEEkmbHb9PXQ4w==", "dependencies": { "deepmerge": "^4.0.0", "load-script": "^1.0.0", @@ -17815,6 +17041,14 @@ "react": ">=16.6.0" } }, + "node_modules/react-side-effect": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz", + "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==", + "peerDependencies": { + "react": "^16.3.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-slick": { "version": "0.29.0", "resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.29.0.tgz", @@ -18093,17 +17327,6 @@ "node": ">=8.10.0" } }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -18401,18 +17624,11 @@ "node": ">= 10" } }, - "node_modules/replace-homedir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-2.0.0.tgz", - "integrity": "sha512-bgEuQQ/BHW0XkkJtawzrfzHFSN70f/3cNOiHa2QsYxqrjaC30X1k74FJ6xswVBP0sr0SpGIdVFuPwfrYziVeyw==", - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -18460,6 +17676,7 @@ "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", @@ -18484,57 +17701,6 @@ "node": ">=18" } }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-dir/node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-dir/node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-dir/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -18924,22 +18090,11 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "devOptional": true, + "dev": true, "bin": { "semver": "bin/semver.js" } }, - "node_modules/semver-greatest-satisfied-range": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-2.0.0.tgz", - "integrity": "sha512-lH3f6kMbwyANB7HuOWRMlLCa2itaCrZJ+SAqqkSZrZKO/cAsk2EOyaKHUtNkVLFyFW9pct22SFesFp3Z7zpA0g==", - "dependencies": { - "sver": "^1.8.3" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -19272,14 +18427,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/sparkles": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-2.1.0.tgz", - "integrity": "sha512-r7iW1bDw8R/cFifrD3JnQJX0K1jqT0kprL48BiBpLZLJPmAm34zsVBsK5lc7HirZYZqMW65dOXZgbAGt/I6frg==", - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -19317,11 +18464,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, - "node_modules/ssr-window": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz", - "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==" - }, "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -19420,15 +18562,13 @@ } }, "node_modules/streamx": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", - "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", "dependencies": { + "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" - }, - "optionalDependencies": { - "bare-events": "^2.2.0" } }, "node_modules/string_decoder": { @@ -19456,6 +18596,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -19469,6 +18610,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -19568,6 +18710,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -19584,14 +18727,6 @@ "node": ">=4" } }, - "node_modules/strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", @@ -19902,6 +19037,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -19909,14 +19045,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sver": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/sver/-/sver-1.8.4.tgz", - "integrity": "sha512-71o1zfzyawLfIWBOmw8brleKyvnbn73oVHNCsu51uPMz/HWiKkkXsI31JjHW5zqXEqnPYkIiHd8ZmL7FCimLEA==", - "optionalDependencies": { - "semver": "^6.3.0" - } - }, "node_modules/svg-inline-loader": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/svg-inline-loader/-/svg-inline-loader-0.8.2.tgz", @@ -20173,6 +19301,19 @@ "b4a": "^1.6.4" } }, + "node_modules/text-decoder/node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -20195,18 +19336,6 @@ "readable-stream": "3" } }, - "node_modules/timers-ext": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", - "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", - "dependencies": { - "es5-ext": "^0.10.64", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -20413,11 +19542,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/type": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", - "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -20541,13 +19665,38 @@ } }, "node_modules/typograf": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/typograf/-/typograf-7.4.1.tgz", - "integrity": "sha512-V+1jqkv574pzPTW/JcqkhXQzmA7U3B2xVKc6QMzNxmN+1eecVn164Z8Wm8xM6ArKSk/sUjKvOPoT0U3G6zOMjQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/typograf/-/typograf-7.6.0.tgz", + "integrity": "sha512-sqYx4X1L7EDNRuJpqg/V+GCWMOpzVD5Om9IW0udi294sQYPwGGeRpPwsLC3gPt2BTsLtLiWJKpkwiyuO5PK2lQ==", "engines": { "node": ">= 4" } }, + "node_modules/ua-parser-js": { + "version": "0.7.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.41.tgz", + "integrity": "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", @@ -20568,14 +19717,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -20972,14 +20113,6 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, - "node_modules/v8flags": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", - "integrity": "sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==", - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -21078,12 +20211,11 @@ } }, "node_modules/vinyl": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", - "integrity": "sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", "dependencies": { "clone": "^2.1.2", - "clone-stats": "^1.0.0", "remove-trailing-separator": "^1.1.0", "replace-ext": "^2.0.0", "teex": "^1.0.1" @@ -21437,18 +20569,11 @@ } } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "engines": { "node": ">=10" } @@ -21471,27 +20596,11 @@ "node": ">= 14.6" } }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, "engines": { "node": ">=10" } diff --git a/package.json b/package.json index 2684694ab470..d4481c166365 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "sideEffects": false, "dependencies": { "@diplodoc/transform": "^4.18.0", + "@gravity-ui/blog-constructor": "^9.0.0-alpha.2", "@gravity-ui/chartkit": "^6.1.1", "@gravity-ui/charts": "^0.8.0", "@gravity-ui/components": "^4.16.0", @@ -15,7 +16,7 @@ "@gravity-ui/icons": "^2.16.0", "@gravity-ui/markdown-editor": "^15.1.0", "@gravity-ui/navigation": "^3.10.1", - "@gravity-ui/page-constructor": "^6.0.0-beta.6", + "@gravity-ui/page-constructor": "^8.0.0-alpha.3", "@gravity-ui/uikit": "^7.26.2", "@gravity-ui/uikit-themer": "^1.4.1", "@mdx-js/mdx": "^2.3.0", @@ -41,6 +42,7 @@ "next": "^14.2.24", "next-global-css": "^1.3.1", "next-i18next": "^15.2.0", + "node-html-parser": "^7.0.1", "prismjs": "^1.29.0", "react": "^18.2.0", "react-dom": "^18.3.1", diff --git a/public/locales/en/blog.json b/public/locales/en/blog.json new file mode 100644 index 000000000000..3e4841619f43 --- /dev/null +++ b/public/locales/en/blog.json @@ -0,0 +1,33 @@ +{ + "meta_title": "Blog", + "meta_description": "Articles, news and updates from Gravity UI team", + "page_title": "Blog", + "page_description": "Latest articles and updates", + "post_readingTime": "{{minutes}} min read", + "post_publishedAt": "Published on", + "post_updatedAt": "Updated on", + "post_backToBlog": "Back to Blog", + "post_share": "Share", + "post_tags": "Tags", + "post_relatedPosts": "Related posts", + "post_notFound": "Post not found", + "post_notFoundDescription": "The article you are looking for doesn't exist or has been removed.", + "filter_search": "Search", + "filter_searchPlaceholder": "Search articles...", + "filter_tags": "Tags", + "filter_services": "Services", + "filter_allTags": "All tags", + "filter_allServices": "All services", + "filter_clearFilters": "Clear filters", + "filter_noResults": "No articles found", + "filter_noResultsDescription": "Try changing your search query or filters", + "pagination_previous": "Previous", + "pagination_next": "Next", + "pagination_page": "Page {{page}} of {{total}}", + "error_loadFailed": "Failed to load content", + "error_tryAgain": "Try again", + "author_by": "By", + "author_authors": "Authors", + "pinnedPost": "Pinned" +} + diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 2d990665115c..b470db53578e 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -12,6 +12,7 @@ "menu_icons": "Icons", "menu_themer": "Themer", "menu_media": "Media", + "menu_blog": "Blog", "roadmap_inProgress": "In progress", "navigation_previous": "Previous", "navigation_next": "Next", diff --git a/public/locales/ru/blog.json b/public/locales/ru/blog.json new file mode 100644 index 000000000000..78668e4cc323 --- /dev/null +++ b/public/locales/ru/blog.json @@ -0,0 +1,33 @@ +{ + "meta_title": "Блог", + "meta_description": "Статьи, новости и обновления от команды Gravity UI", + "page_title": "Блог", + "page_description": "Последние статьи и обновления", + "post_readingTime": "{{minutes}} мин", + "post_publishedAt": "Опубликовано", + "post_updatedAt": "Обновлено", + "post_backToBlog": "Вернуться в блог", + "post_share": "Поделиться", + "post_tags": "Теги", + "post_relatedPosts": "Похожие статьи", + "post_notFound": "Статья не найдена", + "post_notFoundDescription": "Статья, которую вы ищете, не существует или была удалена.", + "filter_search": "Поиск", + "filter_searchPlaceholder": "Поиск статей...", + "filter_tags": "Теги", + "filter_services": "Сервисы", + "filter_allTags": "Все теги", + "filter_allServices": "Все сервисы", + "filter_clearFilters": "Очистить фильтры", + "filter_noResults": "Статьи не найдены", + "filter_noResultsDescription": "Попробуйте изменить запрос или фильтры", + "pagination_previous": "Назад", + "pagination_next": "Далее", + "pagination_page": "Страница {{page}} из {{total}}", + "error_loadFailed": "Не удалось загрузить контент", + "error_tryAgain": "Попробовать снова", + "author_by": "Автор", + "author_authors": "Авторы", + "pinnedPost": "Закреплено" +} + diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json index 8d88dee50c74..f854353501e2 100644 --- a/public/locales/ru/common.json +++ b/public/locales/ru/common.json @@ -15,6 +15,7 @@ "menu_icons": "Иконки", "menu_themer": "Темизатор", "menu_media": "Медиа", + "menu_blog": "Блог", "roadmap_inProgress": "В работе", "navigation_previous": "Назад", "navigation_next": "Далее", diff --git a/src/api/.mocks/en/pages/blogPage.json b/src/api/.mocks/en/pages/blogPage.json new file mode 100644 index 000000000000..2ad4ba6f3877 --- /dev/null +++ b/src/api/.mocks/en/pages/blogPage.json @@ -0,0 +1,48 @@ +{ + "id": 969, + "name": "blog", + "createdAt": "2022-08-24T15:40:07.513Z", + "updatedAt": "2022-08-24T15:40:07.513Z", + "type": "default", + "isDeleted": false, + "pageId": 969, + "locale": "en", + "publishedVersionId": 17498, + "lastVersionId": 17498, + "content": { + "blocks": [ + { + "type": "blog-feed-block", + "resetPaddings": true, + "image": "https://storage.yandexcloud.net/yandex-opensource/blog-cover-bg.png", + "title": "Blog" + } + ] + }, + "title": "Blog", + "noIndex": false, + "shareTitle": null, + "shareDescription": null, + "shareImage": null, + "pageLocaleId": 1261, + "author": "author", + "metaDescription": null, + "keywords": [], + "shareGenImage": null, + "shareGenTitle": null, + "tempShareGenTitle": null, + "solution": null, + "service": null, + "regions": [], + "locales": [ + { + "locale": "en", + "publishedVersionId": null + }, + { + "locale": "ru", + "publishedVersionId": 17498 + } + ] +} + diff --git a/src/api/.mocks/en/pages/gravity-ui-in-opensource.json b/src/api/.mocks/en/pages/gravity-ui-in-opensource.json new file mode 100644 index 000000000000..80e028a39a9f --- /dev/null +++ b/src/api/.mocks/en/pages/gravity-ui-in-opensource.json @@ -0,0 +1,73 @@ +{ + "id": 70, + "name": "blog/gravity-ui-in-opensource", + "createdAt": "2025-12-25T10:46:31.596Z", + "updatedAt": "2025-12-25T10:46:31.596Z", + "type": "default", + "isDeleted": false, + "versionOnTranslationId": null, + "searchCategorySlug": "blog", + "regions": [], + "pageId": 70, + "regionCode": "en", + "publishedVersionId": 194, + "lastVersionId": 194, + "content": "blocks:\n - type: blog-header-block\n resetPaddings: true\n paddingBottom: l\n width: m\n verticalOffset: m\n theme: dark\n background:\n image:\n src: https://storage.yandexcloud.net/yandex-opensource/blog-cover-bg.png\n disableCompress: true\n color: ''\n fullWidth: false\n - type: blog-layout-block\n resetPaddings: true\n mobileOrder: reverse\n children:\n - type: blog-author-block\n column: right\n resetPaddings: true\n authorId: 1069\n - type: blog-yfm-block\n column: right\n resetPaddings: true\n text: \"\\nВ этой статье:\\n\\n - [В чём особенности Gravity\\_UI](#peculiarities)\\n - [Как работать с Gravity\\_UI](#work)\\n - [Как воспользоваться Gravity\\_UI](#use)\\n\"\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\nВсем привет, я Алексей Сизиков, руководитель отдела User Experience в Yandex Cloud. В этой статье я хочу поделиться новостью: мы выпустили нашу дизайн‑систему и библиотеку компонентов [Gravity\\_UI](https://github.com/gravity-ui){target=\\\"_blank\\\"} в опенсорс. \\n\\nС помощью библиотеки компонентов Gravity\\_UI можно строить современные интерфейсы. В неё входит:\\n\\n * набор базовых React‑компонентов;\\n * библиотека‑конструктор для лендингов;\\n * [подробные гайды](https://gravity-ui.com/design){target=\\\"_blank\\\"} по использованию компонентов;\\n * библиотека в [Figma](https://www.figma.com/community/file/1271150067798118027/Gravity-UI-Design-System-(Beta)){target=\\\"_blank\\\"}; \\n * набор готовых иконок, в составе которого почти 600 вариантов;\\n * ChartKit — пакет для визуализации данных;\\n * Yagr — высокопроизводительный рендеринг графиков, основанный на uPlot;\\n * I18n — пакет для локализации интерфейса\\n * и ещё более [25 полезных библиотек](https://gravity-ui.com/libraries){target=\\\"_blank\\\"}.\\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: ''\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic0.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\nПод катом — рассказ, зачем мы сделали Gravity\\_UI, как его используем, в чём особенности и преимущества нашего подхода и как мы планируем развивать его дальше. А ещё — как настроить разные цветовые схемы в своих проектах и почему у нас четыре темы вместо двух стандартных.\\n\\n{% cut \\\"Зачем мы сделали Gravity\\_UI\\\" %}\\n\\nИзначально библиотека UIKit была внутренним продуктом для ускорения работы команды. По мере роста числа новых сервисов мы поставили цель: построить единый UX в наших продуктах. Нам было важно использовать одинаковые паттерны поведения пользователей в сервисах, чтобы пользователь ощущал всю платформу как единое целое.\\n\\nДополнительной целью дизайн‑команды было создать такие инструменты, чтобы разработчики смогли без привлечения дизайнеров сделать новый сервис.\\n\\nОтносительно недавно платформы и сервисы, использующие нашу дизайн‑систему, начали выходить в опенсорс: [YTsaurus](https://ytsaurus.tech/){target=\\\"_blank\\\"}, [YDB](https://ydb.tech/){target=\\\"_blank\\\"}, [DataLens](https://datalens.tech/){target=\\\"_blank\\\"}, [Diplodoc](https://diplodoc.com/){target=\\\"_blank\\\"}. Многие пользователи позитивно отзывались о них и помогали улучшать код вместе с разработчиками. Вдохновившись их примером, мы пришли к идее выпустить в открытый доступ и Gravity\\_UI, потому что видели, насколько библиотека может быть полезна многим сервисам не только внутри Яндекса.\\n\\n{% endcut %}\\n\"\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\n## В чём особенности Gravity\\_UI{#peculiarities}\\n\\n### Основано на реальном опыте\\n\\nОдна из отличительных черт нашей дизайн‑системы — она развивается на основе потребностей наших пользователей, большинство из которых являются разработчиками. Более того, наши дизайнеры неразрывно связаны с продуктами, в которых они работают. У каждого дизайнера есть несколько сервисов с собственными сценариями использования. После того как решение протестировано в их сервисах, продуктовый дизайнер передаёт его в другие сервисы, чтобы убедиться, что оно работает и помогает разработчикам. \\n\\nНапример, компонент боковой навигации изначально развивался только с логотипом и пунктами меню. Позже для удобства мы добавили пункт со всеми сервисами и поиском. А когда у нас появился сервис, где была необходимость создавать новую сущность сразу в боковом меню, у нас появилась отдельная кнопка с плюсиком. Дальше появились разделы меню с разделителями для сложных сервисов с большим количеством пунктов меню, а также кнопка «Остальные пункты».\\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n paddingBottom: s\n text: >-\n Компонент Навигации — можно настроить как простой вариант, так и\n максимально нагруженный\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic1.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\n### Гибкая вариативность\\n\\nМногие компоненты Gravity\\_UI можно настроить, учитывая разные сценарии. Например, у компонента [pagination](https://gravity-ui.com/components/uikit/pagination){target=\\\"_blank\\\"} есть несколько вариантов отображения: с общим числом страниц, полными подписями кнопок, возможностью перейти к конкретной странице и изменить число ответов на странице — этот вариант рассчитан на большое число страниц. А если у вас кейс, где результатов ответов немного, можно сделать компактный режим или даже скрыть цифры и показывать только стрелочки. \\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n paddingBottom: s\n text: Пример отображения разных вариантов пагинации\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic2.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\n### Широкая область применения\\n\\nПри помощи Gravity\\_UI можно сделать как простой интерфейс для администрирования, так и сложный дашборд с графиками. Вот несколько примеров того, что можно собрать с помощью нашей дизайн‑системы:\\n\\n * лендинги,\\n * админки,\\n * дашборды,\\n * графики,\\n * СRM,\\n * аналитический сервис.\\n\\nНапример, наши коллеги сделали такой дашборд:\\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: \"Пример дашборда, который можно сделать с помощью Gravity\\_UI\"\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic3.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\nТакже можно сделать простой лендинг. Например, [сайт](https://opensource.yandex/){target=\\\"_blank\\\"} с нашими проектами в опенсорс сделан на компонентах Gravity\\_UI. \\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n paddingBottom: s\n text: >-\n А это пример сайта, который тоже можно сделать с помощью нашей\n дизайн‑системы\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic4.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n ### Более 150 контрибьюторов\n\n\n Наша экосистема постоянно развивается и улучшается. Кроме обратной\n связи от нашего сообщества разработчиков, к нам поступают предложения\n более чем от 100 сервисов, которые уже используют нашу\n дизайн‑систему. \n\n\n Приведу пример. Изначально у нас было две темы — тёмная и светлая. Но\n мы стали получать фидбэк от команд, которые транслируют интерфейс на\n телевизоры для просмотра графиков или во время стендапа. Дело в том,\n что на телевизоре плохо видно интерфейс. Похожая проблема встречается\n также у пользователей со старыми или низкокачественными мониторами.\n\n\n В итоге разработали повышенную контрастность для каждой из тем. Она\n увеличивает яркость тёмного и светлого, а также семантических цветов.\n Это настраивается CSS‑стилями, а управляется в настройках\n пользователя.\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: \"Пример интерфейса Yandex Tracker, сделанный также на компонентах Gravity\\_UI, с возможностью включения повышенной контрастности\"\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic5.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n Кстати, теперь вы тоже можете сделать свой вклад. Для этого присылайте\n PR в GitHub или оставляйте комментарии в Figma.\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\n## Как работать с Gravity\\_UI{#work}\\n\\n### Настройка интерфейса под свой бренд\\n\\nДалее я расскажу о том, что ещё можно сделать с помощью Gravity\\_UI. Начну с возможности настроить дизайн‑систему под свой бренд. Например, когда YDB выходил в опенсорс, перед нами встала задача сохранить единую дизайн‑систему, но при этом сделать её особенной для разных брендов. Для этого мы создали отдельную группу CSS‑переменных. В неё входят цвета бренда, шрифты и радиусы скруглений. В коде это выглядит как небольшой блок:\\n\\n```json \\n.g-root {\\n --g-font-family-sans: 'Inter', sans-serif;\\n\\n --g-text-header-font-weight: 600;\\n --g-text-subheader-font-weight: 600;\\n --g-text-display-font-weight: 600;\\n --g-text-accent-font-weight: 600;\\n\\n --g-color-base-brand: rgb(117, 155, 255);\\n --g-color-base-brand-hover: rgb(99, 143, 255);\\n --g-color-base-selection: rgba(82, 130, 255, 0.05);\\n --g-color-base-selection-hover: rgba(82, 130, 255, 0.1);\\n --g-color-line-brand: rgb(117, 155, 255);\\n --g-color-text-brand: rgb(117, 155, 255);\\n --g-color-text-brand-contrast: rgb(255, 255 ,255);\\n --g-color-text-link: rgb(117, 155, 255);\\n --g-color-text-link-hover: rgb(82, 130, 255);\\n\\n --g-border-radius-xs: 3px;\\n --g-border-radius-s: 5px;\\n --g-border-radius-m: 6px;\\n --g-border-radius-l: 8px;\\n --g-border-radius-xl: 10px;\\n --g-border-radius-2xl: 16px;\\n}\\n```\\n\\nВ этой группе можно заменить шрифт, цвет акцентных кнопок, скругления. И таким образом можно использовать одну дизайн‑систему для разных брендов, сохраняя при этом фирменный стиль. Если же этот вариант вам не подходит, можно создать собственную цветовую схему. Подробная инструкция есть в [документации](https://preview.gravity-ui.com/uikit/?path=/docs/branding-overview--docs#additional-customization){target=\\\"_blank\\\"}.\\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: Пример интерфейсов с разными переменными бренда\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic6.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n Стоит отметить, что изменение цветов бренда не повлияет на основной\n интерфейс. Это особенно важно для тех элементов, где используются\n семантические цвета: например, красный по‑прежнему будет означать\n ошибку, а зелёный — успех.\n\n\n ### Компоненты в Figma\n\n\n Для удобства работы наша команда дизайнеров подготовила и загрузила\n все состояния компонентов в\n [Figma](https://www.figma.com/community/file/1271150067798118027){target=\"_blank\"}.\n При желании можно сделать копию библиотеки и попробовать собрать\n интерфейс сразу в сервисе.\n\n\n С последним обновлением в библиотеке не дублируются все четыре темы.\n По умолчанию вы работаете в светлой теме, но в разделе Layer вы можете\n переключить любой элемент или всю страницу на другую тему. \n - type: blog-media-block\n column: left\n resetPaddings: true\n text: Как просмотреть элемент в разных темах\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic7.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n Все элементы библиотеки представлены на странице Overview. Тут вы\n можете найти нужный компонент и перейти на страницу со всеми\n состояниями элемента. Кроме того, у каждого компонента есть пример\n использования. \n - type: blog-media-block\n column: left\n resetPaddings: true\n paddingBottom: s\n text: \"Страница со всеми элементами Gravity\\_UI\"\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic8.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n ### Почти 600 иконок\n\n Иконки — один из обязательных элементов дизайна и юзабилити. Они\n помогают организовать и структурировать контент, расставить акценты и\n улучшить восприятие информации. На первый взгляд, сделать пак иконок\n не так уж и сложно. Но мы столкнулись с вызовом при создании иконок\n для сложных метафор, таких как виртуальные машины, базы данных и\n различные типы графиков.\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: Пока у нас 594 иконки, но скоро их станет больше\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic9.png\n fullscreen: true\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: >-\n Особой задачей стала и разработка иконок для графического редактора\n контента (WYSIWYG), который внедряется в различные места для\n форматирования текста \n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic10.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n Чтобы сделать поиск иконок более удобным, мы использовали специальную\n систему нейминга. Теперь одну и ту же иконку можно найти, вводя разные\n названия. Например, чтобы найти такую иконку со стрелочкой, можно\n ввести любое слово: arrow, enter, move, login.\n - type: blog-media-block\n column: left\n resetPaddings: true\n paddingBottom: s\n text: >-\n Все иконки доступны на [отдельной\n странице](https://gravity-ui.com/icons). Вы можете скопировать SVG или\n скачать любую иконку\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic11.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n ### Гайды\n\n\n Как я уже писал выше, наша цель заключалась в том, чтобы разработчики\n могли легко создавать типовые интерфейсы, используя описания\n компонентов в нашем гайде. Мы стремились сделать этот процесс простым,\n без необходимости обращаться к дизайнеру за каждым элементом. На\n данный момент у нас уже есть пять примеров внутренних сервисов,\n которые были полностью созданы разработчиками с использованием только\n гайдов.\n\n\n Конечно, одними руками разработчика эту задачу решить не получится:\n так или иначе есть сложные сценарии, которые требуют внимания\n UX/UI‑специалиста. Тем не менее мы смогли снять значительную часть\n нагрузки с наших дизайнеров.\n\n\n В гайдах команда дизайнеров описала компоненты и дала рекомендации по\n их использованию, демонстрируя примеры правильного и неправильного\n подхода. Вы можете ознакомиться с ними на [этой\n странице](https://gravity-ui.com/components/uikit/alert){target=\"_blank\"}.\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: ''\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic12.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\n## Как воспользоваться Gravity\\_UI{#use}\\n\\nВсё, что нужно сделать, — вбить команду в консоль:\\n\\n```\\ngit clone git@github.com:gravity-ui/uikit-example-cra.git my-project && cd my-project\\nnpm i \\nnpm run start\\n```\\n\\nБолее подробная инструкция есть на главной странице репозитория в [GitHub](https://github.com/gravity-ui/uikit){target=\\\"_blank\\\"}.\\n\\nВсе компоненты Gravity\\_UI можно посмотреть в [UIkit](https://preview.gravity-ui.com/uikit/){target=\\\"_blank\\\"}, а подключить нужную библиотеку для ваших потребностей — в [Libraries](https://gravity-ui.com/libraries){target=\\\"_blank\\\"}. \\n\\n--------\\n\\nПодводя итоги, хочется ещё раз отметить: Gravity\\_UI — это дизайн‑система, которая выросла из реального опыта наших пользователей, потребности разработчиков и экспертизы дизайнеров. Это позволяет ей быть практичной и эффективной. И теперь ею может бесплатно воспользоваться любой желающий.\\n\\nМы стремимся сделать проект ещё лучше, учитывая потребности и отзывы наших пользователей. Заходите к нам в GitHub, оставляйте свои PR, пишите комментарии в Figma и делитесь примерами использования.\\n\"\n - type: blog-layout-block\n resetPaddings: true\n fullWidth: false\n children:\n - type: blog-meta-block\n column: left\n resetPaddings: true\n - type: blog-suggest-block\n resetPaddings: true\n", + "title": "", + "noIndex": false, + "shareTitle": null, + "shareDescription": null, + "shareImage": "https://storage.yandexcloud.net/yandex-opensource/blog-cover-bg.png", + "pageLocaleId": null, + "author": "ngorin", + "metaDescription": null, + "keywords": [], + "shareGenTitle": null, + "canonicalLink": null, + "sharingType": "semi-full", + "sharingTheme": "dark", + "comment": "gravity", + "shareImageUrl": "https://storage.cloud-preprod.yandex.net/ui-api-ru-preprod-stable-share-generator-screenshots/cache/8c45f347a6e585754d1d6e4949c9c5a20a2d570e.png", + "pageRegionId": 73, + "summary": null, + "versionId": 194, + "service": null, + "solution": null, + "locales": [ + { + "id": 73, + "pageId": 70, + "locale": "ru", + "createdAt": "2025-12-25T10:43:18.571Z", + "updatedAt": "2025-12-25T10:43:18.615Z", + "publishedVersionId": null, + "lastVersionId": 190 + }, + { + "id": 74, + "pageId": 70, + "locale": "en", + "createdAt": "2025-12-25T10:43:18.620Z", + "updatedAt": "2025-12-25T10:43:18.926Z", + "publishedVersionId": null, + "lastVersionId": 191 + } + ], + "pageRegions": [ + { + "regionCode": "en", + "publishedVersionId": null + }, + { + "regionCode": "ru-ru", + "publishedVersionId": 194 + } + ], + "searchCategory": { + "id": 7, + "slug": "blog", + "title": "Блог", + "url": "/blog" + }, + "voiceovers": [] + } \ No newline at end of file diff --git a/src/api/.mocks/en/posts/gravity-ui-in-opensource.json b/src/api/.mocks/en/posts/gravity-ui-in-opensource.json new file mode 100644 index 000000000000..60177bebb2c3 --- /dev/null +++ b/src/api/.mocks/en/posts/gravity-ui-in-opensource.json @@ -0,0 +1,35 @@ +{ + "id": 35, + "name": "gravity-ui-in-opensource", + "isPinned": false, + "postId": 35, + "description": "", + "image": "https://storage.yandexcloud.net/yandex-opensource/blog-cover-bg.png", + "readingTime": 10, + "title": "Gravity UI Design System: How to Easily Build Your Interface", + "date": "2025-12-25T00:00:00Z", + "likes": 0, + "hasUserLike": false, + "addLegacyPrefix": false, + "tags": [ + { + "slug": "articles", + "icon": "", + "name": "Articles" + } + ], + "authors": [ + { + "id": 1069, + "avatar": "https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/sizikov.png", + "firstName": "Alexey", + "secondName": "Sizikov", + "description": "Yandex Cloud", + "fullDescription": "Head of User Experience, Yandex Cloud", + "shortDescription": "Head of User Experience, Yandex Cloud", + "fullName": "Alexey Sizikov" + } + ], + "services": [] +} + diff --git a/src/api/.mocks/en/posts/index.json b/src/api/.mocks/en/posts/index.json new file mode 100644 index 000000000000..d29ff18dd054 --- /dev/null +++ b/src/api/.mocks/en/posts/index.json @@ -0,0 +1,32 @@ +{ + "posts": [ + { + "id": 35, + "name": "gravity-ui-in-opensource", + "date": "2025-12-25T00:00:00Z", + "title": "Gravity UI Design System: How to Easily Build Your Interface", + "postId": 35, + "description": "", + "image": "https://storage.yandexcloud.net/yandex-opensource/blog-cover-bg.png", + "readingTime": 10, + "likes": 0, + "hasUserLike": false, + "hasPublishedVersionInRegion": true, + "hasPublishedVersionInLocale": false, + "addLegacyPrefix": false, + "tags": [ + { + "slug": "articles", + "icon": "", + "name": "Articles" + } + ], + "services": [], + "url": "/blog/gravity-ui-in-opensource" + } + ], + "totalCount": 1, + "count": 1, + "pinnedPost": null +} + diff --git a/src/api/.mocks/en/tags.json b/src/api/.mocks/en/tags.json new file mode 100644 index 000000000000..455fe3df1efb --- /dev/null +++ b/src/api/.mocks/en/tags.json @@ -0,0 +1,15 @@ +[ + { + "id": 1, + "slug": "articles", + "createdAt": "2020-03-13T11:00:57.360Z", + "updatedAt": "2022-07-22T08:50:25.432Z", + "icon": "", + "isDeleted": false, + "name": "Articles", + "locale": "en", + "blogTagId": 1, + "count": 1 + } +] + diff --git a/src/api/.mocks/ru/pages/blogPage.json b/src/api/.mocks/ru/pages/blogPage.json new file mode 100644 index 000000000000..575a3f7890f5 --- /dev/null +++ b/src/api/.mocks/ru/pages/blogPage.json @@ -0,0 +1,47 @@ +{ + "id": 969, + "name": "blog", + "createdAt": "2022-08-24T15:40:07.513Z", + "updatedAt": "2022-08-24T15:40:07.513Z", + "type": "default", + "isDeleted": false, + "pageId": 969, + "locale": "ru", + "publishedVersionId": 17498, + "lastVersionId": 17498, + "content": { + "blocks": [ + { + "type": "blog-feed-block", + "resetPaddings": true, + "image": "https://storage.yandexcloud.net/yandex-opensource/blog-cover-bg.png", + "title": "Блог" + } + ] + }, + "title": "Blog", + "noIndex": false, + "shareTitle": null, + "shareDescription": null, + "shareImage": null, + "pageLocaleId": 1261, + "author": "author", + "metaDescription": null, + "keywords": [], + "shareGenImage": null, + "shareGenTitle": null, + "tempShareGenTitle": null, + "solution": null, + "service": null, + "regions": [], + "locales": [ + { + "locale": "en", + "publishedVersionId": null + }, + { + "locale": "ru", + "publishedVersionId": 17498 + } + ] +} diff --git a/src/api/.mocks/ru/pages/gravity-ui-in-opensource.json b/src/api/.mocks/ru/pages/gravity-ui-in-opensource.json new file mode 100644 index 000000000000..bb425358e08e --- /dev/null +++ b/src/api/.mocks/ru/pages/gravity-ui-in-opensource.json @@ -0,0 +1,73 @@ +{ + "id": 70, + "name": "blog/gravity-ui-in-opensource", + "createdAt": "2025-12-25T10:46:31.596Z", + "updatedAt": "2025-12-25T10:46:31.596Z", + "type": "default", + "isDeleted": false, + "versionOnTranslationId": null, + "searchCategorySlug": "blog", + "regions": [], + "pageId": 70, + "regionCode": "ru-ru", + "publishedVersionId": 194, + "lastVersionId": 194, + "content": "blocks:\n - type: blog-header-block\n resetPaddings: true\n paddingBottom: l\n width: m\n verticalOffset: m\n theme: dark\n background:\n image:\n src: https://storage.yandexcloud.net/yandex-opensource/blog-cover-bg.png\n disableCompress: true\n color: ''\n fullWidth: false\n - type: blog-layout-block\n resetPaddings: true\n mobileOrder: reverse\n children:\n - type: blog-author-block\n column: right\n resetPaddings: true\n authorId: 1069\n - type: blog-yfm-block\n column: right\n resetPaddings: true\n text: \"\\nВ этой статье:\\n\\n - [В чём особенности Gravity\\_UI](#peculiarities)\\n - [Как работать с Gravity\\_UI](#work)\\n - [Как воспользоваться Gravity\\_UI](#use)\\n\"\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\nВсем привет, я Алексей Сизиков, руководитель отдела User Experience в Yandex Cloud. В этой статье я хочу поделиться новостью: мы выпустили нашу дизайн‑систему и библиотеку компонентов [Gravity\\_UI](https://github.com/gravity-ui){target=\\\"_blank\\\"} в опенсорс. \\n\\nС помощью библиотеки компонентов Gravity\\_UI можно строить современные интерфейсы. В неё входит:\\n\\n * набор базовых React‑компонентов;\\n * библиотека‑конструктор для лендингов;\\n * [подробные гайды](https://gravity-ui.com/design){target=\\\"_blank\\\"} по использованию компонентов;\\n * библиотека в [Figma](https://www.figma.com/community/file/1271150067798118027/Gravity-UI-Design-System-(Beta)){target=\\\"_blank\\\"}; \\n * набор готовых иконок, в составе которого почти 600 вариантов;\\n * ChartKit — пакет для визуализации данных;\\n * Yagr — высокопроизводительный рендеринг графиков, основанный на uPlot;\\n * I18n — пакет для локализации интерфейса\\n * и ещё более [25 полезных библиотек](https://gravity-ui.com/libraries){target=\\\"_blank\\\"}.\\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: ''\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic0.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\nПод катом — рассказ, зачем мы сделали Gravity\\_UI, как его используем, в чём особенности и преимущества нашего подхода и как мы планируем развивать его дальше. А ещё — как настроить разные цветовые схемы в своих проектах и почему у нас четыре темы вместо двух стандартных.\\n\\n{% cut \\\"Зачем мы сделали Gravity\\_UI\\\" %}\\n\\nИзначально библиотека UIKit была внутренним продуктом для ускорения работы команды. По мере роста числа новых сервисов мы поставили цель: построить единый UX в наших продуктах. Нам было важно использовать одинаковые паттерны поведения пользователей в сервисах, чтобы пользователь ощущал всю платформу как единое целое.\\n\\nДополнительной целью дизайн‑команды было создать такие инструменты, чтобы разработчики смогли без привлечения дизайнеров сделать новый сервис.\\n\\nОтносительно недавно платформы и сервисы, использующие нашу дизайн‑систему, начали выходить в опенсорс: [YTsaurus](https://ytsaurus.tech/){target=\\\"_blank\\\"}, [YDB](https://ydb.tech/){target=\\\"_blank\\\"}, [DataLens](https://datalens.tech/){target=\\\"_blank\\\"}, [Diplodoc](https://diplodoc.com/){target=\\\"_blank\\\"}. Многие пользователи позитивно отзывались о них и помогали улучшать код вместе с разработчиками. Вдохновившись их примером, мы пришли к идее выпустить в открытый доступ и Gravity\\_UI, потому что видели, насколько библиотека может быть полезна многим сервисам не только внутри Яндекса.\\n\\n{% endcut %}\\n\"\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\n## В чём особенности Gravity\\_UI{#peculiarities}\\n\\n### Основано на реальном опыте\\n\\nОдна из отличительных черт нашей дизайн‑системы — она развивается на основе потребностей наших пользователей, большинство из которых являются разработчиками. Более того, наши дизайнеры неразрывно связаны с продуктами, в которых они работают. У каждого дизайнера есть несколько сервисов с собственными сценариями использования. После того как решение протестировано в их сервисах, продуктовый дизайнер передаёт его в другие сервисы, чтобы убедиться, что оно работает и помогает разработчикам. \\n\\nНапример, компонент боковой навигации изначально развивался только с логотипом и пунктами меню. Позже для удобства мы добавили пункт со всеми сервисами и поиском. А когда у нас появился сервис, где была необходимость создавать новую сущность сразу в боковом меню, у нас появилась отдельная кнопка с плюсиком. Дальше появились разделы меню с разделителями для сложных сервисов с большим количеством пунктов меню, а также кнопка «Остальные пункты».\\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n paddingBottom: s\n text: >-\n Компонент Навигации — можно настроить как простой вариант, так и\n максимально нагруженный\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic1.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\n### Гибкая вариативность\\n\\nМногие компоненты Gravity\\_UI можно настроить, учитывая разные сценарии. Например, у компонента [pagination](https://gravity-ui.com/components/uikit/pagination){target=\\\"_blank\\\"} есть несколько вариантов отображения: с общим числом страниц, полными подписями кнопок, возможностью перейти к конкретной странице и изменить число ответов на странице — этот вариант рассчитан на большое число страниц. А если у вас кейс, где результатов ответов немного, можно сделать компактный режим или даже скрыть цифры и показывать только стрелочки. \\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n paddingBottom: s\n text: Пример отображения разных вариантов пагинации\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic2.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\n### Широкая область применения\\n\\nПри помощи Gravity\\_UI можно сделать как простой интерфейс для администрирования, так и сложный дашборд с графиками. Вот несколько примеров того, что можно собрать с помощью нашей дизайн‑системы:\\n\\n * лендинги,\\n * админки,\\n * дашборды,\\n * графики,\\n * СRM,\\n * аналитический сервис.\\n\\nНапример, наши коллеги сделали такой дашборд:\\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: \"Пример дашборда, который можно сделать с помощью Gravity\\_UI\"\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic3.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\nТакже можно сделать простой лендинг. Например, [сайт](https://opensource.yandex/){target=\\\"_blank\\\"} с нашими проектами в опенсорс сделан на компонентах Gravity\\_UI. \\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n paddingBottom: s\n text: >-\n А это пример сайта, который тоже можно сделать с помощью нашей\n дизайн‑системы\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic4.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n ### Более 150 контрибьюторов\n\n\n Наша экосистема постоянно развивается и улучшается. Кроме обратной\n связи от нашего сообщества разработчиков, к нам поступают предложения\n более чем от 100 сервисов, которые уже используют нашу\n дизайн‑систему. \n\n\n Приведу пример. Изначально у нас было две темы — тёмная и светлая. Но\n мы стали получать фидбэк от команд, которые транслируют интерфейс на\n телевизоры для просмотра графиков или во время стендапа. Дело в том,\n что на телевизоре плохо видно интерфейс. Похожая проблема встречается\n также у пользователей со старыми или низкокачественными мониторами.\n\n\n В итоге разработали повышенную контрастность для каждой из тем. Она\n увеличивает яркость тёмного и светлого, а также семантических цветов.\n Это настраивается CSS‑стилями, а управляется в настройках\n пользователя.\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: \"Пример интерфейса Yandex Tracker, сделанный также на компонентах Gravity\\_UI, с возможностью включения повышенной контрастности\"\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic5.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n Кстати, теперь вы тоже можете сделать свой вклад. Для этого присылайте\n PR в GitHub или оставляйте комментарии в Figma.\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\n## Как работать с Gravity\\_UI{#work}\\n\\n### Настройка интерфейса под свой бренд\\n\\nДалее я расскажу о том, что ещё можно сделать с помощью Gravity\\_UI. Начну с возможности настроить дизайн‑систему под свой бренд. Например, когда YDB выходил в опенсорс, перед нами встала задача сохранить единую дизайн‑систему, но при этом сделать её особенной для разных брендов. Для этого мы создали отдельную группу CSS‑переменных. В неё входят цвета бренда, шрифты и радиусы скруглений. В коде это выглядит как небольшой блок:\\n\\n```json \\n.g-root {\\n --g-font-family-sans: 'Inter', sans-serif;\\n\\n --g-text-header-font-weight: 600;\\n --g-text-subheader-font-weight: 600;\\n --g-text-display-font-weight: 600;\\n --g-text-accent-font-weight: 600;\\n\\n --g-color-base-brand: rgb(117, 155, 255);\\n --g-color-base-brand-hover: rgb(99, 143, 255);\\n --g-color-base-selection: rgba(82, 130, 255, 0.05);\\n --g-color-base-selection-hover: rgba(82, 130, 255, 0.1);\\n --g-color-line-brand: rgb(117, 155, 255);\\n --g-color-text-brand: rgb(117, 155, 255);\\n --g-color-text-brand-contrast: rgb(255, 255 ,255);\\n --g-color-text-link: rgb(117, 155, 255);\\n --g-color-text-link-hover: rgb(82, 130, 255);\\n\\n --g-border-radius-xs: 3px;\\n --g-border-radius-s: 5px;\\n --g-border-radius-m: 6px;\\n --g-border-radius-l: 8px;\\n --g-border-radius-xl: 10px;\\n --g-border-radius-2xl: 16px;\\n}\\n```\\n\\nВ этой группе можно заменить шрифт, цвет акцентных кнопок, скругления. И таким образом можно использовать одну дизайн‑систему для разных брендов, сохраняя при этом фирменный стиль. Если же этот вариант вам не подходит, можно создать собственную цветовую схему. Подробная инструкция есть в [документации](https://preview.gravity-ui.com/uikit/?path=/docs/branding-overview--docs#additional-customization){target=\\\"_blank\\\"}.\\n\"\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: Пример интерфейсов с разными переменными бренда\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic6.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n Стоит отметить, что изменение цветов бренда не повлияет на основной\n интерфейс. Это особенно важно для тех элементов, где используются\n семантические цвета: например, красный по‑прежнему будет означать\n ошибку, а зелёный — успех.\n\n\n ### Компоненты в Figma\n\n\n Для удобства работы наша команда дизайнеров подготовила и загрузила\n все состояния компонентов в\n [Figma](https://www.figma.com/community/file/1271150067798118027){target=\"_blank\"}.\n При желании можно сделать копию библиотеки и попробовать собрать\n интерфейс сразу в сервисе.\n\n\n С последним обновлением в библиотеке не дублируются все четыре темы.\n По умолчанию вы работаете в светлой теме, но в разделе Layer вы можете\n переключить любой элемент или всю страницу на другую тему. \n - type: blog-media-block\n column: left\n resetPaddings: true\n text: Как просмотреть элемент в разных темах\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic7.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n Все элементы библиотеки представлены на странице Overview. Тут вы\n можете найти нужный компонент и перейти на страницу со всеми\n состояниями элемента. Кроме того, у каждого компонента есть пример\n использования. \n - type: blog-media-block\n column: left\n resetPaddings: true\n paddingBottom: s\n text: \"Страница со всеми элементами Gravity\\_UI\"\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic8.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n ### Почти 600 иконок\n\n Иконки — один из обязательных элементов дизайна и юзабилити. Они\n помогают организовать и структурировать контент, расставить акценты и\n улучшить восприятие информации. На первый взгляд, сделать пак иконок\n не так уж и сложно. Но мы столкнулись с вызовом при создании иконок\n для сложных метафор, таких как виртуальные машины, базы данных и\n различные типы графиков.\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: Пока у нас 594 иконки, но скоро их станет больше\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic9.png\n fullscreen: true\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: >-\n Особой задачей стала и разработка иконок для графического редактора\n контента (WYSIWYG), который внедряется в различные места для\n форматирования текста \n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic10.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n Чтобы сделать поиск иконок более удобным, мы использовали специальную\n систему нейминга. Теперь одну и ту же иконку можно найти, вводя разные\n названия. Например, чтобы найти такую иконку со стрелочкой, можно\n ввести любое слово: arrow, enter, move, login.\n - type: blog-media-block\n column: left\n resetPaddings: true\n paddingBottom: s\n text: >-\n Все иконки доступны на [отдельной\n странице](https://gravity-ui.com/icons). Вы можете скопировать SVG или\n скачать любую иконку\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic11.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: >\n\n ### Гайды\n\n\n Как я уже писал выше, наша цель заключалась в том, чтобы разработчики\n могли легко создавать типовые интерфейсы, используя описания\n компонентов в нашем гайде. Мы стремились сделать этот процесс простым,\n без необходимости обращаться к дизайнеру за каждым элементом. На\n данный момент у нас уже есть пять примеров внутренних сервисов,\n которые были полностью созданы разработчиками с использованием только\n гайдов.\n\n\n Конечно, одними руками разработчика эту задачу решить не получится:\n так или иначе есть сложные сценарии, которые требуют внимания\n UX/UI‑специалиста. Тем не менее мы смогли снять значительную часть\n нагрузки с наших дизайнеров.\n\n\n В гайдах команда дизайнеров описала компоненты и дала рекомендации по\n их использованию, демонстрируя примеры правильного и неправильного\n подхода. Вы можете ознакомиться с ними на [этой\n странице](https://gravity-ui.com/components/uikit/alert){target=\"_blank\"}.\n - type: blog-media-block\n column: left\n resetPaddings: true\n text: ''\n image:\n src: >-\n https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/pic12.png\n fullscreen: true\n - type: blog-yfm-block\n column: left\n resetPaddings: true\n text: \"\\n## Как воспользоваться Gravity\\_UI{#use}\\n\\nВсё, что нужно сделать, — вбить команду в консоль:\\n\\n```\\ngit clone git@github.com:gravity-ui/uikit-example-cra.git my-project && cd my-project\\nnpm i \\nnpm run start\\n```\\n\\nБолее подробная инструкция есть на главной странице репозитория в [GitHub](https://github.com/gravity-ui/uikit){target=\\\"_blank\\\"}.\\n\\nВсе компоненты Gravity\\_UI можно посмотреть в [UIkit](https://preview.gravity-ui.com/uikit/){target=\\\"_blank\\\"}, а подключить нужную библиотеку для ваших потребностей — в [Libraries](https://gravity-ui.com/libraries){target=\\\"_blank\\\"}. \\n\\n--------\\n\\nПодводя итоги, хочется ещё раз отметить: Gravity\\_UI — это дизайн‑система, которая выросла из реального опыта наших пользователей, потребности разработчиков и экспертизы дизайнеров. Это позволяет ей быть практичной и эффективной. И теперь ею может бесплатно воспользоваться любой желающий.\\n\\nМы стремимся сделать проект ещё лучше, учитывая потребности и отзывы наших пользователей. Заходите к нам в GitHub, оставляйте свои PR, пишите комментарии в Figma и делитесь примерами использования.\\n\"\n - type: blog-layout-block\n resetPaddings: true\n fullWidth: false\n children:\n - type: blog-meta-block\n column: left\n resetPaddings: true\n - type: blog-suggest-block\n resetPaddings: true\n", + "title": "", + "noIndex": false, + "shareTitle": null, + "shareDescription": null, + "shareImage": "https://storage.yandexcloud.net/yandex-opensource/blog-cover-bg.png", + "pageLocaleId": null, + "author": "ngorin", + "metaDescription": null, + "keywords": [], + "shareGenTitle": null, + "canonicalLink": null, + "sharingType": "semi-full", + "sharingTheme": "dark", + "comment": "gravity", + "shareImageUrl": "https://storage.cloud-preprod.yandex.net/ui-api-ru-preprod-stable-share-generator-screenshots/cache/8c45f347a6e585754d1d6e4949c9c5a20a2d570e.png", + "pageRegionId": 73, + "summary": null, + "versionId": 194, + "service": null, + "solution": null, + "locales": [ + { + "id": 73, + "pageId": 70, + "locale": "ru", + "createdAt": "2025-12-25T10:43:18.571Z", + "updatedAt": "2025-12-25T10:43:18.615Z", + "publishedVersionId": null, + "lastVersionId": 190 + }, + { + "id": 74, + "pageId": 70, + "locale": "en", + "createdAt": "2025-12-25T10:43:18.620Z", + "updatedAt": "2025-12-25T10:43:18.926Z", + "publishedVersionId": null, + "lastVersionId": 191 + } + ], + "pageRegions": [ + { + "regionCode": "en", + "publishedVersionId": null + }, + { + "regionCode": "ru-ru", + "publishedVersionId": 194 + } + ], + "searchCategory": { + "id": 7, + "slug": "blog", + "title": "Блог", + "url": "/blog" + }, + "voiceovers": [] + } \ No newline at end of file diff --git a/src/api/.mocks/ru/posts/gravity-ui-in-opensource.json b/src/api/.mocks/ru/posts/gravity-ui-in-opensource.json new file mode 100644 index 000000000000..cc1407d9448b --- /dev/null +++ b/src/api/.mocks/ru/posts/gravity-ui-in-opensource.json @@ -0,0 +1,34 @@ +{ + "id": 35, + "name": "gravity-ui-in-opensource", + "isPinned": false, + "postId": 35, + "description": "", + "image": "https://storage.yandexcloud.net/yandex-opensource/blog-cover-bg.png", + "readingTime": 10, + "title": "Дизайн-система Gravity UI: как легко построить свой интерфейс", + "date": "2025-12-25T00:00:00Z", + "likes": 0, + "hasUserLike": false, + "addLegacyPrefix": false, + "tags": [ + { + "slug": "articles", + "icon": "", + "name": "Статьи" + } + ], + "authors": [ + { + "id": 1069, + "avatar": "https://storage.yandexcloud.net/cloud-www-assets/blog-assets/ru/posts/2025/12/gravity-ui-in-opensource/sizikov.png", + "firstName": "Алексей", + "secondName": "Сизиков", + "description": "Yandex Cloud", + "fullDescription": "Руководитель отдела User Experience, Yandex Cloud", + "shortDescription": "Руководитель отдела User Experience, Yandex Cloud", + "fullName": "Алексей Сизиков" + } + ], + "services": [] + } \ No newline at end of file diff --git a/src/api/.mocks/ru/posts/index.json b/src/api/.mocks/ru/posts/index.json new file mode 100644 index 000000000000..c962bbb73b23 --- /dev/null +++ b/src/api/.mocks/ru/posts/index.json @@ -0,0 +1,31 @@ +{ + "posts": [ + { + "id": 35, + "name": "gravity-ui-in-opensource", + "date": "2025-12-25T00:00:00Z", + "title": "Дизайн-система Gravity UI: как легко построить свой интерфейс", + "postId": 35, + "description": "", + "image": "https://storage.yandexcloud.net/yandex-opensource/blog-cover-bg.png", + "readingTime": 10, + "likes": 0, + "hasUserLike": false, + "hasPublishedVersionInRegion": true, + "hasPublishedVersionInLocale": false, + "addLegacyPrefix": false, + "tags": [ + { + "slug": "articles", + "icon": "", + "name": "Статьи" + } + ], + "services": [], + "url": "/blog/gravity-ui-in-opensource" + } + ], + "totalCount": 1, + "count": 1, + "pinnedPost": null +} diff --git a/src/api/.mocks/ru/tags.json b/src/api/.mocks/ru/tags.json new file mode 100644 index 000000000000..fe3e142affd9 --- /dev/null +++ b/src/api/.mocks/ru/tags.json @@ -0,0 +1,14 @@ +[ + { + "id": 1, + "slug": "articles", + "createdAt": "2020-03-13T11:00:57.360Z", + "updatedAt": "2022-07-22T08:50:25.432Z", + "icon": "", + "isDeleted": false, + "name": "Статьи", + "locale": "ru", + "blogTagId": 1, + "count": 1 + } +] diff --git a/src/api/index.ts b/src/api/index.ts index fa6f4d45a360..610049bae90c 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -2,6 +2,12 @@ import fs from 'fs'; import path from 'path'; import {fileURLToPath} from 'url'; +import type {MarkdownItPluginCb} from '@diplodoc/transform/lib/plugins/typings'; +import { + createReadableContent, + transformPageContent, + transformPost, +} from '@gravity-ui/blog-constructor/server'; import {createAppAuth} from '@octokit/auth-app'; import {Octokit} from '@octokit/rest'; import {i18n} from 'next-i18next.config'; @@ -20,6 +26,142 @@ export type CodeOwners = { owners: string[]; }; +// Blog types +export type BlogTag = { + id: number; + slug: string; + createdAt: string; + updatedAt: string; + icon: string | null; + isDeleted: boolean; + name: string; + locale: string; + blogTagId: number; + count: number; +}; + +export type BlogService = { + id: number; + name: string; + slug: string; +}; + +export type BlogAuthor = { + id: number; + firstName: string; + secondName: string; + description: string; + fullDescription?: string; + shortDescription: string; + avatar: string; + createdAt: string; + updatedAt: string; +}; + +export type BlogPostListItem = { + id: number; + slug: string; + date: string; + postDate: string; + blogPostId: number; + image: string; + readingTime: number; + keywords: string[]; + shareTitle: string | null; + likes: number; + hasUserLike: boolean; + services: BlogService[]; + url: string; + tags: BlogTag[]; + textTitle: string; + htmlTitle: string; + metaTitle: string; + description: string; + content: string; +}; + +export type BlogPost = { + id: number; + slug: string; + createdAt: string; + updatedAt: string; + isDeleted: boolean; + pageId: number; + postDate: string; + isPinned: boolean; + migrated: boolean; + date: string; + title: string; + shareTitle: string | null; + description: string; + author: string | null; + sharedImage: string; + content: string; + locale: string; + isPublished: boolean; + blogPostId: number; + image: string; + metaDescription: string | null; + keywords: string[] | null; + metaTitle: string | null; + readingTime: number; + likes: number; + hasUserLike: boolean; + tags: BlogTag[]; + authors: BlogAuthor[]; + shareOptions?: string[]; + textTitle?: string; + htmlTitle?: string; +}; + +export type BlogPostsResponse = { + posts: BlogPostListItem[]; + totalCount: number; + count: number; + pinnedPost: BlogPostListItem | null; +}; + +export type BlogPageContent = { + blocks: Array>; +}; + +export type BlogPage = { + id: number; + name: string; + createdAt: string; + updatedAt: string; + type: string; + isDeleted: boolean; + pageId: number; + locale: string; + publishedVersionId: number; + lastVersionId: number; + content: BlogPageContent; + title: string; + noIndex: boolean; + shareTitle: string | null; + shareDescription: string | null; + shareImage: string | null; + pageLocaleId: number; + author: string; + metaDescription: string | null; + keywords: string[]; + shareGenImage: string | null; + shareGenTitle: string | null; + solution: string | null; + service: string | null; + regions?: string[]; + locales?: Array<{locale: string; publishedVersionId: number | null}>; +}; + +export type BlogPostsQuery = { + page?: number; + pageSize?: number; + search?: string; + tags?: string[]; + services?: string[]; +}; + export type LibMetadata = { stars: number; version: string; @@ -588,4 +730,170 @@ export class Api { return content; } + + // Blog API methods + // Currently returning mock data. Will be replaced with real API calls later. + + /** + * Get blog post by slug + * @param locale - Current locale (not used for now, same data for all locales) + * @param slug - Full post slug (e.g., "posts/2022/09/review") + * @returns Blog post with page content + * + * TODO: When connecting to real API, parse slug to extract date and post slug + * Example: "posts/2022/09/review" -> { year: 2022, month: 09, slug: "review" } + */ + async getBlogPost(locale: string, slug: string): Promise<{post: BlogPost; page: BlogPage}> { + try { + // Determine lang and region from locale + + const lang = locale.split('-')[0] as 'en' | 'ru'; + const region = locale.includes('-') ? locale : `${locale}-${locale}`; + + const postMock = await import(`./.mocks/${lang}/posts/${slug}.json`); + const pageMock = await import(`./.mocks/${lang}/pages/${slug}.json`); + + // Plugins for markdown transformation (empty array for now) + const plugins: MarkdownItPluginCb[] = []; + + // Transform post using transformPost from blog-constructor + const transformedPost = transformPost({ + postData: postMock.default, + lang, + region, + plugins, + }) as unknown as BlogPost; + + // Transform page content using transformPageContent from blog-constructor + const transformedPageContent: Parameters[number] = + transformPageContent({ + content: pageMock.default.content, + lang, + region, + plugins: plugins as MarkdownItPluginCb[], + }); + + return { + post: { + ...transformedPost, + locale, + }, + page: { + ...pageMock.default, + content: transformedPageContent, + } as unknown as BlogPage, + }; + } catch (error) { + console.error('Error fetching blog post:', error); + throw new Error(`Failed to fetch blog post: ${slug}`); + } + } + + /** + * Get list of blog tags + * @param locale - Current locale (not used for now, same data for all locales) + * @returns Array of blog tags + * + * TODO: When connecting to real API, filter tags by locale + */ + async getBlogTags(locale: string): Promise { + try { + const tagsMock = await import(`./.mocks/${locale}/tags.json`); + return tagsMock.default; + } catch (error) { + console.error('Error fetching blog tags:', error); + return []; + } + } + + /** + * Get list of blog posts with filtering + * @param locale - Current locale (not used for now, same data for all locales) + * @param _query - Query parameters for filtering and pagination + * @returns Blog posts response with pagination info + * + * TODO: When connecting to real API, implement actual filtering and pagination + */ + async getBlogPosts( + locale: string, + _query?: BlogPostsQuery, + ): Promise { + try { + const postsMock = (await import(`./.mocks/${locale}/posts/index.json`)) as { + default: BlogPostsResponse; + }; + const blogPageMock = await import(`./.mocks/${locale}/pages/blogPage.json`); + const {preparePost} = await import('../utils/blog'); + + // Transform locale string to object with lang property + const localeObj = {lang: locale}; + + // Transform mock data using preparePost + const transformedPosts = postsMock.default.posts.map((post: any) => { + const preparedPost = preparePost({ + postData: { + ...post, + title: post.textTitle || post.htmlTitle || post.title || 'Untitled', + }, + locale: localeObj, + withContent: false, + }); + + return { + ...preparedPost, + locale, + } as unknown as BlogPostListItem; + }); + + const transformedPinnedPost = postsMock.default.pinnedPost + ? (() => { + const preparedPost = preparePost({ + postData: { + ...postsMock.default.pinnedPost, + title: + (postsMock.default.pinnedPost as any).title || + (postsMock.default.pinnedPost as any).textTitle || + 'Untitled', + }, + locale: localeObj, + withContent: false, + }); + + return { + ...preparedPost, + locale, + } as unknown as BlogPostListItem; + })() + : null; + + // For now, return all mock data without filtering + // TODO: Implement filtering by tags, services, search when connecting to real API + return { + posts: transformedPosts, + count: postsMock.default.count, + totalCount: postsMock.default.totalCount, + pinnedPost: transformedPinnedPost, + page: blogPageMock.default as unknown as BlogPage, + }; + } catch (error) { + console.error('Error fetching blog posts:', error); + throw new Error('Failed to fetch blog posts'); + } + } + + /** + * Get suggested posts for a blog post + * @param locale - Current locale (not used for now, same data for all locales) + * @param _postId - Current post ID (not used for now, returns mock data) + * @returns Array of suggested posts + * + * TODO: When connecting to real API, get related posts based on postId + */ + async getSuggestedPosts(_locale: string, _postId?: number): Promise { + try { + } catch (error) { + console.error('Error fetching suggested posts:', error); + return []; + } + } } diff --git a/src/blocks/Contributors/Contributors.scss b/src/blocks/Contributors/Contributors.scss index 1ab65ca0cd4f..a9adb3507f01 100644 --- a/src/blocks/Contributors/Contributors.scss +++ b/src/blocks/Contributors/Contributors.scss @@ -21,10 +21,13 @@ $block: '.#{variables.$ns}contributors'; } &__header-title { - @include pcStyles.heading2(); padding: 0; } + &__header-title-content { + @include pcStyles.heading2(); + } + &__header-count { flex-grow: 1; font-size: 32px; diff --git a/src/blocks/Contributors/Contributors.tsx b/src/blocks/Contributors/Contributors.tsx index 4ad66b6c122b..951268df1a83 100644 --- a/src/blocks/Contributors/Contributors.tsx +++ b/src/blocks/Contributors/Contributors.tsx @@ -1,4 +1,4 @@ -import {Animatable, AnimateBlock, HTML} from '@gravity-ui/page-constructor'; +import {Animatable, AnimateBlock, YFMWrapper} from '@gravity-ui/page-constructor'; import {Button} from '@gravity-ui/uikit'; import React from 'react'; @@ -36,7 +36,11 @@ export const ContributorsBlock: React.FC = ({

- {title} +

{contributors.length}
diff --git a/src/blocks/CustomHeader/CustomHeader.scss b/src/blocks/CustomHeader/CustomHeader.scss index 831efa0d3046..5327bcdfeac8 100644 --- a/src/blocks/CustomHeader/CustomHeader.scss +++ b/src/blocks/CustomHeader/CustomHeader.scss @@ -15,8 +15,12 @@ $block: '.#{variables.$ns}custom-header'; } &__title { - @include pcStyles.heading1(); max-width: 800px; + margin: 0; + } + + &__title-content { + @include pcStyles.heading1(); } &__buttons { diff --git a/src/blocks/CustomHeader/CustomHeader.tsx b/src/blocks/CustomHeader/CustomHeader.tsx index 823aa1bc9c1b..aba6766a5347 100644 --- a/src/blocks/CustomHeader/CustomHeader.tsx +++ b/src/blocks/CustomHeader/CustomHeader.tsx @@ -1,5 +1,5 @@ import {ChevronRight} from '@gravity-ui/icons'; -import {Animatable, AnimateBlock, Col, Grid, HTML, Row} from '@gravity-ui/page-constructor'; +import {Animatable, AnimateBlock, Col, Grid, Row, YFMWrapper} from '@gravity-ui/page-constructor'; import {Button, ButtonProps, Flex, Icon, IconData, Text} from '@gravity-ui/uikit'; import React from 'react'; import ReactTimeAgo from 'react-time-ago'; @@ -99,7 +99,11 @@ export const CustomHeader: React.FC = ({ )}

- {title} +

{buttons?.length > 0 ? (
@@ -147,7 +151,10 @@ export const CustomHeader: React.FC = ({ />
- {newsItem.content} +
) : null, diff --git a/src/blocks/Examples/Examples.tsx b/src/blocks/Examples/Examples.tsx index 0b3b6cbd2285..23014f31905c 100644 --- a/src/blocks/Examples/Examples.tsx +++ b/src/blocks/Examples/Examples.tsx @@ -1,4 +1,4 @@ -import {Animatable, AnimateBlock, HTML} from '@gravity-ui/page-constructor'; +import {Animatable, AnimateBlock, YFMWrapper} from '@gravity-ui/page-constructor'; import {Button, Icon, SegmentedRadioGroup, Select, SelectOption, Theme} from '@gravity-ui/uikit'; import {useTranslation} from 'next-i18next'; import React from 'react'; @@ -55,7 +55,7 @@ export const Examples: React.FC = ({animated, title, colors}) =>

- {title} +

diff --git a/src/blocks/GithubStarsBlock/GithubStarsBlock.tsx b/src/blocks/GithubStarsBlock/GithubStarsBlock.tsx index ff619ece6f1b..4729b16e1c87 100644 --- a/src/blocks/GithubStarsBlock/GithubStarsBlock.tsx +++ b/src/blocks/GithubStarsBlock/GithubStarsBlock.tsx @@ -1,5 +1,5 @@ import {ChevronRight} from '@gravity-ui/icons'; -import {Animatable, HTML} from '@gravity-ui/page-constructor'; +import {Animatable, YFMWrapper} from '@gravity-ui/page-constructor'; import {Icon, Text} from '@gravity-ui/uikit'; import {useTranslation} from 'next-i18next'; import {useRouter} from 'next/router'; @@ -43,7 +43,10 @@ export const GithubStarsBlock: React.FC = ({device}) => {
- {t('home:github_stars-text')} + diff --git a/src/blocks/Libraries/Libraries.tsx b/src/blocks/Libraries/Libraries.tsx index d7b510370634..99d3b0f526b9 100644 --- a/src/blocks/Libraries/Libraries.tsx +++ b/src/blocks/Libraries/Libraries.tsx @@ -83,7 +83,6 @@ export const Libraries: React.FC = ({ return ( = ({lib, contentStyle
{title ? (
- {title} +
) : null} {stars ? ( diff --git a/src/blocks/RoadmapBlock/RoadmapBlock.scss b/src/blocks/RoadmapBlock/RoadmapBlock.scss index 09ca1563b569..476817875836 100644 --- a/src/blocks/RoadmapBlock/RoadmapBlock.scss +++ b/src/blocks/RoadmapBlock/RoadmapBlock.scss @@ -8,7 +8,10 @@ $block: '.#{variables.$ns}roadmap-block'; @include pcStyles.animate(); &__title { - @include pcStyles.heading2(); margin-bottom: pcVariables.$indentM; } + + &__title-content { + @include pcStyles.heading2(); + } } diff --git a/src/blocks/RoadmapBlock/RoadmapBlock.tsx b/src/blocks/RoadmapBlock/RoadmapBlock.tsx index 9e5fd5b7267f..45c52518db75 100644 --- a/src/blocks/RoadmapBlock/RoadmapBlock.tsx +++ b/src/blocks/RoadmapBlock/RoadmapBlock.tsx @@ -1,4 +1,4 @@ -import {Animatable, AnimateBlock, HTML} from '@gravity-ui/page-constructor'; +import {Animatable, AnimateBlock, YFMWrapper} from '@gravity-ui/page-constructor'; import React from 'react'; import {Roadmap, RoadmapTask} from '../../components/Roadmap'; @@ -22,7 +22,11 @@ export const RoadmapBlock: React.FC = ({animated, title, tasks}) = return (

- {title} +

diff --git a/src/blocks/TemplatesBlock/TemplatesBlock.scss b/src/blocks/TemplatesBlock/TemplatesBlock.scss index a97669cb0e99..066b0ca033ee 100644 --- a/src/blocks/TemplatesBlock/TemplatesBlock.scss +++ b/src/blocks/TemplatesBlock/TemplatesBlock.scss @@ -8,8 +8,10 @@ $block: '.#{variables.$ns}templates-block'; @include pcStyles.animate(); &__title { - @include pcStyles.heading2(); - margin-bottom: pcVariables.$indentM; } + + &__title-content { + @include pcStyles.heading2(); + } } diff --git a/src/blocks/TemplatesBlock/TemplatesBlock.tsx b/src/blocks/TemplatesBlock/TemplatesBlock.tsx index a56955df0721..ef7261cbc746 100644 --- a/src/blocks/TemplatesBlock/TemplatesBlock.tsx +++ b/src/blocks/TemplatesBlock/TemplatesBlock.tsx @@ -1,4 +1,4 @@ -import {Animatable, AnimateBlock, HTML} from '@gravity-ui/page-constructor'; +import {Animatable, AnimateBlock, YFMWrapper} from '@gravity-ui/page-constructor'; import React from 'react'; import {Templates} from '../../components/Templates'; @@ -40,7 +40,11 @@ export const TemplatesBlock: React.FC = ({animated, title, tabs}

- {title} +

diff --git a/src/blocks/UISamples/UISamples.scss b/src/blocks/UISamples/UISamples.scss index f17b0a594875..e7e93d38df01 100644 --- a/src/blocks/UISamples/UISamples.scss +++ b/src/blocks/UISamples/UISamples.scss @@ -8,7 +8,10 @@ $block: '.#{variables.$ns}ui-samples-block'; @include pcStyles.animate(); &__title { - @include pcStyles.heading2(); margin-bottom: pcVariables.$indentM; } + + &__title-content { + @include pcStyles.heading2(); + } } diff --git a/src/blocks/UISamples/UISamples.tsx b/src/blocks/UISamples/UISamples.tsx index bea314b4429c..3d4e2fbd1bde 100644 --- a/src/blocks/UISamples/UISamples.tsx +++ b/src/blocks/UISamples/UISamples.tsx @@ -1,4 +1,4 @@ -import {Animatable, AnimateBlock, HTML} from '@gravity-ui/page-constructor'; +import {Animatable, AnimateBlock, YFMWrapper} from '@gravity-ui/page-constructor'; import React from 'react'; import {block} from 'src/utils'; @@ -22,7 +22,11 @@ export const UISamplesBlock: React.FC = ({title}) => { return (

- {title} +

diff --git a/src/components/Interactive/Interactive.tsx b/src/components/Interactive/Interactive.tsx index 40c5946fd9fb..ba1e8b44d558 100644 --- a/src/components/Interactive/Interactive.tsx +++ b/src/components/Interactive/Interactive.tsx @@ -1,11 +1,10 @@ import {Theme} from '@gravity-ui/uikit'; import React from 'react'; -import 'swiper/css'; -import {Autoplay, EffectCreative} from 'swiper/modules'; -import {Swiper, SwiperClass, SwiperSlide} from 'swiper/react'; import {EnvironmentContext} from '../../contexts'; import {block} from '../../utils'; +import {Autoplay, EffectCreative, Swiper, SwiperSlide} from '../../utils/swiper'; +import type {SwiperClass} from '../../utils/swiper'; import './Interactive.scss'; import {InteractiveContextProvider} from './InteractiveContext'; diff --git a/src/components/Libraries/Libraries.scss b/src/components/Libraries/Libraries.scss index 223b9e81aff6..9db698bc21d7 100644 --- a/src/components/Libraries/Libraries.scss +++ b/src/components/Libraries/Libraries.scss @@ -83,12 +83,9 @@ $block: '.#{variables.$ns}libraries'; &__library-title { flex: 1; - - @include pcStyles.heading4(); - display: flex; position: relative; - margin-bottom: pcVariables.$indentXXXS; + margin: 0 0 pcVariables.$indentXXXS 0; color: #fff; a { @@ -96,6 +93,10 @@ $block: '.#{variables.$ns}libraries'; } } + &__library-title-content { + @include pcStyles.heading4(); + } + &__stars { display: flex; align-items: center; diff --git a/src/components/Libraries/Libraries.tsx b/src/components/Libraries/Libraries.tsx index 72af47242c8e..5efcee5d57bc 100644 --- a/src/components/Libraries/Libraries.tsx +++ b/src/components/Libraries/Libraries.tsx @@ -1,4 +1,4 @@ -import {Col, Grid, HTML, Row} from '@gravity-ui/page-constructor'; +import {Col, Grid, Row, YFMWrapper} from '@gravity-ui/page-constructor'; import {Icon, TextInput} from '@gravity-ui/uikit'; import {useTranslation} from 'next-i18next'; import React from 'react'; @@ -101,7 +101,11 @@ export const Libraries = ({libs}: Props) => { >
- {lib.config.title} +
{lib.metadata.stars ? (
diff --git a/src/components/Library/Library.scss b/src/components/Library/Library.scss index 7a25c1e01a65..5d51bad5c6a1 100644 --- a/src/components/Library/Library.scss +++ b/src/components/Library/Library.scss @@ -1,4 +1,5 @@ @use '~@gravity-ui/page-constructor/styles/variables.scss' as pcVariables; +@use '~@gravity-ui/page-constructor/styles/styles.scss' as pcStyles; @use '../../variables.scss'; $block: '.#{variables.$ns}library'; @@ -54,16 +55,13 @@ $block: '.#{variables.$ns}library'; } } - &__breadcrumbs-item { + &__breadcrumbs-title { + @include pcStyles.text-size(caption-3); color: #fff; } &__title { margin: 0 0 8px; - font-size: 32px; - line-height: 40px; - font-weight: 600; - color: #fff; @media (max-width: map-get(pcVariables.$gridBreakpoints, 'lg') - 1) { font-size: 28px; @@ -71,6 +69,11 @@ $block: '.#{variables.$ns}library'; } } + &__title-content { + @include pcStyles.heading2(); + color: #fff; + } + &__description { font-size: 17px; line-height: 24px; diff --git a/src/components/Library/Library.tsx b/src/components/Library/Library.tsx index 18660a6ad6c8..b82d6684d168 100644 --- a/src/components/Library/Library.tsx +++ b/src/components/Library/Library.tsx @@ -1,4 +1,4 @@ -import {Col, Grid, HTML, Row} from '@gravity-ui/page-constructor'; +import {Col, Grid, Row, YFMWrapper} from '@gravity-ui/page-constructor'; import {Button, Icon, Tab, TabList, TabProvider} from '@gravity-ui/uikit'; import {useTranslation} from 'next-i18next'; import React from 'react'; @@ -140,11 +140,20 @@ export const Library: React.FC = ({lib}) => { {t('library:libraries')} {' '} - / {lib.config.title} + /{' '} +

- {lib.config.title} +

diff --git a/src/components/LibraryPreview/LibraryPreview.tsx b/src/components/LibraryPreview/LibraryPreview.tsx index 9c3dd51c914e..6faccc032f08 100644 --- a/src/components/LibraryPreview/LibraryPreview.tsx +++ b/src/components/LibraryPreview/LibraryPreview.tsx @@ -1,4 +1,4 @@ -import {HTML} from '@gravity-ui/page-constructor'; +import {YFMWrapper} from '@gravity-ui/page-constructor'; import {Icon} from '@gravity-ui/uikit'; import React from 'react'; @@ -24,7 +24,10 @@ export const LibraryPreview = ({lib}: LibraryPreviewProps) => {

GravityUI

- {lib.config.title} +

diff --git a/src/components/Menu/LocalePicker/LocalePicker.tsx b/src/components/Menu/LocalePicker/LocalePicker.tsx index ff886877b413..4160297ac58b 100644 --- a/src/components/Menu/LocalePicker/LocalePicker.tsx +++ b/src/components/Menu/LocalePicker/LocalePicker.tsx @@ -26,6 +26,9 @@ export const LocalePicker: React.FC = () => { const appLocale = useLocale(); + // Check if we're on a blog page - blog is only available for en and ru + const isBlogPage = router.asPath.includes('/blog'); + const renderOption = React.useCallback((option: SelectOption) => { const locale = option.value; const localeUpperCase = option.value.toUpperCase(); @@ -43,13 +46,23 @@ export const LocalePicker: React.FC = () => { return null; } + // Filter locales for blog pages - only en and ru are available + const availableLocales = React.useMemo(() => { + if (isBlogPage) { + return i18nextConfig.i18n.locales.filter( + (locale) => locale === 'en' || locale === 'ru', + ); + } + return i18nextConfig.i18n.locales; + }, [isBlogPage]); + return (