From 19e34b53192161b6aa71ef676f6cb79c8f34690d Mon Sep 17 00:00:00 2001 From: Sebastian Qvarfordt Date: Wed, 23 Sep 2020 16:40:18 +0200 Subject: [PATCH] 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 * 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 --- .../techdocs/src/reader/components/Reader.tsx | 17 ++++++++ .../techdocs/src/reader/transformers/index.ts | 1 + .../src/reader/transformers/injectCss.test.ts | 40 +++++++++++++++++++ .../src/reader/transformers/injectCss.ts | 31 ++++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 plugins/techdocs/src/reader/transformers/injectCss.test.ts create mode 100644 plugins/techdocs/src/reader/transformers/injectCss.ts diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 8ae3273e12..2aa87ea1ee 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -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(); 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) { diff --git a/plugins/techdocs/src/reader/transformers/index.ts b/plugins/techdocs/src/reader/transformers/index.ts index c8568282cf..ddbaadd071 100644 --- a/plugins/techdocs/src/reader/transformers/index.ts +++ b/plugins/techdocs/src/reader/transformers/index.ts @@ -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; diff --git a/plugins/techdocs/src/reader/transformers/injectCss.test.ts b/plugins/techdocs/src/reader/transformers/injectCss.test.ts new file mode 100644 index 0000000000..afad9bbd2c --- /dev/null +++ b/plugins/techdocs/src/reader/transformers/injectCss.test.ts @@ -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 = ` + + + + + `; + 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); + }); +}); diff --git a/plugins/techdocs/src/reader/transformers/injectCss.ts b/plugins/techdocs/src/reader/transformers/injectCss.ts new file mode 100644 index 0000000000..2f6aa46bb6 --- /dev/null +++ b/plugins/techdocs/src/reader/transformers/injectCss.ts @@ -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', ``); + + return dom; + }; +};