diff --git a/.storybook/docs.tsx b/.storybook/docs.tsx new file mode 100644 index 00000000..897bf26f --- /dev/null +++ b/.storybook/docs.tsx @@ -0,0 +1,69 @@ +import React from 'react'; + +import { + Description, + DocsContext, + Subtitle, + Title, +} from '@storybook/addon-docs/'; + +const readmeCache: Record = {}; + +function importAllReadme(ctx: __WebpackModuleApi.RequireContext) { + const path = ctx.id.split(' ')[0].replace('./', '') + '/'; + ctx.keys().forEach((key) => { + const dirPath = key.replace(/^\.\//, path).replace(/\/readme\.md$/i, ''); + readmeCache[dirPath] = ctx(key); + }); +} + +importAllReadme(require.context('../src/components', true, /readme\.md$/i)); + +export const Docs = () => { + const context = React.useContext(DocsContext); + const fileName = context?.parameters?.fileName; + const kind = context.kind; + let isComponent = false; + if (kind && /Components\//.test(kind)) { + isComponent = true; + } + + let dirPath; + if (isComponent && fileName) { + const pathArr = fileName.split('/'); + dirPath = pathArr.slice(1, pathArr.length - 2).join('/'); + } + + let sourceBadgeContent; + if (dirPath) { + sourceBadgeContent = ( + + + + ); + } + + let readmeContent; + if (dirPath && readmeCache[dirPath]) { + readmeContent = ( +
+ ); + } + + return ( + <> + {/* */} + {sourceBadgeContent} + {/* <Subtitle /> */} + {/* <Description /> */} + {readmeContent} + </> + ); +}; diff --git a/.storybook/main.ts b/.storybook/main.ts index aae52fe7..7c31e256 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,5 +1,8 @@ import type {StorybookConfig} from '@storybook/core-common'; +const {join} = require('path'); + + const config: StorybookConfig = { stories: ['../src/**/*.stories.@(ts|tsx)'], addons: [ @@ -7,6 +10,21 @@ const config: StorybookConfig = { {name: '@storybook/addon-essentials', options: {backgrounds: false}}, './theme-addon/register.tsx', ], + + webpackFinal: (storybookBaseConfig) => { + storybookBaseConfig?.module?.rules.push({ + test: /\.md$/, + include: [join(__dirname, '../src')], + use: [{loader: 'markdown-loader'}], + }); + + // to turn fileName in context.parameters into path form number in production bundle + if (storybookBaseConfig?.optimization) { + storybookBaseConfig.optimization.moduleIds = 'named'; + } + + return storybookBaseConfig; + }, }; module.exports = config; diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 6aec932e..302c61ff 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,3 +1,4 @@ +import './styles.scss'; import '@gravity-ui/uikit/styles/styles.css'; import React from 'react'; @@ -7,6 +8,7 @@ import {ThemeProvider, MobileProvider, Lang, configure as uiKitConfigure} from ' import {configure} from '../src'; import {withMobile} from './decorators/withMobile'; import {withLang} from './decorators/withLang'; +import {Docs} from './docs'; configure({ lang: Lang.En, @@ -31,7 +33,7 @@ export const decorators = [withMobile, withLang, withContextProvider]; export const parameters = { docs: { - theme: 'light', + page: Docs, }, jsx: {showFunctions: true}, viewport: { diff --git a/.storybook/styles.scss b/.storybook/styles.scss new file mode 100644 index 00000000..1484276c --- /dev/null +++ b/.storybook/styles.scss @@ -0,0 +1 @@ +@import '~@doc-tools/transform/dist/css/yfm.css'; diff --git a/package-lock.json b/package-lock.json index 2ce94756..3a626b57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1738,6 +1738,48 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true }, + "@doc-tools/transform": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@doc-tools/transform/-/transform-3.1.0.tgz", + "integrity": "sha512-U1LqP7SS2f+d+W5Y8ICXAQGe2lgAsnoQPmh8dzWOusIpI7FTFEDeJ/qemVUlfRct0aaYzRE/Ms3zF5REPysMoQ==", + "dev": true, + "requires": { + "chalk": "4.1.2", + "get-root-node-polyfill": "1.0.0", + "github-slugger": "1.4.0", + "js-yaml": "^4.1.0", + "lodash": "4.17.21", + "markdown-it": "13.0.1", + "markdown-it-attrs": "4.1.4", + "markdown-it-deflist": "2.1.0", + "markdown-it-meta": "0.0.1", + "markdown-it-sup": "1.0.0", + "markdownlint": "^0.25.1", + "markdownlint-rule-helpers": "0.17.2", + "postcss": "8.4.16", + "sanitize-html": "2.7.3", + "slugify": "1.6.5" + }, + "dependencies": { + "github-slugger": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", + "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==", + "dev": true + }, + "postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + } + } + }, "@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -8508,9 +8550,9 @@ } }, "cyclist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", - "integrity": "sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz", + "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==", "dev": true }, "d": { @@ -8877,9 +8919,9 @@ "dev": true }, "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -11135,6 +11177,12 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, + "get-root-node-polyfill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-root-node-polyfill/-/get-root-node-polyfill-1.0.0.tgz", + "integrity": "sha512-AzucsG1DdepagLF8tkxfjUqn3cCQ63MgH/tBWwPSy0BIDt8iLFZYDwnTxA08d+zdgL8l2dkPdZDe+Qkd+RMl9Q==", + "dev": true + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -14942,6 +14990,15 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -15208,6 +15265,158 @@ "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", "dev": true }, + "markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "dev": true, + "requires": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "dependencies": { + "entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true + } + } + }, + "markdown-it-attrs": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/markdown-it-attrs/-/markdown-it-attrs-4.1.4.tgz", + "integrity": "sha512-53Zfv8PTb6rlVFDlD106xcZHKBSsRZKJ2IW/rTxEJBEVbVaoxaNsmRkG0HXfbHl2SK8kaxZ2QKqdthWy/QBwmA==", + "dev": true + }, + "markdown-it-deflist": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/markdown-it-deflist/-/markdown-it-deflist-2.1.0.tgz", + "integrity": "sha512-3OuqoRUlSxJiuQYu0cWTLHNhhq2xtoSFqsZK8plANg91+RJQU1ziQ6lA2LzmFAEes18uPBsHZpcX6We5l76Nzg==", + "dev": true + }, + "markdown-it-meta": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/markdown-it-meta/-/markdown-it-meta-0.0.1.tgz", + "integrity": "sha512-sCQG7mHJM3i4l6MztgzxE8t3aTQB5CSCO0wq8k6CEaqud40eryWXqPesq5AyztbYgwnxJcNIsmFsKDRkrl6Zuw==", + "dev": true, + "requires": { + "js-yaml": "^3.8.1" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } + } + }, + "markdown-it-sup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-sup/-/markdown-it-sup-1.0.0.tgz", + "integrity": "sha512-E32m0nV9iyhRR7CrhnzL5msqic7rL1juWre6TQNxsnApg7Uf+F97JOKxUijg5YwXz86lZ0mqfOnutoryyNdntQ==", + "dev": true + }, + "markdown-loader": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/markdown-loader/-/markdown-loader-6.0.0.tgz", + "integrity": "sha512-kUTEEpWRc5zcQbdjpK0QYdp/9Z5Oep440foKSXc7wWetcRxrWm4vbbXRW0Gqhht5CKJ4gm7el4HOPPyqs/ziTA==", + "dev": true, + "requires": { + "loader-utils": "^1.2.3", + "marked": "^0.7.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "markdownlint": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.25.1.tgz", + "integrity": "sha512-AG7UkLzNa1fxiOv5B+owPsPhtM4D6DoODhsJgiaNg1xowXovrYgOnLqAgOOFQpWOlHFVQUzjMY5ypNNTeov92g==", + "dev": true, + "requires": { + "markdown-it": "12.3.2" + }, + "dependencies": { + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true + }, + "linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "requires": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + } + } + }, + "markdownlint-rule-helpers": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.17.2.tgz", + "integrity": "sha512-XaeoW2NYSlWxMCZM2B3H7YTG6nlaLfkEZWMBhr4hSPlq9MuY2sy83+Xr89jXOqZMZYjvi5nBCGoFh7hHoPKZmA==", + "dev": true + }, + "marked": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", + "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", + "dev": true + }, "matchdep": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", @@ -16847,6 +17056,12 @@ "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", "dev": true }, + "parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", + "dev": true + }, "parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -18829,6 +19044,34 @@ } } }, + "sanitize-html": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.7.3.tgz", + "integrity": "sha512-jMaHG29ak4miiJ8wgqA1849iInqORgNv7SLfSw9LtfOhEUQ1C0YHKH73R+hgyufBW9ZFeJrb057k9hjlfBCVlw==", + "dev": true, + "requires": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^6.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + } + } + }, "sass": { "version": "1.62.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.62.0.tgz", @@ -19157,6 +19400,12 @@ "is-fullwidth-code-point": "^3.0.0" } }, + "slugify": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.5.tgz", + "integrity": "sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ==", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -20661,6 +20910,12 @@ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, "uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", diff --git a/package.json b/package.json index 67b000dd..350d082b 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "devDependencies": { "@commitlint/cli": "^17.0.0", "@commitlint/config-conventional": "^17.0.0", + "@doc-tools/transform": "^3.1.0", "@gravity-ui/eslint-config": "^1.0.0", "@gravity-ui/prettier-config": "^1.0.0", "@gravity-ui/stylelint-config": "^1.0.0", @@ -62,6 +63,7 @@ "gulp-typescript": "^5.0.1", "husky": "^8.0.0", "jest": "^28.0.0", + "markdown-loader": "^6.0.0", "nano-staged": "^0.6.0", "npm-run-all": "^4.0.0", "prettier": "^2.0.0", @@ -73,7 +75,8 @@ "style-loader": "^2.0.0", "stylelint": "^14.0.0", "ts-jest": "^28.0.0", - "typescript": "^4.0.0" + "typescript": "^4.0.0", + "webpack": "^4.46.0" }, "peerDependencies": { "@gravity-ui/uikit": "^4.0.0",