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:
blam
2020-09-24 10:54:04 +02:00
150 changed files with 2452 additions and 993 deletions
+9 -9
View File
@@ -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',