TechDocs: Inject CSS transformer and initial backstage style integration for reader (#2560)

* Inject CSS transformer and initial backstage style integration for reader

* Update plugins/techdocs/src/reader/transformers/injectCss.test.ts

Co-authored-by: Emma Indal <emmai@spotify.com>

* Fix test name and run injectCss in preTransformer

* Fix for invisible links in reader

* Added missing semi-colon

* Better styling on codeblocks

Co-authored-by: Emma Indal <emmai@spotify.com>
This commit is contained in:
Sebastian Qvarfordt
2020-09-23 16:40:18 +02:00
committed by GitHub
parent 216257c4e0
commit 19e34b5319
4 changed files with 89 additions and 0 deletions
@@ -21,6 +21,8 @@ import { useAsync } from 'react-use';
import { techdocsStorageApiRef } from '../../api';
import { useParams, useNavigate } from 'react-router-dom';
import { ParsedEntityId } from '../../types';
import { useTheme } from '@material-ui/core';
import { BackstageTheme } from '@backstage/theme';
import transformer, {
addBaseUrl,
@@ -30,6 +32,7 @@ import transformer, {
modifyCss,
onCssReady,
sanitizeDOM,
injectCss,
} from '../transformers';
import { TechDocsNotFound } from './TechDocsNotFound';
@@ -40,6 +43,7 @@ type Props = {
export const Reader = ({ entityId }: Props) => {
const { kind, namespace, name } = entityId;
const { '*': path } = useParams();
const theme = useTheme<BackstageTheme>();
const techdocsStorageApi = useApi(techdocsStorageApiRef);
const [shadowDomRef, shadowRoot] = useShadowDom();
@@ -73,6 +77,18 @@ export const Reader = ({ entityId }: Props) => {
},
}),
removeMkdocsHeader(),
injectCss({
css: `
body {
font-family: ${theme.typography.fontFamily};
--md-text-color: ${theme.palette.text.primary};
--md-text-link-color: ${theme.palette.primary.main};
--md-code-fg-color: ${theme.palette.text.primary};
--md-code-bg-color: ${theme.palette.background.paper};
}
`,
}),
]);
if (!transformedElement) {
@@ -125,6 +141,7 @@ export const Reader = ({ entityId }: Props) => {
entityId,
navigate,
techdocsStorageApi,
theme,
]);
if (error) {
@@ -21,6 +21,7 @@ export * from './removeMkdocsHeader';
export * from './modifyCss';
export * from './onCssReady';
export * from './sanitizeDOM';
export * from './injectCss';
export type Transformer = (dom: Element) => Element;
@@ -0,0 +1,40 @@
/*
* 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 { createTestShadowDom } from '../../test-utils';
import { injectCss } from '../transformers';
describe('injectCss', () => {
it('should inject style with passed css in head', () => {
const html = `
<html>
<head></head>
<body></body>
</html>
`;
const injectedCss = '* {background-color: #fff}';
const shadowDom = createTestShadowDom(html, {
preTransformers: [injectCss({ css: injectedCss })],
postTransformers: [],
});
const styleElement = shadowDom.querySelector('head > style');
expect(styleElement).toBeTruthy();
expect(styleElement!.innerHTML).toEqual(injectedCss);
});
});
@@ -0,0 +1,31 @@
/*
* 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 type { Transformer } from './index';
type InjectCssOptions = {
css: string;
};
export const injectCss = ({ css }: InjectCssOptions): Transformer => {
return dom => {
dom
.getElementsByTagName('head')[0]
.insertAdjacentHTML('beforeend', `<style>${css}</style>`);
return dom;
};
};