From 74790ffa6662bde6830c47532a129350d2121f99 Mon Sep 17 00:00:00 2001 From: Sergey Makhnatkin Date: Thu, 21 Nov 2024 14:06:55 +0100 Subject: [PATCH] chore(demo): integrated autogenerated docs into the demo (#490) --- .gitignore | 1 + .storybook/addons/generateDocs.ts | 106 ++++++++++++++++++ .storybook/main.ts | 10 +- .storybook/preview.ts | 2 +- ...how-to-add-editor-with-create-react-app.md | 2 + docs/how-to-add-editor-with-nextjs.md | 4 +- docs/how-to-add-preview.md | 2 + ...-add-text-binding-extension-in-markdown.md | 11 +- docs/how-to-connect-gpt-extensions.md | 11 +- docs/how-to-connect-html-extension.md | 4 +- docs/how-to-connect-latex-extension.md | 4 +- docs/how-to-connect-mermaid-extension.md | 4 +- docs/how-to-create-extension.md | 2 + docs/how-to-customize-the-editor.md | 5 +- package-lock.json | 4 +- package.json | 2 + 16 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 .storybook/addons/generateDocs.ts diff --git a/.gitignore b/.gitignore index 9b8f9f9f..a5548247 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ build/ coverage/ storybook-static/ .eslintcache +demo/docs diff --git a/.storybook/addons/generateDocs.ts b/.storybook/addons/generateDocs.ts new file mode 100644 index 00000000..7623d7fd --- /dev/null +++ b/.storybook/addons/generateDocs.ts @@ -0,0 +1,106 @@ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +const inputDir = path.join(__dirname, '../../docs'); +const outputDir = path.join(__dirname, '../../demo/docs'); + +/** + * Converts a kebab-case string to camelCase + */ +const kebabToCamelCase = (str: string): string => { + return str.replace(/-./g, (match) => match.charAt(1).toUpperCase()); +}; + +/** + * Generates the content for the MDX file + */ +const getContent = (title: string, updatedContent: string): string => ` +{/* +This file is auto-generated. Any changes made to this file will be overwritten +*/} + +import { Meta, Markdown } from '@storybook/blocks'; + + + +{${JSON.stringify(updatedContent)}} +`; + +/** + * Writes the MDX file to the specified path + */ +const generateMdxFile = async ( + _: string, + outputFilePath: string, + title: string, + updatedContent: string, +): Promise => { + const content = getContent(title, updatedContent); + await fs.writeFile(outputFilePath, content, 'utf8'); + console.log(`Generated: ${outputFilePath}`); +}; + +const TITLE_MATCH = /^#####\s+(.*)$/m; + +/** + * Clears the output directory + */ +const clearOutputDir = async (): Promise => { + try { + await fs.rm(outputDir, {recursive: true, force: true}); + console.log(`Cleared directory: ${outputDir}`); + } catch (error) { + console.error(`Failed to clear directory: ${outputDir}`, error); + throw error; + } +}; + +/** + * Generate MDX files from Markdown + */ +const generateDocs = async (): Promise => { + console.log('Running docs:generate...'); + try { + await clearOutputDir(); + await fs.mkdir(outputDir, {recursive: true}); + + const files = await fs.readdir(inputDir); + + for (const file of files) { + if (path.extname(file) === '.md') { + const inputFilePath = path.join(inputDir, file); + const content = await fs.readFile(inputFilePath, 'utf8'); + + const titleMatch = content.match(TITLE_MATCH); + if (!titleMatch) { + console.warn(`No title found in ${file}, skipping.`); + continue; + } + + const title = titleMatch[1].trim(); + const baseName = kebabToCamelCase(file.replace(/\.md$/, '')); + const outputFilePath = path.join(outputDir, `${baseName}.mdx`); + + await generateMdxFile(inputFilePath, outputFilePath, title, content); + } + } + } catch (error) { + console.error('Error generating docs:', error); + throw error; + } +}; + +/** + * Custom storybook addon for generate docs + */ +export default { + name: 'generate-docs', + async managerEntries(entries: string[] = []): Promise { + try { + await generateDocs(); + } catch (error) { + console.error('Error running docs:generate:', error); + } + return entries; + }, +}; diff --git a/.storybook/main.ts b/.storybook/main.ts index e70db002..8226d339 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,6 +1,5 @@ import webpack from 'webpack'; import type {StorybookConfig} from '@storybook/react-webpack5'; - import pkg from '../package.json'; const config: StorybookConfig = { @@ -8,22 +7,25 @@ const config: StorybookConfig = { name: '@storybook/react-webpack5', options: {}, }, - stories: ['../demo/**/*.stories.@(js|jsx|ts|tsx)'], + stories: ['../demo/**/*.mdx', '../demo/**/*.stories.@(js|jsx|ts|tsx)'], addons: [ + './addons/generateDocs', '@storybook/preset-scss', {name: '@storybook/addon-essentials', options: {backgrounds: false}}, '@storybook/addon-webpack5-compiler-babel', + '@storybook/addon-docs', ], typescript: { check: true, - reactDocgen: 'react-docgen-typescript' + reactDocgen: 'react-docgen-typescript', }, - webpackFinal(config) { + webpackFinal: (config) => { config.plugins?.push( new webpack.DefinePlugin({ __VERSION__: `'${pkg.version}-storybook'`, }), ); + return config; }, }; diff --git a/.storybook/preview.ts b/.storybook/preview.ts index c6e20086..1160194d 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -12,7 +12,7 @@ const preview: Preview = { }, options: { storySort: { - order: ['Markdown Editor', ['Playground', 'Presets', '*'], '*'], + order: ['Docs', 'Markdown Editor', ['Playground', 'Presets', '*'], '*'], }, }, controls: { diff --git a/docs/how-to-add-editor-with-create-react-app.md b/docs/how-to-add-editor-with-create-react-app.md index 74a80269..104bfa90 100644 --- a/docs/how-to-add-editor-with-create-react-app.md +++ b/docs/how-to-add-editor-with-create-react-app.md @@ -1,3 +1,5 @@ +##### Install / Create react app + ## Installation Guide ### 1. Setting Up the Environment for the React Application diff --git a/docs/how-to-add-editor-with-nextjs.md b/docs/how-to-add-editor-with-nextjs.md index df6b4c86..31741db4 100644 --- a/docs/how-to-add-editor-with-nextjs.md +++ b/docs/how-to-add-editor-with-nextjs.md @@ -1,5 +1,7 @@ +##### Install / NextJS + ## Connection and Configuration -This document provides instructions for configuring Webpack and Turbopack to avoid issues related to the 'fs' module and for connecting the editor on the nextjs client side. +This document provides instructions for configuring Webpack and Turbopack to avoid issues related to the 'fs' module and for connecting the editor on the nextjs client side. ### Issue with 'fs' Module Not Found In order for the `diplodoc/transform` process to function correctly, please add the [webpack resolve-fallbacks](https://webpack.js.org/configuration/resolve/#resolvefallback). diff --git a/docs/how-to-add-preview.md b/docs/how-to-add-preview.md index 800f6640..42c94788 100644 --- a/docs/how-to-add-preview.md +++ b/docs/how-to-add-preview.md @@ -1,3 +1,5 @@ +##### Develop / Preview + ## How to Add Preview for Markup Mode ### Add a Preview component diff --git a/docs/how-to-add-text-binding-extension-in-markdown.md b/docs/how-to-add-text-binding-extension-in-markdown.md index de6b70ea..6d998fb0 100644 --- a/docs/how-to-add-text-binding-extension-in-markdown.md +++ b/docs/how-to-add-text-binding-extension-in-markdown.md @@ -1,6 +1,8 @@ +##### Develop / Extension with popup + ## How to create an extension with popup for Markdown mode with text binding -Let's consider connecting an extension with text binding based on the Ghost extension — this is a test extension. +Let's consider connecting an extension with text binding based on the Ghost extension — this is a test extension. To begin with, we need the plugin itself, which we can implement as follows: @@ -49,7 +51,7 @@ class SpanWidget extends WidgetType { export const GhostPopupPlugin = ViewPlugin.fromClass( class implements PluginValue { // The class allows you to implement the following methods: update, docViewUpdate, destroy. - + decos: DecorationSet = Decoration.none; readonly _view: EditorView; readonly _renderItem; @@ -63,7 +65,7 @@ export const GhostPopupPlugin = ViewPlugin.fromClass( .createItem('ghost-popup-example-in-markup-mode', () => this.renderPopup()); } - + // Called when transactions want to be applied to the view update(update: ViewUpdate) { if (update.docChanged || update.selectionSet) { @@ -140,6 +142,7 @@ export const GhostPopupPlugin = ViewPlugin.fromClass( Let's create a popup that will be linked to the text. This is a simple component that takes a link and renders a popup in its place + ```ts // popup.ts import React from 'react'; @@ -244,4 +247,4 @@ return + + - + ### 1. Add extension usage and extensions props @@ -55,7 +58,7 @@ export const Editor: React.FC = (props) => { editor={mdEditor} markupToolbarConfig={mToolbarConfig} /> -}; +}; ``` ### 2. Implementation ```gptWidgetProps``` @@ -139,7 +142,7 @@ export const gptWidgetProps: GptWidgetOptions = { }, onLike: async () => {}, // function to track feedback for good onDislike: async () => {}, // and bad GPT answers -}; +}; ``` ### 3. Add extension to menubar and toolbar and command menu config for editor diff --git a/docs/how-to-connect-html-extension.md b/docs/how-to-connect-html-extension.md index 24c2be6e..fde3961d 100644 --- a/docs/how-to-connect-html-extension.md +++ b/docs/how-to-connect-html-extension.md @@ -1,4 +1,6 @@ -## How to Connect the HTML Extensions in the Editor +##### Connect / Html block + +## How to Connect the HTML Extension in the Editor To integrate the HTML extensions in your editor, you will use the specified versions of the necessary packages. Here’s a detailed guide: diff --git a/docs/how-to-connect-latex-extension.md b/docs/how-to-connect-latex-extension.md index cb9033ef..39558aa0 100644 --- a/docs/how-to-connect-latex-extension.md +++ b/docs/how-to-connect-latex-extension.md @@ -1,4 +1,6 @@ -## How to Connect the Latex Extensions in the Editor +##### Connect / Latex extension + +## How to Connect the Latex Extension in the Editor To integrate the LaTeX extension in your editor, you will use the specified versions of the necessary packages. Here’s a detailed guide: diff --git a/docs/how-to-connect-mermaid-extension.md b/docs/how-to-connect-mermaid-extension.md index dcf5e1d4..c3190054 100644 --- a/docs/how-to-connect-mermaid-extension.md +++ b/docs/how-to-connect-mermaid-extension.md @@ -1,4 +1,6 @@ -## How to Connect the Mermaid Extensions in the Editor +##### Connect / Mermaid Extension + +## How to Connect the Mermaid Extension in the Editor To integrate the Mermaid extension in your editor, you will use the specified versions of the necessary packages. Here’s a detailed guide. diff --git a/docs/how-to-create-extension.md b/docs/how-to-create-extension.md index 376a84b0..f29b587d 100644 --- a/docs/how-to-create-extension.md +++ b/docs/how-to-create-extension.md @@ -1,3 +1,5 @@ +##### Develop / Extension creation + ## How to Create Extension Let us examine the process of creating an extension based on the Mermaid extension, which enables the insertion and manipulation of Mermaid diagrams. diff --git a/docs/how-to-customize-the-editor.md b/docs/how-to-customize-the-editor.md index da9edc42..ce8dbc40 100644 --- a/docs/how-to-customize-the-editor.md +++ b/docs/how-to-customize-the-editor.md @@ -1,9 +1,12 @@ +##### Develop / Editor customization + ## How to customize the editor You can use CSS variables to make editor contents fit your own needs + | **Variable** | **Description** | **CSS Property Type** | **Default** | | :---: | :---: | :---: | :---: | | `--g-md-toolbar-padding` | Toolbar padding | padding | 0px | | `--g-md-toolbar-sticky-padding` | Toolbar padding in sticky mode | padding | -4px | | `--g-md-toolbar-sticky-inset` | Toolbar inset in sticky mode | inset | -4px | | `--g-md-toolbar-sticky-offset` | Toolbar offset in sticky mode | top | 0px | -| `--g-md-editor-padding` | Editor contents padding | padding | 0px | \ No newline at end of file +| `--g-md-editor-padding` | Editor contents padding | padding | 0px | diff --git a/package-lock.json b/package-lock.json index 10971971..374d4b2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,8 +65,10 @@ "@gravity-ui/stylelint-config": "4.0.1", "@gravity-ui/tsconfig": "1.0.0", "@gravity-ui/uikit": "6.11.0", + "@storybook/addon-docs": "8.4.1", "@storybook/addon-essentials": "^8.4.1", "@storybook/addon-webpack5-compiler-babel": "3.0.3", + "@storybook/blocks": "8.4.1", "@storybook/cli": "^8.4.1", "@storybook/preset-scss": "1.0.3", "@storybook/react": "8.4.1", @@ -4628,7 +4630,6 @@ "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.4.1.tgz", "integrity": "sha512-yPD/NssJf7pMJzaKvma02C6yX8ykPVnEjhRbNYcBNM8s8g/cT5JkROvIB+FOb4T81yhdfbGg9bGkpAXGX270IQ==", "dev": true, - "license": "MIT", "dependencies": { "@mdx-js/react": "^3.0.0", "@storybook/blocks": "8.4.1", @@ -4775,7 +4776,6 @@ "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.4.1.tgz", "integrity": "sha512-C4w5T5fhg0iONXozHQ1bh9im2Lr1BiY7Bj/9XoFjkc5YeCzxlMpujFA6Nmo4ToUFW90QbvKN7/QVhbrtY9O1Jg==", "dev": true, - "license": "MIT", "dependencies": { "@storybook/csf": "^0.1.11", "@storybook/icons": "^1.2.12", diff --git a/package.json b/package.json index 5b7d9daa..a58d01c2 100644 --- a/package.json +++ b/package.json @@ -213,8 +213,10 @@ "@gravity-ui/stylelint-config": "4.0.1", "@gravity-ui/tsconfig": "1.0.0", "@gravity-ui/uikit": "6.11.0", + "@storybook/addon-docs": "8.4.1", "@storybook/addon-essentials": "^8.4.1", "@storybook/addon-webpack5-compiler-babel": "3.0.3", + "@storybook/blocks": "8.4.1", "@storybook/cli": "^8.4.1", "@storybook/preset-scss": "1.0.3", "@storybook/react": "8.4.1",