Skip to content

Commit 74790ff

Browse files
authored
chore(demo): integrated autogenerated docs into the demo (#490)
1 parent fbc977c commit 74790ff

16 files changed

+154
-20
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ build/
2121
coverage/
2222
storybook-static/
2323
.eslintcache
24+
demo/docs

.storybook/addons/generateDocs.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import * as fs from 'fs/promises';
2+
import * as path from 'path';
3+
4+
const inputDir = path.join(__dirname, '../../docs');
5+
const outputDir = path.join(__dirname, '../../demo/docs');
6+
7+
/**
8+
* Converts a kebab-case string to camelCase
9+
*/
10+
const kebabToCamelCase = (str: string): string => {
11+
return str.replace(/-./g, (match) => match.charAt(1).toUpperCase());
12+
};
13+
14+
/**
15+
* Generates the content for the MDX file
16+
*/
17+
const getContent = (title: string, updatedContent: string): string => `
18+
{/*
19+
This file is auto-generated. Any changes made to this file will be overwritten
20+
*/}
21+
22+
import { Meta, Markdown } from '@storybook/blocks';
23+
24+
<Meta title="Docs / ${title}" />
25+
26+
<Markdown>{${JSON.stringify(updatedContent)}}</Markdown>
27+
`;
28+
29+
/**
30+
* Writes the MDX file to the specified path
31+
*/
32+
const generateMdxFile = async (
33+
_: string,
34+
outputFilePath: string,
35+
title: string,
36+
updatedContent: string,
37+
): Promise<void> => {
38+
const content = getContent(title, updatedContent);
39+
await fs.writeFile(outputFilePath, content, 'utf8');
40+
console.log(`Generated: ${outputFilePath}`);
41+
};
42+
43+
const TITLE_MATCH = /^#####\s+(.*)$/m;
44+
45+
/**
46+
* Clears the output directory
47+
*/
48+
const clearOutputDir = async (): Promise<void> => {
49+
try {
50+
await fs.rm(outputDir, {recursive: true, force: true});
51+
console.log(`Cleared directory: ${outputDir}`);
52+
} catch (error) {
53+
console.error(`Failed to clear directory: ${outputDir}`, error);
54+
throw error;
55+
}
56+
};
57+
58+
/**
59+
* Generate MDX files from Markdown
60+
*/
61+
const generateDocs = async (): Promise<void> => {
62+
console.log('Running docs:generate...');
63+
try {
64+
await clearOutputDir();
65+
await fs.mkdir(outputDir, {recursive: true});
66+
67+
const files = await fs.readdir(inputDir);
68+
69+
for (const file of files) {
70+
if (path.extname(file) === '.md') {
71+
const inputFilePath = path.join(inputDir, file);
72+
const content = await fs.readFile(inputFilePath, 'utf8');
73+
74+
const titleMatch = content.match(TITLE_MATCH);
75+
if (!titleMatch) {
76+
console.warn(`No title found in ${file}, skipping.`);
77+
continue;
78+
}
79+
80+
const title = titleMatch[1].trim();
81+
const baseName = kebabToCamelCase(file.replace(/\.md$/, ''));
82+
const outputFilePath = path.join(outputDir, `${baseName}.mdx`);
83+
84+
await generateMdxFile(inputFilePath, outputFilePath, title, content);
85+
}
86+
}
87+
} catch (error) {
88+
console.error('Error generating docs:', error);
89+
throw error;
90+
}
91+
};
92+
93+
/**
94+
* Custom storybook addon for generate docs
95+
*/
96+
export default {
97+
name: 'generate-docs',
98+
async managerEntries(entries: string[] = []): Promise<string[]> {
99+
try {
100+
await generateDocs();
101+
} catch (error) {
102+
console.error('Error running docs:generate:', error);
103+
}
104+
return entries;
105+
},
106+
};

.storybook/main.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,31 @@
11
import webpack from 'webpack';
22
import type {StorybookConfig} from '@storybook/react-webpack5';
3-
43
import pkg from '../package.json';
54

65
const config: StorybookConfig = {
76
framework: {
87
name: '@storybook/react-webpack5',
98
options: {},
109
},
11-
stories: ['../demo/**/*.stories.@(js|jsx|ts|tsx)'],
10+
stories: ['../demo/**/*.mdx', '../demo/**/*.stories.@(js|jsx|ts|tsx)'],
1211
addons: [
12+
'./addons/generateDocs',
1313
'@storybook/preset-scss',
1414
{name: '@storybook/addon-essentials', options: {backgrounds: false}},
1515
'@storybook/addon-webpack5-compiler-babel',
16+
'@storybook/addon-docs',
1617
],
1718
typescript: {
1819
check: true,
19-
reactDocgen: 'react-docgen-typescript'
20+
reactDocgen: 'react-docgen-typescript',
2021
},
21-
webpackFinal(config) {
22+
webpackFinal: (config) => {
2223
config.plugins?.push(
2324
new webpack.DefinePlugin({
2425
__VERSION__: `'${pkg.version}-storybook'`,
2526
}),
2627
);
28+
2729
return config;
2830
},
2931
};

.storybook/preview.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const preview: Preview = {
1212
},
1313
options: {
1414
storySort: {
15-
order: ['Markdown Editor', ['Playground', 'Presets', '*'], '*'],
15+
order: ['Docs', 'Markdown Editor', ['Playground', 'Presets', '*'], '*'],
1616
},
1717
},
1818
controls: {

docs/how-to-add-editor-with-create-react-app.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
##### Install / Create react app
2+
13
## Installation Guide
24

35
### 1. Setting Up the Environment for the React Application

docs/how-to-add-editor-with-nextjs.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
##### Install / NextJS
2+
13
## Connection and Configuration
2-
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.
4+
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.
35

46
### Issue with 'fs' Module Not Found
57
In order for the `diplodoc/transform` process to function correctly, please add the [webpack resolve-fallbacks](https://webpack.js.org/configuration/resolve/#resolvefallback).

docs/how-to-add-preview.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
##### Develop / Preview
2+
13
## How to Add Preview for Markup Mode
24

35
### Add a Preview component

docs/how-to-add-text-binding-extension-in-markdown.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
##### Develop / Extension with popup
2+
13
## How to create an extension with popup for Markdown mode with text binding
24

3-
Let's consider connecting an extension with text binding based on the Ghost extension — this is a test extension.
5+
Let's consider connecting an extension with text binding based on the Ghost extension — this is a test extension.
46

57
To begin with, we need the plugin itself, which we can implement as follows:
68

@@ -49,7 +51,7 @@ class SpanWidget extends WidgetType {
4951
export const GhostPopupPlugin = ViewPlugin.fromClass(
5052
class implements PluginValue {
5153
// The class allows you to implement the following methods: update, docViewUpdate, destroy.
52-
54+
5355
decos: DecorationSet = Decoration.none;
5456
readonly _view: EditorView;
5557
readonly _renderItem;
@@ -63,7 +65,7 @@ export const GhostPopupPlugin = ViewPlugin.fromClass(
6365
.createItem('ghost-popup-example-in-markup-mode', () => this.renderPopup());
6466
}
6567

66-
68+
6769
// Called when transactions want to be applied to the view
6870
update(update: ViewUpdate) {
6971
if (update.docChanged || update.selectionSet) {
@@ -140,6 +142,7 @@ export const GhostPopupPlugin = ViewPlugin.fromClass(
140142
Let's create a popup that will be linked to the text.
141143

142144
This is a simple component that takes a link and renders a popup in its place
145+
143146
```ts
144147
// popup.ts
145148
import React from 'react';
@@ -244,4 +247,4 @@ return <MarkdownEditorView
244247
```
245248

246249
Now you can use the plugin!
247-
You can also check out the GPT implementation or see the Ghost example on the Playground and in the code.
250+
You can also check out the GPT implementation or see the Ghost example on the Playground and in the code.

docs/how-to-connect-gpt-extensions.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
##### Connect / GPT
2+
13
## How to connect GPT extensions to editor
24

35
First to integrate this extension, you need to use the following versions of the packages:
@@ -7,9 +9,10 @@ First to integrate this extension, you need to use the following versions of the
79

810
Features:
911

10-
<img src="./assets/gifs/custom-prompt-preset-gpt.gif" width="470"/>
12+
<img src="https://raw.githubusercontent.com/gravity-ui/markdown-editor/refs/heads/main/docs/assets/gifs/custom-prompt-preset-gpt.gif" width="470"/>
13+
1114

12-
<img src="./assets/gifs/prompt-preset-gpt.gif" width="470"/>
15+
<img src="https://raw.githubusercontent.com/gravity-ui/markdown-editor/refs/heads/main/docs/assets/gifs/prompt-preset-gpt.gif" width="470"/>
1316

1417
### 1. Add extension usage and extensions props
1518

@@ -55,7 +58,7 @@ export const Editor: React.FC<EditorProps> = (props) => {
5558
editor={mdEditor}
5659
markupToolbarConfig={mToolbarConfig}
5760
/>
58-
};
61+
};
5962
```
6063
### 2. Implementation ```gptWidgetProps```
6164

@@ -139,7 +142,7 @@ export const gptWidgetProps: GptWidgetOptions = {
139142
},
140143
onLike: async () => {}, // function to track feedback for good
141144
onDislike: async () => {}, // and bad GPT answers
142-
};
145+
};
143146
```
144147
### 3. Add extension to menubar and toolbar and command menu config for editor
145148

docs/how-to-connect-html-extension.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
## How to Connect the HTML Extensions in the Editor
1+
##### Connect / Html block
2+
3+
## How to Connect the HTML Extension in the Editor
24

35
To integrate the HTML extensions in your editor, you will use the specified versions of the necessary packages. Here’s a detailed guide:
46

0 commit comments

Comments
 (0)