Skip to content

Commit 90b71b7

Browse files
authored
🪟 🎉 Support docusaurus admonitions in markdown docs (#15519)
* Support docusaurus admonitions in markdown docs * Narrow down docs folders in vscod workspace * Add mdast and remark-directive dependencies * Add remark-directive to Markdown component plugins * Add admonitions plugin to support docusaurus admonitions * Add styles for admonitions in markdown files * Add storybook component for Markdown and fix issues with code blocks * Rename Markdown component styles files, improve code blocks style and lower heading font sizes * Update admonitions tag to div * Update DocumentationPanel to lazy load * Add @types/unist to package.json
1 parent da5b837 commit 90b71b7

File tree

10 files changed

+1027
-145
lines changed

10 files changed

+1027
-145
lines changed

.vscode/frontend.code-workspace

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77
"path": "../airbyte-webapp-e2e-tests"
88
},
99
{
10-
"path": "../docs"
10+
"name": "docs/integrations/destinations",
11+
"path": "../docs/integrations/destinations"
12+
},
13+
{
14+
"name": "docs/integrations/sources",
15+
"path": "../docs/integrations/sources"
1116
}
1217
],
1318
"extensions": {

airbyte-webapp/package-lock.json

Lines changed: 748 additions & 52 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

airbyte-webapp/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"framer-motion": "^6.3.11",
4141
"launchdarkly-js-client-sdk": "^2.22.1",
4242
"lodash": "^4.17.21",
43+
"mdast": "^3.0.0",
4344
"query-string": "^6.13.1",
4445
"react": "^17.0.2",
4546
"react-dom": "^17.0.2",
@@ -59,13 +60,15 @@
5960
"recharts": "^2.1.10",
6061
"rehype-slug": "^5.0.1",
6162
"rehype-urls": "^1.1.1",
63+
"remark-directive": "^2.0.1",
6264
"remark-frontmatter": "^4.0.1",
6365
"remark-gfm": "^3.0.0",
6466
"rxjs": "^7.5.5",
6567
"sanitize-html": "^2.7.0",
6668
"sass": "^1.52.2",
6769
"styled-components": "^5.3.5",
6870
"typesafe-actions": "^5.1.0",
71+
"unist-util-visit": "^4.1.0",
6972
"yup": "^0.32.11"
7073
},
7174
"devDependencies": {
@@ -95,6 +98,7 @@
9598
"@types/react-widgets": "^4.4.7",
9699
"@types/sanitize-html": "^2.6.2",
97100
"@types/styled-components": "^5.1.25",
101+
"@types/unist": "^2.0.5",
98102
"@typescript-eslint/eslint-plugin": "^5.27.1",
99103
"@typescript-eslint/parser": "^5.27.1",
100104
"eslint-config-prettier": "^8.5.0",
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
@use "../../scss/colors";
2+
3+
.airbyte-markdown {
4+
* {
5+
color: colors.$dark-blue;
6+
line-height: 24px;
7+
font-size: 16px;
8+
font-weight: 400;
9+
}
10+
11+
h1 {
12+
font-size: 32px;
13+
line-height: 56px;
14+
font-weight: bold;
15+
}
16+
17+
h2 {
18+
font-size: 22px;
19+
line-height: 36px;
20+
font-weight: bold;
21+
}
22+
23+
h3 {
24+
font-size: 18px;
25+
font-weight: bold;
26+
}
27+
28+
h4 {
29+
font-weight: bold;
30+
}
31+
32+
a {
33+
color: colors.$blue;
34+
text-decoration: none;
35+
line-height: 24px;
36+
37+
&:hover {
38+
text-decoration: underline;
39+
}
40+
}
41+
42+
table {
43+
border-collapse: collapse;
44+
}
45+
46+
th,
47+
td {
48+
border: 1px solid colors.$grey-100;
49+
margin: 0;
50+
padding: 8px 16px;
51+
}
52+
53+
th {
54+
background: colors.$grey-50;
55+
}
56+
57+
blockquote {
58+
border-left: 4px solid colors.$grey-100;
59+
padding-left: 16px;
60+
margin-left: 25px;
61+
}
62+
63+
strong {
64+
font-weight: bold;
65+
}
66+
67+
code {
68+
white-space: break-spaces;
69+
background: colors.$grey-50;
70+
font-family: Menlo, Monaco, Consolas, monospace;
71+
}
72+
73+
pre > code {
74+
display: block;
75+
padding: 15px;
76+
overflow: auto;
77+
border-radius: 8px;
78+
border-bottom: 2px solid colors.$grey-100;
79+
}
80+
81+
img {
82+
max-width: 100%;
83+
}
84+
85+
.admonition {
86+
border-radius: 8px;
87+
border-left: 8px solid colors.$grey-300;
88+
padding: 1px 16px 1px 48px;
89+
margin: -1px 0 15px;
90+
background-color: colors.$grey-50;
91+
position: relative;
92+
93+
&::before {
94+
content: "ℹ️";
95+
position: absolute;
96+
top: 16px;
97+
left: 16px;
98+
}
99+
100+
&--caution,
101+
&--warning {
102+
background-color: colors.$yellow-50;
103+
border-left-color: colors.$yellow-300;
104+
&::before {
105+
content: "⚠️";
106+
}
107+
}
108+
109+
&--danger {
110+
background-color: colors.$red-50;
111+
border-left-color: colors.$red-300;
112+
&::before {
113+
content: "⚠️";
114+
}
115+
}
116+
117+
&--note::before {
118+
content: "📝";
119+
}
120+
121+
&--tip,
122+
&--info {
123+
background-color: colors.$blue-50;
124+
border-left-color: colors.$blue-300;
125+
}
126+
127+
&--tip::before {
128+
content: "💡";
129+
}
130+
}
131+
}

airbyte-webapp/src/components/Markdown/Markdown.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,21 @@ import type { PluggableList } from "react-markdown/lib/react-markdown";
33
import classNames from "classnames";
44
import React from "react";
55
import ReactMarkdown from "react-markdown";
6+
import remarkDirective from "remark-directive";
67
import remarkFrontmatter from "remark-frontmatter";
78
import remarkGfm from "remark-gfm";
89

9-
import "./styles.scss";
10+
import { remarkAdmonitionsPlugin } from "./remarkAdmonitionsPlugin";
1011

11-
interface Props {
12+
import "./Markdown.styles.scss";
13+
14+
interface MarkdownProps {
1215
content?: string;
1316
className?: string;
1417
rehypePlugins?: PluggableList;
1518
}
1619

17-
export const Markdown: React.FC<Props> = ({ content, className, rehypePlugins }) => {
20+
export const Markdown: React.VFC<MarkdownProps> = ({ content, className, rehypePlugins }) => {
1821
return (
1922
<ReactMarkdown
2023
// Open everything except fragment only links in a new tab
@@ -23,7 +26,7 @@ export const Markdown: React.FC<Props> = ({ content, className, rehypePlugins })
2326
skipHtml
2427
// @ts-expect-error remarkFrontmatter currently has type conflicts due to duplicate vfile dependencies
2528
// This is not actually causing any issues, but requires to disable TS on this for now.
26-
remarkPlugins={[remarkFrontmatter, remarkGfm]}
29+
remarkPlugins={[remarkDirective, remarkAdmonitionsPlugin, remarkFrontmatter, remarkGfm]}
2730
rehypePlugins={rehypePlugins}
2831
children={content || ""}
2932
/>
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { ComponentStory, ComponentMeta } from "@storybook/react";
2+
3+
import { Markdown } from "./Markdown";
4+
5+
export default {
6+
title: "Ui/Markdown",
7+
component: Markdown,
8+
argTypes: {},
9+
} as ComponentMeta<typeof Markdown>;
10+
11+
const Template: ComponentStory<typeof Markdown> = (args) => (
12+
<div style={{ backgroundColor: "white" }}>
13+
<Markdown {...args} />
14+
</div>
15+
);
16+
17+
const content = `
18+
# Heading 1
19+
## Heading 2
20+
### Heading 3
21+
#### Heading 4
22+
##### Heading 5
23+
###### Heading 6
24+
25+
The quick brown fox jumps over the lazy dog.
26+
27+
The quick brown fox jumps over the lazy dog.
28+
29+
> The quick brown fox jumps over the lazy dog.
30+
31+
[Link](https://www.airbyte.com/)
32+
33+
\`Pre\`
34+
35+
*italic*
36+
37+
**bold**
38+
39+
~strikethrough~
40+
41+
42+
\`\`\`javascript
43+
function codeBlock() {
44+
// comment
45+
}
46+
\`\`\`
47+
48+
| Heading 1 | Heading 2 |
49+
|:----------|:----------|
50+
|Cell 1 | Cell 2 |
51+
|Cell 3 | Cell 4 |
52+
53+
- List item 1
54+
- List item 2
55+
- List item 3
56+
57+
1. List item 1
58+
2. List item 2
59+
3. List item 3
60+
61+
* List item 1
62+
* List item 2
63+
* List item 3
64+
65+
:::note
66+
This is a note admonition
67+
:::
68+
69+
:::tip
70+
This is a tip admonition
71+
:::
72+
73+
:::info
74+
This is a info admonition
75+
:::
76+
77+
:::caution
78+
This is a caution admonition
79+
:::
80+
81+
:::warning
82+
This is a warning admonition
83+
:::
84+
85+
:::danger
86+
This is a danger admonition
87+
:::
88+
89+
`;
90+
91+
export const Primary = Template.bind({});
92+
Primary.args = {
93+
content,
94+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Root } from "mdast";
2+
import { Plugin } from "unified";
3+
import { Node } from "unist";
4+
import { visit } from "unist-util-visit";
5+
6+
const SUPPORTED_ADMONITION_NAMES: Readonly<string[]> = ["note", "tip", "info", "caution", "warning", "danger"];
7+
const SUPPORTED_NODE_TYPES: Readonly<string[]> = ["textDirective", "leafDirective", "containerDirective"];
8+
9+
export const remarkAdmonitionsPlugin: Plugin<[], Root> = () => (tree) => {
10+
visit<Node & { name?: string }>(tree, (node) => {
11+
if (!node.name || !SUPPORTED_ADMONITION_NAMES.includes(node.name) || !SUPPORTED_NODE_TYPES.includes(node.type)) {
12+
return;
13+
}
14+
15+
const data = node.data ?? (node.data = {});
16+
const className = `admonition admonition--${node.name}`;
17+
18+
data.hName = "div";
19+
data.hProperties = { class: className };
20+
});
21+
};

0 commit comments

Comments
 (0)