Skip to content

Commit b8f9885

Browse files
committed
feat: add MarkdownViewer component and cnYFM helper
1 parent ba23367 commit b8f9885

18 files changed

Lines changed: 335 additions & 2 deletions

File tree

.github/workflows/publish.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ on:
1616
- 'packages/editor'
1717
- 'packages/latex-extension'
1818
- 'packages/page-constructor-extension'
19+
- 'packages/viewer'
1920
tag:
2021
description: 'Publish with tag'
2122
required: true

.release-please/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"packages": {
1515
"packages/editor": {},
1616
"packages/latex-extension": {},
17-
"packages/page-constructor-extension": {}
17+
"packages/page-constructor-extension": {},
18+
"packages/viewer": {}
1819
}
1920
}

.release-please/manifest.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"packages/editor": "15.40.0",
33
"packages/latex-extension": "0.1.0",
4-
"packages/page-constructor-extension": "0.1.0"
4+
"packages/page-constructor-extension": "0.1.0",
5+
"packages/viewer": "0.0.0"
56
}

demo/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"@gravity-ui/markdown-editor": "workspace:*",
3535
"@gravity-ui/markdown-editor-latex-extension": "workspace:*",
3636
"@gravity-ui/markdown-editor-page-constructor-extension": "workspace:*",
37+
"@gravity-ui/markdown-viewer": "workspace:*",
3738
"@gravity-ui/page-constructor": "catalog:peer-gravity",
3839
"@gravity-ui/uikit": "catalog:peer-gravity",
3940
"markdown-it": "catalog:peers"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type {StoryObj} from '@storybook/react';
2+
3+
import {markup} from '../../defaults/content';
4+
5+
import {Viewer} from './MarkdownViewer';
6+
7+
export const Story: StoryObj<typeof Viewer> = {
8+
args: {
9+
markdown: markup,
10+
},
11+
};
12+
Story.storyName = 'Markdown Viewer';
13+
14+
export default {
15+
title: 'Viewer / Markdown Viewer',
16+
component: Viewer,
17+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {useEffect, useState} from 'react';
2+
3+
import transform from '@diplodoc/transform';
4+
import {MarkdownViewer, cnYFM} from '@gravity-ui/markdown-viewer';
5+
6+
export type ViewerProps = {
7+
markdown: string;
8+
};
9+
10+
export const Viewer: React.FC<ViewerProps> = ({markdown}) => {
11+
const [html, setHtml] = useState('');
12+
13+
useEffect(() => {
14+
setHtml(transform(markdown).result.html);
15+
}, [markdown]);
16+
17+
return (
18+
<MarkdownViewer
19+
html={html}
20+
className={cnYFM({
21+
'no-list-reset': true,
22+
'no-stripe-table': true,
23+
})}
24+
qa="demo-markdown-viewer"
25+
role="presentation"
26+
/>
27+
);
28+
};

packages/viewer/.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build

packages/viewer/README.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# @gravity-ui/markdown-viewer &middot; [![npm package](https://img.shields.io/npm/v/@gravity-ui/markdown-viewer)](https://www.npmjs.com/package/@gravity-ui/markdown-viewer)
2+
3+
Markdown viewer component for [@gravity-ui/markdown-editor](https://github.com/gravity-ui/markdown-editor). Renders pre-transformed HTML from `@diplodoc/transform` with support for YFM (Yandex Flavored Markdown) styles and runtime extensions.
4+
5+
## Installation
6+
7+
```bash
8+
npm install @gravity-ui/markdown-viewer
9+
```
10+
11+
### Required peer dependencies
12+
13+
```bash
14+
npm install @gravity-ui/uikit react react-dom
15+
```
16+
17+
## Usage
18+
19+
### Basic rendering
20+
21+
```tsx
22+
import {MarkdownViewer} from '@gravity-ui/markdown-viewer';
23+
24+
export function Preview({html}: {html: string}) {
25+
return <MarkdownViewer html={html} />;
26+
}
27+
```
28+
29+
### With YFM styles
30+
31+
To apply YFM styles, pass the `cnYFM()` class to the `className` prop. Import the stylesheets manually:
32+
33+
```tsx
34+
import {MarkdownViewer, cnYFM} from '@gravity-ui/markdown-viewer';
35+
36+
import '@diplodoc/transform/dist/yfm.css';
37+
38+
export function Preview({html}: {html: string}) {
39+
return <MarkdownViewer html={html} className={cnYFM()} />;
40+
}
41+
```
42+
43+
### With YFM modifiers
44+
45+
`cnYFM()` accepts optional modifier flags:
46+
47+
```tsx
48+
<MarkdownViewer html={html} className={cnYFM({'no-list-reset': true, 'no-stripe-table': true})} />
49+
```
50+
51+
Available modifiers:
52+
53+
| Modifier | Description |
54+
|---|---|
55+
| `no-list-reset` | Disable list counter reset |
56+
| `no-stripe-table` | Disable striped table rows |
57+
58+
## API
59+
60+
### `MarkdownViewer`
61+
62+
| Prop | Type | Description |
63+
|---|---|---|
64+
| `html` | `string` | Pre-transformed HTML string to render. The component does not sanitize it — make sure to sanitize before passing. |
65+
| `className` | `string` | CSS class applied to the inner content element |
66+
| `style` | `CSSProperties` | Inline styles applied to the inner content element |
67+
| `ref` | `Ref<HTMLDivElement>` | Ref forwarded to the inner content element |
68+
| `children` | `ReactNode` | Additional nodes rendered alongside the content (e.g. runtime extension portals) |
69+
| `...props` | `HTMLAttributes<HTMLDivElement>` | Any other props are forwarded to the inner content `div` |
70+
71+
### `cnYFM(mods?, mix?)`
72+
73+
BEM class name helper for the `.yfm` scope. Use it to enable YFM styles and modifiers on the viewer.
74+
75+
```ts
76+
import {cnYFM, type YFMMods} from '@gravity-ui/markdown-viewer';
77+
78+
cnYFM() // => 'yfm'
79+
cnYFM({'no-list-reset': true}) // => 'yfm yfm_no-list-reset'
80+
```
81+
82+
## License
83+
84+
MIT

packages/viewer/gulpfile.mjs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {dirname, resolve} from 'node:path';
2+
import {fileURLToPath} from 'node:url';
3+
4+
import {series, task} from '@markdown-editor/gulp-tasks';
5+
import {registerBuildTasks} from '@markdown-editor/gulp-tasks/build';
6+
7+
import pkg from './package.json' with {type: 'json'};
8+
9+
const __dirname = dirname(fileURLToPath(import.meta.url));
10+
11+
const BUILD_DIR = resolve('build');
12+
const NODE_MODULES_DIR = resolve(__dirname, 'node_modules');
13+
14+
registerBuildTasks({
15+
version: pkg.version,
16+
buildDir: BUILD_DIR,
17+
nodeModulesDir: NODE_MODULES_DIR,
18+
});
19+
20+
task('default', series('clean', 'build'));

packages/viewer/package.json

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
{
2+
"name": "@gravity-ui/markdown-viewer",
3+
"version": "0.0.0",
4+
"description": "Viewer for markdown content from @gravity-ui/markdown-editor",
5+
"license": "MIT",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/gravity-ui/markdown-editor"
9+
},
10+
"keywords": [
11+
"md",
12+
"yfm",
13+
"markdown"
14+
],
15+
"scripts": {
16+
"clean": "gulp clean",
17+
"build": "gulp build",
18+
"typecheck": "tsc -p tsconfig.json --noEmit",
19+
"lint": "run-p -cs lint:*",
20+
"lint:js": "eslint './**/*.{js,jsx,mjs,ts,tsx}'",
21+
"lint:styles": "stylelint './**/*.{css,scss}' --allow-empty-input",
22+
"lint:prettier": "prettier --check './**/*.{js,jsx,mjs,ts,tsx,css,scss}'",
23+
"test": "exit 0",
24+
"prepublishOnly": "nx lint && nx clean && nx build"
25+
},
26+
"exports": {
27+
".": {
28+
"import": {
29+
"types": "./build/esm/index.d.ts",
30+
"default": "./build/esm/index.js"
31+
},
32+
"require": {
33+
"types": "./build/cjs/index.d.ts",
34+
"default": "./build/cjs/index.js"
35+
}
36+
}
37+
},
38+
"main": "build/cjs/index.js",
39+
"module": "build/esm/index.js",
40+
"types": "build/esm/index.d.ts",
41+
"files": [
42+
"build",
43+
"README.md"
44+
],
45+
"dependencies": {
46+
"@bem-react/classname": "^1.6.0",
47+
"tslib": "catalog:ts"
48+
},
49+
"devDependencies": {
50+
"@gravity-ui/uikit": "catalog:peer-gravity",
51+
"@markdown-editor/gulp-tasks": "workspace:*",
52+
"@markdown-editor/linters": "workspace:*",
53+
"@markdown-editor/tsconfig": "workspace:*",
54+
"@types/react": "catalog:react",
55+
"@types/react-dom": "catalog:react",
56+
"gulp-cli": "catalog:",
57+
"npm-run-all": "^4.1.5",
58+
"react": "catalog:react",
59+
"react-dom": "catalog:react",
60+
"typescript": "catalog:ts"
61+
},
62+
"peerDependencies": {
63+
"@gravity-ui/uikit": "^7.1.0",
64+
"react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
65+
"react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
66+
},
67+
"sideEffects": [
68+
"*.css",
69+
"*.scss"
70+
]
71+
}

0 commit comments

Comments
 (0)