Skip to content

Commit

Permalink
fix: restore older impl of CodeViewer (#168)
Browse files Browse the repository at this point in the history
* fix: restore older impl of CodeViewer

* chore: move directories

* chore: langs

* fix: types and stuff

* fix: add refractor dep

* revert: directory structure

* test: refractor is typed now
  • Loading branch information
P0lip authored Jun 3, 2020
1 parent c6df86f commit dac7ad2
Show file tree
Hide file tree
Showing 17 changed files with 1,128 additions and 36 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"react-tabs": "^3.1.0",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "~1.8.5",
"refractor": "^3.0.0",
"yup": "^0.28.0"
},
"devDependencies": {
Expand Down Expand Up @@ -86,6 +87,7 @@
"@types/react-tabs": "^2.3.1",
"@types/react-virtualized-auto-sizer": "^1.0.0",
"@types/react-window": "^1.8.1",
"@types/refractor": "^2.8.0",
"@types/yup": "~0.26.27",
"autoprefixer": "^9.7.3",
"babel-loader": "^8.0.6",
Expand Down
68 changes: 55 additions & 13 deletions src/CodeViewer/__tests__/Viewer.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,77 @@
import { mount } from 'enzyme';
import { shallow } from 'enzyme';
import 'jest-enzyme';
import * as React from 'react';
import { CodeViewer } from '..';
import { CodeViewer } from '../index';
import { astToReact } from '../utils/astToReact';
import { parseCode } from '../utils/parseCode';

jest.mock('../utils/astToReact');
jest.mock('../utils/parseCode');

describe('Code Viewer component', () => {
afterEach(() => {
(parseCode as jest.Mock).mockReset();
(astToReact as jest.Mock).mockReset();
});

it('renders code element with raw value for inline view', () => {
const code = '{}';
const language = 'json';

const wrapper = mount(<CodeViewer language={language} value={code} inline />);
expect(wrapper).toHaveHTML(
`<code class="bp3-code-editor isInline"><span class="token punctuation">{</span><span class="token punctuation">}</span></code>`,
);
const wrapper = shallow(<CodeViewer language={language} value={code} inline />);
expect(wrapper).toHaveText(code);
expect(wrapper).toHaveDisplayName('code');

expect(parseCode).not.toHaveBeenCalled();
});

it('renders pre element for block view', () => {
const code = '{}';
const language = 'json';

const wrapper = mount(<CodeViewer language={language} value={code} />);
expect(wrapper).toHaveHTML(
`<pre class="bp3-code-editor language-json"><span class="token punctuation">{</span><span class="token punctuation">}</span></pre>`,
);
const wrapper = shallow(<CodeViewer language={language} value={code} />);
expect(wrapper).toHaveDisplayName('pre');
});

it('renders code as is if parsing fails', () => {
const code = '{}';
const language = 'json';
(parseCode as jest.Mock).mockReturnValue(null);

const wrapper = shallow(<CodeViewer language={language} value={code} />);
expect(wrapper).toHaveText(code);

expect(parseCode).toHaveBeenCalledWith(code, language, false);
});

it('does not try to map ast nodes to react nodes if parsing failed', () => {
(parseCode as jest.Mock).mockReturnValue(null);
shallow(<CodeViewer language="javascript" value="foo()" />);

expect(astToReact).not.toHaveBeenCalled();
});

it('renders parsed markup if possible', () => {
const code = 'function';
const language = 'javascript';
const html = `<pre class="bp3-code-editor language-javascript"><span class="token keyword">function</span></pre>`;
const ast = [
{
type: 'element',
tagName: 'span',
properties: {
className: ['token', 'function'],
},
value: 'function',
},
];
const markup = <span className="token function">function</span>;

(parseCode as jest.Mock).mockReturnValue(ast);
(astToReact as jest.Mock).mockReturnValue(() => markup);

const wrapper = mount(<CodeViewer language={language} value={code} />);
expect(wrapper).toHaveHTML(html);
const wrapper = shallow(<CodeViewer language={language} value={code} />);
expect(wrapper).toContainReact(markup);
expect(parseCode).toHaveBeenCalledWith(code, language, false);
expect(astToReact).toHaveBeenCalled();
});
});
28 changes: 15 additions & 13 deletions src/CodeViewer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as cn from 'classnames';
import 'prismjs';
import * as React from 'react';

import { Classes } from '../classes';
import { highlightCode } from '../CodeEditor/utils/highlightCode';
import { astToReact } from './utils/astToReact';
import { parseCode } from './utils/parseCode';

const languageMaps: { [from: string]: string } = {
md: 'markdown',
Expand All @@ -12,7 +12,7 @@ const languageMaps: { [from: string]: string } = {
/**
* CODE VIEWER
*/
interface ICodeViewerProps extends React.HTMLAttributes<HTMLDivElement> {
interface ICodeViewerProps extends React.HTMLAttributes<HTMLPreElement> {
value: string;
language?: string;
showLineNumbers?: boolean;
Expand All @@ -27,32 +27,34 @@ const CodeViewer: React.FunctionComponent<ICodeViewerProps> = ({
className,
...rest
}) => {
const lang = (language && languageMaps[language]) || language || '';

const code = React.useMemo(() => highlightCode(value, lang, showLineNumbers), [value, lang, showLineNumbers]);
const lang = (language && languageMaps[language]) || language;

if (inline) {
return (
<code
className={cn(Classes.CODE_EDITOR, className, {
isInline: inline,
'line-numbers': showLineNumbers,
showLineNumbers,
})}
{...rest}
dangerouslySetInnerHTML={{ __html: code }}
/>
>
{value}
</code>
);
}

const markup = parseCode(value, lang, showLineNumbers);

return (
<pre
className={cn(Classes.CODE_EDITOR, className, `language-${lang || 'unknown'}`, {
isInline: inline,
'line-numbers': showLineNumbers,
showLineNumbers,
})}
{...(rest as React.HTMLAttributes<HTMLPreElement>)}
dangerouslySetInnerHTML={{ __html: code }}
/>
{...rest}
>
{markup ? markup.map(astToReact()) : value}
</pre>
);
};

Expand Down
10 changes: 0 additions & 10 deletions src/CodeViewer/types.ts

This file was deleted.

118 changes: 118 additions & 0 deletions src/CodeViewer/utils/__tests__/__snapshots__/astToReact.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`astToReact util fixture clike 1`] = `
<pre>
int
<span
className="token function"
key="cv-0-1"
>
main
</span>
<span
className="token punctuation"
key="cv-0-2"
>
(
</span>
<span
className="token punctuation"
key="cv-0-3"
>
)
</span>
<span
className="token punctuation"
key="cv-0-5"
>
{
</span>
<span
className="token comment"
key="cv-0-7"
>
// some dumb code
</span>
<span
className="token keyword"
key="cv-0-9"
>
return
</span>
<span
className="token number"
key="cv-0-11"
>
0
</span>
<span
className="token punctuation"
key="cv-0-12"
>
;
</span>
<span
className="token punctuation"
key="cv-0-14"
>
}
</span>
</pre>
`;
exports[`astToReact util fixture javascript 1`] = `
<pre>
<span
className="token keyword"
key="cv-0-0"
>
const
</span>
defaultValue
<span
className="token operator"
key="cv-0-2"
>
=
</span>
stoplight
<span
className="token punctuation"
key="cv-0-4"
>
.
</span>
<span
className="token function"
key="cv-0-5"
>
io
</span>
<span
className="token punctuation"
key="cv-0-6"
>
(
</span>
<span
className="token punctuation"
key="cv-0-7"
>
)
</span>
<span
className="token punctuation"
key="cv-0-8"
>
;
</span>
</pre>
`;
Loading

0 comments on commit dac7ad2

Please sign in to comment.