-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(CodeBlock): allow var, mark, and anchor tags within code blocks
- Loading branch information
1 parent
e25190f
commit a916fbb
Showing
5 changed files
with
256 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,7 +64,7 @@ const CodeHighlight = ({ | |
var, | ||
mark { | ||
font-size: 1em; | ||
font-size: inherit; | ||
} | ||
var { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { css } from '@emotion/core'; | ||
import { Link } from '@newrelic/gatsby-theme-newrelic'; | ||
import parse, { domToReact } from 'html-react-parser'; | ||
|
||
const RawCode = ({ code, language }) => { | ||
return ( | ||
<pre | ||
css={css` | ||
color: var(--color-nord-6); | ||
font-family: var(--code-font); | ||
font-size: 0.75rem; | ||
display: block; | ||
overflow: auto; | ||
white-space: pre; | ||
word-spacing: normal; | ||
word-break: normal; | ||
tab-size: 2; | ||
hyphens: none; | ||
text-shadow: none; | ||
padding: 1rem; | ||
.light-mode & { | ||
color: var(--color-nord-0); | ||
} | ||
`} | ||
data-language={language} | ||
> | ||
<code | ||
css={css` | ||
display: table; | ||
width: 100%; | ||
padding: 0; | ||
background: none; | ||
var, | ||
mark { | ||
font-size: inherit; | ||
} | ||
var { | ||
background: var(--color-nord-2); | ||
color: inherit; | ||
.light-mode & { | ||
background: var(--color-nord-4); | ||
} | ||
} | ||
a:hover var { | ||
background: var(--color-nord-3); | ||
.light-mode & { | ||
background: var(--color-nord-5); | ||
} | ||
} | ||
mark { | ||
color: var(--color-neutrals-900) !important; | ||
var { | ||
color: var(--color-neutrals-100); | ||
.light-mode & { | ||
color: var(--color-neutrals-900); | ||
} | ||
} | ||
} | ||
`} | ||
> | ||
{parse(code, { | ||
replace: ({ name, attribs, children }) => { | ||
if (name === 'a') { | ||
return <Link to={attribs.href}>{domToReact(children)}</Link>; | ||
} | ||
|
||
if (name && name !== 'var' && name !== 'mark') { | ||
return domToReact(children); | ||
} | ||
}, | ||
})} | ||
</code> | ||
</pre> | ||
); | ||
}; | ||
|
||
RawCode.propTypes = { | ||
code: PropTypes.string.isRequired, | ||
language: PropTypes.string, | ||
}; | ||
|
||
export default RawCode; |
142 changes: 142 additions & 0 deletions
142
packages/gatsby-theme-newrelic/src/components/__tests__/CodeBlock.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import React from 'react'; | ||
import CodeBlock from '../CodeBlock'; | ||
import { render, fireEvent, screen } from '@testing-library/react'; | ||
import { renderWithTranslation } from '../../test-utils/renderHelpers'; | ||
|
||
jest.mock('gatsby', () => ({ | ||
__esModule: true, | ||
graphql: () => {}, | ||
Link: ({ to, ...props }) => <a href={to} {...props} />, | ||
useStaticQuery: () => ({ | ||
allLocale: { | ||
nodes: [ | ||
{ | ||
name: 'English', | ||
locale: 'en', | ||
localizedPath: '/en', | ||
isDefault: true, | ||
}, | ||
], | ||
}, | ||
site: { | ||
siteMetadata: { | ||
siteUrl: 'https://github.com/foo/bar', | ||
repository: 'https://foobar.net', | ||
}, | ||
}, | ||
}), | ||
})); | ||
|
||
test('renders embedded var tag', () => { | ||
const { container } = renderWithTranslation( | ||
<CodeBlock language="graphql">{` | ||
query MyQuery(<var>$accountId</var>: ID!) { | ||
account(accountId: <var>$accountId</var>) { | ||
name | ||
} | ||
} | ||
`}</CodeBlock> | ||
); | ||
|
||
const vars = container.querySelectorAll('var'); | ||
|
||
expect(vars.length).toEqual(2); | ||
expect(vars[0].textContent).toEqual('$accountId'); | ||
expect(vars[1].textContent).toEqual('$accountId'); | ||
}); | ||
|
||
test('renders embedded mark tags', () => { | ||
const { container } = renderWithTranslation( | ||
<CodeBlock language="graphql">{` | ||
query <mark>MyQuery</mark>($accountId: ID!) { | ||
<mark>account(accountId: $accountId) { | ||
name | ||
}</mark> | ||
} | ||
`}</CodeBlock> | ||
); | ||
|
||
const marks = container.querySelectorAll('mark'); | ||
|
||
expect(marks.length).toEqual(2); | ||
expect(marks[0].textContent).toEqual('MyQuery'); | ||
expect(marks[1].textContent).toEqual(`account(accountId: $accountId) { | ||
name | ||
}`); | ||
}); | ||
|
||
test('renders embedded anchor tags', () => { | ||
const { container } = renderWithTranslation( | ||
<CodeBlock language="graphql">{` | ||
query MyQuery($accountId: ID!) { | ||
<a href="/docs/nerd-graph">account</a>(accountId: $accountId) { | ||
name | ||
} | ||
} | ||
`}</CodeBlock> | ||
); | ||
|
||
const anchors = container.querySelectorAll('a'); | ||
|
||
expect(anchors.length).toEqual(1); | ||
expect(anchors[0].textContent).toEqual('account'); | ||
}); | ||
|
||
test('handles combinations of tags', () => { | ||
const { container } = renderWithTranslation( | ||
<CodeBlock language="graphql">{` | ||
query MyQuery($accountId: ID!) { | ||
<a href="/docs/nerd-graph"><var>account</var></a>(accountId: $accountId) { | ||
name | ||
} | ||
} | ||
`}</CodeBlock> | ||
); | ||
|
||
const anchors = container.querySelectorAll('a'); | ||
const vars = container.querySelectorAll('var'); | ||
|
||
expect(anchors.length).toEqual(1); | ||
expect(vars.length).toEqual(1); | ||
}); | ||
|
||
test('leaves text as-is if other HTML tags are used', () => { | ||
const { container, debug } = renderWithTranslation( | ||
<CodeBlock language="graphql">{` | ||
query <span>MyQuery</span>($accountId: ID!) { | ||
account(<strong>accountId</strong>: $accountId) { | ||
name | ||
} | ||
} | ||
`}</CodeBlock> | ||
); | ||
|
||
const code = container.querySelector('code'); | ||
|
||
expect(code.textContent).toEqual( | ||
`query <span>MyQuery</span>($accountId: ID!) { account(<strong>accountId</strong>: $accountId) { name }}` | ||
); | ||
}); | ||
|
||
test('leaves var/mark/a tags as raw text when language is html', () => { | ||
const { container } = renderWithTranslation( | ||
<CodeBlock language="html">{` | ||
<!DOCTYPE html> | ||
<html> | ||
<body> | ||
<div> | ||
<var>$accountId</var> | ||
<mark>Highlight it up!</mark> | ||
<a href="/docs/nrql">A link</a> | ||
</div> | ||
</body> | ||
</html> | ||
`}</CodeBlock> | ||
); | ||
|
||
const vars = container.querySelectorAll('var'); | ||
|
||
expect(container.querySelectorAll('var').length).toEqual(0); | ||
expect(container.querySelectorAll('mark').length).toEqual(0); | ||
expect(container.querySelectorAll('a').length).toEqual(0); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters