feat: add MarkdownContent component

This commit is contained in:
Jesko Steinberg
2020-10-29 13:14:15 +01:00
parent bf8a64c29b
commit 357f42b6a1
7 changed files with 273 additions and 1 deletions
+15
View File
@@ -0,0 +1,15 @@
---
'@backstage/core': minor
---
Adds the MarkdownContent component to render and display markdown input.
```
<MarkdownContent content={markdown} />
```
Render and display the github flavored markdown [GFM](https://github.github.com/gfm/) input:
```
<MarkdownContent content={markdownGithubFlavored} enableGfm />
```
+3 -1
View File
@@ -48,11 +48,13 @@
"react-dom": "^16.12.0",
"react-helmet": "6.1.0",
"react-hook-form": "^6.6.0",
"react-markdown": "^5.0.2",
"react-router": "6.0.0-beta.0",
"react-router-dom": "6.0.0-beta.0",
"react-sparklines": "^1.7.0",
"react-syntax-highlighter": "^13.5.1",
"react-use": "^15.3.3"
"react-use": "^15.3.3",
"remark-gfm": "^1.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.1.1-alpha.26",
@@ -0,0 +1,120 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { MarkdownContent } from './MarkdownContent';
export default {
title: 'Data Display/MarkdownContent',
component: MarkdownContent,
};
const markdownGithubFlavored =
'# GFM\n' +
'\n' +
'## Autolink literals\n' +
'\n' +
'www.example.com, https://example.com, and contact@example.com.\n' +
'\n' +
'## Strikethrough\n' +
'\n' +
'~one~ or ~~two~~ tildes.\n' +
'\n' +
'## Table\n' +
'\n' +
'| foo | bar |\n' +
'| --- | --- |\n' +
'| baz | bim |\n' +
'| buz | bum |\n' +
'| biz | bim |\n' +
'\n' +
'## Tasklist\n' +
'\n' +
'* [ ] to do\n' +
'* [x] done';
const markdown =
'# Choreas Iovis\n' +
'\n' +
'## Incedere retenta\n' +
'\n' +
'Lorem markdownum velamina [nupta amici aequoreis](http://est-quae.org/sic)\n' +
'desertum factum premunt: falcato parvos nihil. Facietque vulnus tum dumque\n' +
'reserato Maeandros insignia solidis, tot longi causa et nimium arcuerat altera\n' +
'unus, in quis.\n' +
'\n' +
'1. Est qui dixere nullus\n' +
'2. Fuit obicit\n' +
'3. Vim patrem portae materiem ulla quod crater\n' +
'4. Rigido est magis raptor quid crepitante aequa\n' +
'5. Imago quis ignis tamen\n' +
'\n' +
'## Vix posse vestem\n' +
'\n' +
'Nec deos robora visa pater toris remittit *crimina* utque, ora ego lacerae quae\n' +
'laboris laturus silvas audax terrae. Qua fuisse patrio inlaesas [sine\n' +
'seque](http://ambitvictore.org/), nondum et tamen annis, nec. Poscimur magnum,\n' +
'Hesperium dedisti, ait ipse et fides terras scalas.\n' +
'\n' +
'- Quas superis satyri adloquitur natura hausimus\n' +
'- Dux suspicere siccare\n' +
'- Cape huc quid videor\n' +
'- Foret vivit concolor\n' +
'- Occupat morte oblectamina minuunt quaeque placidis nate\n' +
'- Non posset' +
'\n' +
'Licet movitque dederat potest in sorores in sola pendere luce pro quod, sit.\n' +
'Inpia ut in opibus flores uno quam quo multifidasque fera anhelitus retorsit.\n' +
'Sustinui premebat puppe somnos. Dicit genu sic qualia excussit facunde parvae in\n' +
'robur, Ianthe Interea. Superis victorque ponat puta cum: est enim.\n' +
'\n' +
'## Tacetve est in nullis Cerberus silvani luminibus\n' +
'\n' +
'Divulsere *summissoque esse manes*; artus ausus conatoque utque: illo\n' +
'Phaestiadas quod pascat et referentem, nec. In seris, iubebat iam nomina:\n' +
'tergoque occidit ingenii.\n' +
'\n' +
' mouseDdl(tablet_definition * phishing_icann_mamp);\n' +
' vector += 20 + key_ram.source_isa(hard_tunneling_zone(w_wireless_page));\n' +
' if (rate_client_direct) {\n' +
' textXDpi += sql_cloud_class.sdk.speakers_wired_warm(pcZettabyteGis(\n' +
' market_bezel, 1), 1);\n' +
' tag_scraping = format_ppi;\n' +
' }\n' +
'\n' +
'Per quem, nec formosior qui cum Peliden me interea **ornatos**! Te facit\n' +
'instimulat sequentia in flumina exilium te vulnere, sola. Coetum nec amnes.\n' +
'Protinus nam Caras cava, *a* vocantem dicta inevitabile, nata nulla.\n' +
'\n' +
'## Piscem Iunoni maius\n' +
'\n' +
'Prece fallere arduus, *ad Athamantis laticem* simillima in ante Temesesque opus!\n' +
'Ausim quoslibet crede Tyria: Medusa [muneris Aeneaden\n' +
'tutaque](http://cragon-aequoribus.io/) genitor fistula cogeris abstrahere nati,\n' +
'relevare videri *non*.\n' +
'\n' +
'> Promissas ulterius senectae Desinet his ait pedum! Libet *sublime* vibrantia\n' +
'> si *dicta quod* pectora cupidine hastam dominoque.\n' +
'\n' +
'Pedis hic, est bis quod, adhaeret et reditum. Fixa sic vel pugnare **forte est**\n' +
'parte in quaerite generisque repugnat; de quod, creatos.';
export const MarkdownContentCommonMark = () => (
<MarkdownContent content={markdown} />
);
export const MarkdownContentGithubFlavoredCommonMark = () => (
<MarkdownContent content={markdownGithubFlavored} enableGfm />
);
@@ -0,0 +1,43 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
import { MarkdownContent } from './MarkdownContent';
describe('<MarkdownContent />', () => {
it('render MarkdownContent component with common mark', async () => {
const rendered = await renderWithEffects(
wrapInTestApp(
<MarkdownContent content={'# H1\n' + '## H2\n' + '### H3'} />,
),
);
expect(rendered.getByText('H1', { selector: 'h1' })).toBeInTheDocument();
expect(rendered.getByText('H2', { selector: 'h2' })).toBeInTheDocument();
expect(rendered.getByText('H3', { selector: 'h3' })).toBeInTheDocument();
});
it('render MarkdownContent component with common mark github flavored', async () => {
const rendered = await renderWithEffects(
wrapInTestApp(
<MarkdownContent content="https://example.com" enableGfm />,
),
);
expect(
rendered.getByText('https://example.com', { selector: 'a' }),
).toBeInTheDocument();
});
});
@@ -0,0 +1,74 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { makeStyles } from '@material-ui/core';
import ReactMarkdown from 'react-markdown';
import gfm from 'remark-gfm';
import React from 'react';
const useStyles = makeStyles(theme => ({
markdown: {
'& table': {
borderCollapse: 'collapse',
border: '1px solid #dfe2e5',
color: 'rgb(36, 41, 46)',
},
'& th, & td': {
border: '1px solid #dfe2e5',
padding: theme.spacing(1),
},
'& tr': {
backgroundColor: '#fff',
},
'& tr:nth-child(2n)': {
backgroundColor: '#f6f8fa',
},
'& pre': {
padding: '16px',
overflow: 'auto',
fontSize: '85%',
lineHeight: 1.45,
backgroundColor: '#f6f8fa',
borderRadius: '6px',
color: 'rgba(0, 0, 0, 0.87)',
},
'& a': {
color: '#2E77D0',
},
'& img': {
maxWidth: '100%',
},
},
}));
/**
* MarkdownContent. Renders markdown (CommonMark, optionally with [GFM](https://github.com/remarkjs/remark-gfm)) to formatted HTML.
*/
type Props = {
content: string;
enableGfm?: boolean;
};
export const MarkdownContent = ({ content, enableGfm = false }: Props) => {
const classes = useStyles();
return (
<ReactMarkdown
plugins={enableGfm ? [gfm] : []}
className={classes.markdown}
children={content}
/>
);
};
@@ -0,0 +1,17 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { MarkdownContent } from './MarkdownContent';
+1
View File
@@ -35,3 +35,4 @@ export * from './Tabs';
export * from './TrendLine';
export * from './WarningPanel';
export * from './EmptyState';
export * from './MarkdownContent';