Merge branch 'master' of github.com:spotify/backstage into feat/backend-plugin
* 'master' of github.com:spotify/backstage: (30 commits) fix(techdocs-core): use the content of the readme as long description for the pypi package (#2578) chore: add contrib to CONTRIBUTING.md (#2585) Fix typo (#2584) backend-common: default config env to development v0.1.1-alpha.23 TechDocs: Inject CSS transformer and initial backstage style integration for reader (#2560) bug(gql): use import to import the graphql module Rename file [blog] Announce CNCF Sandbox (#2568) document cleaning - tutorial quickstarts (#2520) Simplify codecov flag names chore(scaffolder-backend): typo in visibility Kubernetes plugins boilerplate (#2559) CHANGELOG: add entry for SessionApi refactor Upload package specific code coverage to codecov Add codecov flags for core and core-api packages TechDocs: Enable allowVulnerableTags in sanitize-html (#2554) chore: trust the Boolean :) docs: regenerate api reference docs core: refactor SessionStateApi to SessionApi with sign-in/out ...
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-techdocs",
|
||||
"version": "0.1.1-alpha.22",
|
||||
"version": "0.1.1-alpha.23",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -22,12 +22,12 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^0.1.1-alpha.22",
|
||||
"@backstage/core": "^0.1.1-alpha.22",
|
||||
"@backstage/core-api": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-catalog": "^0.1.1-alpha.22",
|
||||
"@backstage/test-utils": "^0.1.1-alpha.22",
|
||||
"@backstage/theme": "^0.1.1-alpha.22",
|
||||
"@backstage/catalog-model": "^0.1.1-alpha.23",
|
||||
"@backstage/core": "^0.1.1-alpha.23",
|
||||
"@backstage/core-api": "^0.1.1-alpha.23",
|
||||
"@backstage/plugin-catalog": "^0.1.1-alpha.23",
|
||||
"@backstage/test-utils": "^0.1.1-alpha.23",
|
||||
"@backstage/theme": "^0.1.1-alpha.23",
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
@@ -40,8 +40,8 @@
|
||||
"sanitize-html": "^1.27.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.1.1-alpha.22",
|
||||
"@backstage/dev-utils": "^0.1.1-alpha.22",
|
||||
"@backstage/cli": "^0.1.1-alpha.23",
|
||||
"@backstage/dev-utils": "^0.1.1-alpha.23",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
"@testing-library/react": "^10.4.1",
|
||||
"@testing-library/user-event": "^12.0.7",
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
@@ -62,4 +62,42 @@ describe('sanitizeDOM', () => {
|
||||
shadowDom.querySelector('#test-malicious-link')?.hasAttribute('onclick'),
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
it('removes style tags', () => {
|
||||
const html = `
|
||||
<html>
|
||||
<head>
|
||||
<style>* {color: #f0f;}<style>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
const shadowDom = createTestShadowDom(html, {
|
||||
preTransformers: [sanitizeDOM()],
|
||||
postTransformers: [],
|
||||
});
|
||||
|
||||
expect(shadowDom.querySelectorAll('style').length).toEqual(0);
|
||||
});
|
||||
|
||||
it('does not remove link tags', () => {
|
||||
const html = `
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
const shadowDom = createTestShadowDom(html, {
|
||||
preTransformers: [sanitizeDOM()],
|
||||
postTransformers: [],
|
||||
});
|
||||
|
||||
expect(shadowDom.querySelectorAll('link').length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -101,7 +101,6 @@ export const html = [
|
||||
'span',
|
||||
'strike',
|
||||
'strong',
|
||||
'style',
|
||||
'sub',
|
||||
'summary',
|
||||
'sup',
|
||||
@@ -162,7 +161,6 @@ export const svg = [
|
||||
'radialgradient',
|
||||
'rect',
|
||||
'stop',
|
||||
'style',
|
||||
'switch',
|
||||
'symbol',
|
||||
'text',
|
||||
|
||||
Reference in New Issue
Block a user