Issue 660: CodeSnippet Reuseable component (#803)
* Initial CodeSnippet setup in Storybook * Add support for line numbers * Pseudo-code some basic tests and leverage useTheme hook The test suite cannot currently be run, as the react-syntax-highlighter appears to be using ESM, which are not supported by Jest out-of-the-box. This should only require a simple Babel loader to remedy, but I want to make sure first that I have not misconfigured something, as configuring Babel is likely a notable scope increase for this relatively small issue. * Fix ESM Jest issue and update tests It would be ideal to have snapshot tests to cover the lightmode vs darkmode rendering. I started experimenting with directly testing the styling, and it quickly became very sloppy. * Provide more examples in stories * Add showLineNumbers to PropType validation
This commit is contained in:
@@ -40,7 +40,8 @@
|
||||
"react-helmet": "5.2.1",
|
||||
"react-router": "^5.1.2",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-sparklines": "^1.7.0"
|
||||
"react-sparklines": "^1.7.0",
|
||||
"react-syntax-highlighter": "^12.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.1.1-alpha.4",
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 CodeSnippet from './CodeSnippet';
|
||||
|
||||
export default {
|
||||
title: 'CodeSnippet',
|
||||
component: CodeSnippet,
|
||||
};
|
||||
|
||||
const containerStyle = { width: 300 };
|
||||
|
||||
const JAVASCRIPT = `const greeting = "Hello";
|
||||
const world = "World";
|
||||
|
||||
const greet = person => greeting + " " + person + "!";
|
||||
|
||||
greet(world);
|
||||
`;
|
||||
|
||||
const TYPESCRIPT = `const greeting: string = "Hello";
|
||||
const world: string = "World";
|
||||
|
||||
const greet = (person: string): string => greeting + " " + person + "!";
|
||||
|
||||
greet(world);
|
||||
`;
|
||||
|
||||
const PYTHON = `greeting = "Hello"
|
||||
world = "World"
|
||||
|
||||
def greet(person):
|
||||
return f"{greeting} {person}!"
|
||||
|
||||
greet(world)
|
||||
`;
|
||||
|
||||
export const Default = () => (
|
||||
<CodeSnippet text={"const hello = 'World';"} language="javascript" />
|
||||
);
|
||||
|
||||
export const MultipleLines = () => (
|
||||
<CodeSnippet text={JAVASCRIPT} language="javascript" />
|
||||
);
|
||||
|
||||
export const LineNumbers = () => (
|
||||
<CodeSnippet text={JAVASCRIPT} language="javascript" showLineNumbers />
|
||||
);
|
||||
|
||||
export const Overflow = () => (
|
||||
<>
|
||||
<div style={containerStyle}>
|
||||
<CodeSnippet text={JAVASCRIPT} language="javascript" />
|
||||
</div>
|
||||
<div style={containerStyle}>
|
||||
<CodeSnippet text={JAVASCRIPT} language="javascript" showLineNumbers />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
export const Laguages = () => (
|
||||
<>
|
||||
<CodeSnippet text={JAVASCRIPT} language="javascript" showLineNumbers />
|
||||
<CodeSnippet text={TYPESCRIPT} language="typescript" showLineNumbers />
|
||||
<CodeSnippet text={PYTHON} language="python" showLineNumbers />
|
||||
</>
|
||||
);
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 { render } from '@testing-library/react';
|
||||
import { wrapInThemedTestApp } from '@backstage/test-utils';
|
||||
|
||||
import CodeSnippet from './CodeSnippet';
|
||||
|
||||
const JAVASCRIPT = `const greeting = "Hello";
|
||||
const world = "World";
|
||||
|
||||
const greet = person => gretting + " " + person + "!";
|
||||
`;
|
||||
|
||||
const minProps = {
|
||||
text: JAVASCRIPT,
|
||||
language: 'javascript',
|
||||
};
|
||||
|
||||
describe('<CodeSnippet />', () => {
|
||||
it('renders text without exploding', () => {
|
||||
const { getByText } = render(
|
||||
wrapInThemedTestApp(<CodeSnippet {...minProps} />),
|
||||
);
|
||||
expect(getByText(/"Hello"/)).toBeInTheDocument();
|
||||
expect(getByText(/"World"/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders without line numbers', () => {
|
||||
const { queryByText } = render(
|
||||
wrapInThemedTestApp(<CodeSnippet {...minProps} />),
|
||||
);
|
||||
expect(queryByText('1')).not.toBeInTheDocument();
|
||||
expect(queryByText('2')).not.toBeInTheDocument();
|
||||
expect(queryByText('3')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders with line numbers', () => {
|
||||
const { queryByText } = render(
|
||||
wrapInThemedTestApp(<CodeSnippet {...minProps} showLineNumbers />),
|
||||
);
|
||||
expect(queryByText(/1/)).toBeInTheDocument();
|
||||
expect(queryByText(/2/)).toBeInTheDocument();
|
||||
expect(queryByText(/3/)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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, { FC } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||
import { docco, dark } from 'react-syntax-highlighter/dist/cjs/styles/hljs';
|
||||
import { useTheme } from '@material-ui/core';
|
||||
import { BackstageTheme } from '@backstage/theme';
|
||||
|
||||
type Props = {
|
||||
text: string;
|
||||
language: string;
|
||||
showLineNumbers?: boolean;
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
showLineNumbers: false,
|
||||
};
|
||||
|
||||
const CodeSnippet: FC<Props> = props => {
|
||||
const { text, language, showLineNumbers } = {
|
||||
...defaultProps,
|
||||
...props,
|
||||
};
|
||||
|
||||
const theme = useTheme<BackstageTheme>();
|
||||
const mode = theme.palette.type === 'dark' ? dark : docco;
|
||||
|
||||
return (
|
||||
<SyntaxHighlighter
|
||||
language={language}
|
||||
style={mode}
|
||||
showLineNumbers={showLineNumbers}
|
||||
>
|
||||
{text}
|
||||
</SyntaxHighlighter>
|
||||
);
|
||||
};
|
||||
|
||||
// Type check for the JS files using this core component
|
||||
CodeSnippet.propTypes = {
|
||||
text: PropTypes.string.isRequired,
|
||||
language: PropTypes.string.isRequired,
|
||||
showLineNumbers: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default CodeSnippet;
|
||||
@@ -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 { default } from './CodeSnippet';
|
||||
@@ -10907,6 +10907,11 @@ highlight.js@~9.13.0:
|
||||
resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
|
||||
integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
|
||||
|
||||
highlight.js@~9.15.0, highlight.js@~9.15.1:
|
||||
version "9.15.10"
|
||||
resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.10.tgz#7b18ed75c90348c045eef9ed08ca1319a2219ad2"
|
||||
integrity sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw==
|
||||
|
||||
history@^4.9.0:
|
||||
version "4.10.1"
|
||||
resolved "https://registry.npmjs.org/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
|
||||
@@ -14141,6 +14146,14 @@ lowercase-keys@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
||||
integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
|
||||
|
||||
lowlight@1.12.1:
|
||||
version "1.12.1"
|
||||
resolved "https://registry.npmjs.org/lowlight/-/lowlight-1.12.1.tgz#014acf8dd73a370e02ff1cc61debcde3bb1681eb"
|
||||
integrity sha512-OqaVxMGIESnawn+TU/QMV5BJLbUghUfjDWPAtFqDYDmDtr4FnB+op8xM+pR7nKlauHNUHXGt0VgWatFB8voS5w==
|
||||
dependencies:
|
||||
fault "^1.0.2"
|
||||
highlight.js "~9.15.0"
|
||||
|
||||
lowlight@~1.11.0:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.npmjs.org/lowlight/-/lowlight-1.11.0.tgz#1304d83005126d4e8b1dc0f07981e9b689ec2efc"
|
||||
@@ -17923,6 +17936,17 @@ react-syntax-highlighter@^11.0.2:
|
||||
prismjs "^1.8.4"
|
||||
refractor "^2.4.1"
|
||||
|
||||
react-syntax-highlighter@^12.2.1:
|
||||
version "12.2.1"
|
||||
resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-12.2.1.tgz#14d78352da1c1c3f93c6698b70ec7c706b83493e"
|
||||
integrity sha512-CTsp0ZWijwKRYFg9xhkWD4DSpQqE4vb2NKVMdPAkomnILSmsNBHE0n5GuI5zB+PU3ySVvXvdt9jo+ViD9XibCA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.3.1"
|
||||
highlight.js "~9.15.1"
|
||||
lowlight "1.12.1"
|
||||
prismjs "^1.8.4"
|
||||
refractor "^2.4.1"
|
||||
|
||||
react-textarea-autosize@^7.1.0:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-7.1.2.tgz#70fdb333ef86bcca72717e25e623e90c336e2cda"
|
||||
|
||||
Reference in New Issue
Block a user