diff --git a/.changeset/techdocs-hold-me-closer.md b/.changeset/techdocs-hold-me-closer.md
new file mode 100644
index 0000000000..2295603388
--- /dev/null
+++ b/.changeset/techdocs-hold-me-closer.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs-addons': minor
+---
+
+Introducing an addon framework for TechDocs.
diff --git a/plugins/techdocs-addons/api-report.md b/plugins/techdocs-addons/api-report.md
index f3b3d5fe69..c5a61a34e3 100644
--- a/plugins/techdocs-addons/api-report.md
+++ b/plugins/techdocs-addons/api-report.md
@@ -3,9 +3,14 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
+///
+
import { ComponentType } from 'react';
+import { CompoundEntityRef } from '@backstage/catalog-model';
import { Extension } from '@backstage/core-plugin-api';
import { default as React_2 } from 'react';
+import { TechDocsEntityMetadata } from '@backstage/plugin-techdocs';
+import { TechDocsMetadata } from '@backstage/plugin-techdocs';
// @public
export function createTechDocsAddon(
@@ -31,4 +36,28 @@ export type TechDocsAddonOptions = {
// @public
export const TechDocsAddons: React_2.ComponentType;
+
+// @public
+export const TechDocsReaderPage: (
+ props: TechDocsReaderPageProps,
+) => JSX.Element;
+
+// @public (undocumented)
+export type TechDocsReaderPageProps = {
+ entityName: CompoundEntityRef;
+};
+
+// @public
+export const useEntityMetadata: () => TechDocsEntityMetadata | undefined;
+
+// @public
+export const useMetadata: () => TechDocsMetadata | undefined;
+
+// @public
+export const useShadowRoot: () => ShadowRoot | undefined;
+
+// @public
+export const useShadowRootElements: (
+ selectors: string[],
+) => T[];
```
diff --git a/plugins/techdocs-addons/package.json b/plugins/techdocs-addons/package.json
index 79da76e32a..3eb29ea77a 100644
--- a/plugins/techdocs-addons/package.json
+++ b/plugins/techdocs-addons/package.json
@@ -22,8 +22,17 @@
"postpack": "backstage-cli package postpack"
},
"dependencies": {
+ "@backstage/catalog-model": "^0.13.0",
+ "@backstage/core-components": "^0.9.1",
"@backstage/core-plugin-api": "^0.8.0",
- "react-router-dom": "6.0.0-beta.0"
+ "@backstage/plugin-techdocs": "^0.15.1",
+ "@material-ui/core": "^4.12.2",
+ "@material-ui/lab": "4.0.0-alpha.57",
+ "@material-ui/styles": "^4.11.0",
+ "jss": "~10.8.2",
+ "react-helmet": "6.1.0",
+ "react-router-dom": "6.0.0-beta.0",
+ "react-use": "^17.2.4"
},
"peerDependencies": {
"@types/react": "^16.13.1 || ^17.0.0",
diff --git a/plugins/techdocs-addons/src/context.tsx b/plugins/techdocs-addons/src/context.tsx
new file mode 100644
index 0000000000..7908033874
--- /dev/null
+++ b/plugins/techdocs-addons/src/context.tsx
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * 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 { CompoundEntityRef } from '@backstage/catalog-model';
+import { useApi, useApp } from '@backstage/core-plugin-api';
+import {
+ techdocsApiRef,
+ TechDocsEntityMetadata,
+ TechDocsMetadata,
+} from '@backstage/plugin-techdocs';
+import React, {
+ createContext,
+ Dispatch,
+ PropsWithChildren,
+ SetStateAction,
+ useContext,
+ useState,
+} from 'react';
+import useAsync from 'react-use/lib/useAsync';
+
+type PropsWithEntityName = PropsWithChildren<{ entityName: CompoundEntityRef }>;
+
+const TechDocsMetadataContext = createContext(
+ undefined,
+);
+
+export const TechDocsMetadataProvider = ({
+ entityName,
+ children,
+}: PropsWithEntityName) => {
+ const { NotFoundErrorPage } = useApp().getComponents();
+ const techdocsApi = useApi(techdocsApiRef);
+
+ const { value, loading, error } = useAsync(async () => {
+ return await techdocsApi.getTechDocsMetadata(entityName);
+ }, []);
+
+ if (!loading && error) {
+ return ;
+ }
+
+ return (
+
+ {children}
+
+ );
+};
+
+/**
+ * Hook for use within TechDocs addons to retrieve TechDocs Metadata for the
+ * current TechDocs site.
+ * @public
+ */
+export const useMetadata = () => {
+ return useContext(TechDocsMetadataContext);
+};
+
+const TechDocsEntityContext = createContext(
+ undefined,
+);
+
+export const TechDocsEntityProvider = ({
+ entityName,
+ children,
+}: PropsWithEntityName) => {
+ const { NotFoundErrorPage } = useApp().getComponents();
+ const techdocsApi = useApi(techdocsApiRef);
+
+ const { value, loading, error } = useAsync(async () => {
+ return await techdocsApi.getEntityMetadata(entityName);
+ }, []);
+
+ if (!loading && error) {
+ return ;
+ }
+
+ return (
+
+ {children}
+
+ );
+};
+
+/**
+ * Hook for use within TechDocs addons to retrieve Entity Metadata for the
+ * current TechDocs site.
+ * @public
+ */
+export const useEntityMetadata = () => {
+ return useContext(TechDocsEntityContext);
+};
+
+export type TechDocsReaderPageValue = {
+ entityName: CompoundEntityRef;
+ shadowRoot?: ShadowRoot;
+ setShadowRoot: Dispatch>;
+ title: string;
+ setTitle: Dispatch>;
+ subtitle: string;
+ setSubtitle: Dispatch>;
+};
+
+export const defaultTechDocsReaderPageValue: TechDocsReaderPageValue = {
+ title: '',
+ setTitle: () => {},
+ subtitle: '',
+ setSubtitle: () => {},
+ setShadowRoot: () => {},
+ entityName: { kind: '', name: '', namespace: '' },
+};
+
+export const TechDocsReaderPageContext = createContext(
+ defaultTechDocsReaderPageValue,
+);
+
+export const useTechDocsReaderPage = () => {
+ return useContext(TechDocsReaderPageContext);
+};
+
+export const TechDocsReaderPageProvider = ({
+ entityName,
+ children,
+}: PropsWithEntityName) => {
+ const [title, setTitle] = useState(defaultTechDocsReaderPageValue.title);
+ const [subtitle, setSubtitle] = useState(
+ defaultTechDocsReaderPageValue.subtitle,
+ );
+ const [shadowRoot, setShadowRoot] = useState(
+ defaultTechDocsReaderPageValue.shadowRoot,
+ );
+
+ const value = {
+ entityName,
+ shadowRoot,
+ setShadowRoot,
+ title,
+ setTitle,
+ subtitle,
+ setSubtitle,
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+/**
+ * Hook for use within TechDocs addons that provides access to the underlying
+ * shadow root of the current page, allowing the DOM within to be mutated.
+ * @public
+ */
+export const useShadowRoot = () => {
+ const { shadowRoot } = useTechDocsReaderPage();
+ return shadowRoot;
+};
+
+/**
+ * Convenience hook for use within TechDocs addons that provides access to
+ * elements that match a given selector within the shadow root.
+ *
+ * todo(backstage/techdocs-core): Consider extending `selectors` from string[]
+ * to some kind of typed object array, so users have more control over the
+ * shape of the result. e.g. a flag to indicate querySelector vs.
+ * querySelectorAll.
+ *
+ * @public
+ */
+export const useShadowRootElements = (
+ selectors: string[],
+): T[] => {
+ const shadowRoot = useShadowRoot();
+ if (!shadowRoot) return [];
+ return selectors
+ .map(selector => shadowRoot?.querySelectorAll(selector))
+ .filter(nodeList => nodeList.length)
+ .map(nodeList => Array.from(nodeList))
+ .flat();
+};
diff --git a/plugins/techdocs-addons/src/index.ts b/plugins/techdocs-addons/src/index.ts
index ba9f2a7266..43802de14f 100644
--- a/plugins/techdocs-addons/src/index.ts
+++ b/plugins/techdocs-addons/src/index.ts
@@ -21,4 +21,12 @@
*/
export { createTechDocsAddon, TechDocsAddons } from './addons';
+export {
+ useEntityMetadata,
+ useMetadata,
+ useShadowRoot,
+ useShadowRootElements,
+} from './context';
+export { TechDocsReaderPage } from './reader';
+export type { TechDocsReaderPageProps } from './reader';
export type { TechDocsAddonLocations, TechDocsAddonOptions } from './types';
diff --git a/plugins/techdocs-addons/src/reader.tsx b/plugins/techdocs-addons/src/reader.tsx
new file mode 100644
index 0000000000..f7f2407d46
--- /dev/null
+++ b/plugins/techdocs-addons/src/reader.tsx
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * 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 { CompoundEntityRef } from '@backstage/catalog-model';
+import { Content, Header, Page, Progress } from '@backstage/core-components';
+import { configApiRef, useApi } from '@backstage/core-plugin-api';
+// todo(backstage/techdocs-core): Export these from @backstage/plugin-techdocs
+import {
+ // @ts-ignore
+ useTechDocsReaderDom,
+ // @ts-ignore
+ withTechDocsReaderProvider,
+ // @ts-ignore
+ TechDocsStateIndicator as TechDocReaderPageIndicator,
+} from '@backstage/plugin-techdocs';
+import {
+ withStyles,
+ Portal,
+ Box,
+ Toolbar,
+ ToolbarProps,
+} from '@material-ui/core';
+import { Skeleton } from '@material-ui/lab';
+import { StylesProvider, jssPreset } from '@material-ui/styles';
+import React, { useEffect, useRef, useState } from 'react';
+import { create } from 'jss';
+import Helmet from 'react-helmet';
+
+import { useTechDocsAddons } from './addons';
+import {
+ TechDocsMetadataProvider,
+ useMetadata,
+ TechDocsEntityProvider,
+ TechDocsReaderPageProvider,
+ useTechDocsReaderPage,
+} from './context';
+import { TechDocsAddonLocations as locations } from './types';
+
+const TechDocsReaderPageSubheader = withStyles(theme => ({
+ root: {
+ gridArea: 'pageSubheader',
+ flexDirection: 'column',
+ minHeight: 'auto',
+ padding: theme.spacing(3, 3, 0),
+ },
+}))(({ ...rest }: ToolbarProps) => {
+ const addons = useTechDocsAddons();
+
+ if (!addons.renderComponentsWithLocation(locations.SUBHEADER)) return null;
+
+ return (
+
+ {addons.renderComponentsWithLocation(locations.SUBHEADER) && (
+
+ {addons.renderComponentsWithLocation(locations.SUBHEADER)}
+
+ )}
+
+ );
+});
+
+const skeleton = ;
+
+const TechDocsReaderPageHeader = () => {
+ const addons = useTechDocsAddons();
+ const configApi = useApi(configApiRef);
+
+ const metadata = useMetadata();
+
+ const { title, setTitle, subtitle, setSubtitle } = useTechDocsReaderPage();
+
+ useEffect(() => {
+ if (!metadata) return;
+ setTitle(prevTitle => prevTitle || metadata.site_name);
+ setSubtitle(
+ prevSubtitle => prevSubtitle || metadata.site_description || 'Home',
+ );
+ }, [metadata, setTitle, setSubtitle]);
+
+ const appTitle = configApi.getOptional('app.title') || 'Backstage';
+ const tabTitle = [subtitle, title, appTitle].filter(Boolean).join(' | ');
+
+ return (
+
+
+ {tabTitle}
+
+ {addons.renderComponentsWithLocation(locations.HEADER)}
+
+ );
+};
+
+const TechDocsReaderPageContent = () => {
+ const ref = useRef(null);
+ const [jss, setJss] = useState(
+ create({
+ ...jssPreset(),
+ insertionPoint: undefined,
+ }),
+ );
+
+ const addons = useTechDocsAddons();
+ const { entityName, setShadowRoot } = useTechDocsReaderPage();
+ const dom = useTechDocsReaderDom(entityName);
+
+ useEffect(() => {
+ const shadowHost = ref.current;
+ if (!dom || !shadowHost || shadowHost.shadowRoot) return;
+
+ setJss(
+ create({
+ ...jssPreset(),
+ insertionPoint: dom.querySelector('head') || undefined,
+ }),
+ );
+
+ const shadowRoot = shadowHost.attachShadow({ mode: 'open' });
+ shadowRoot.innerHTML = '';
+ shadowRoot.appendChild(dom);
+ setShadowRoot(shadowRoot);
+ }, [dom, setShadowRoot]);
+
+ const contentElement = ref.current?.shadowRoot?.querySelector(
+ '[data-md-component="container"]',
+ );
+ const primarySidebarElement = ref.current?.shadowRoot?.querySelector(
+ '[data-md-component="navigation"]',
+ );
+ const secondarySidebarElement = ref.current?.shadowRoot?.querySelector(
+ '[data-md-component="toc"]',
+ );
+
+ const primarySidebarAddonSpace = document.createElement('div');
+ primarySidebarElement?.prepend(primarySidebarAddonSpace);
+
+ const secondarySidebarAddonSpace = document.createElement('div');
+ secondarySidebarElement?.prepend(secondarySidebarAddonSpace);
+
+ // do not return content until dom is ready
+ if (!dom) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+ {/* sheetsManager={new Map()} is needed in order to deduplicate the injection of CSS in the page. */}
+
+
+
+ {addons.renderComponentsWithLocation(locations.PRIMARY_SIDEBAR)}
+
+
+ {addons.renderComponentsWithLocation(locations.CONTENT)}
+
+
+ {addons.renderComponentsWithLocation(locations.SECONDARY_SIDEBAR)}
+
+
+
+ );
+};
+
+/**
+ * @public
+ */
+export type TechDocsReaderPageProps = { entityName: CompoundEntityRef };
+
+/**
+ * An addon-aware implementation of the TechDocsReaderPage.
+ * @public
+ */
+export const TechDocsReaderPage = (props: TechDocsReaderPageProps) => {
+ const { entityName } = props;
+ const Component = withTechDocsReaderProvider(() => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }, entityName);
+ return ;
+};
diff --git a/plugins/techdocs-addons/src/types.ts b/plugins/techdocs-addons/src/types.ts
index 584d2229b3..9cb095577f 100644
--- a/plugins/techdocs-addons/src/types.ts
+++ b/plugins/techdocs-addons/src/types.ts
@@ -54,6 +54,9 @@ export enum TechDocsAddonLocations {
* every HTML node with the same tag name as the addon name in the markdown
* content. If no reference is made, no instance will be rendered. Works like
* regular React components, just being accessible from markdown.
+ *
+ * todo(backstage/techdocs-core): Keep and implement or remove before
+ * releasing this package!
*/
COMPONENT = 'component',
}
diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json
index 8516c09783..d0ef75e32c 100644
--- a/plugins/techdocs/package.json
+++ b/plugins/techdocs/package.json
@@ -72,6 +72,7 @@
"@testing-library/react": "^12.1.3",
"@testing-library/react-hooks": "^7.0.2",
"@testing-library/user-event": "^14.0.0",
+ "@types/event-source-polyfill": "^1.0.0",
"@types/dompurify": "^2.2.2",
"@types/jest": "^26.0.7",
"@types/node": "^16.11.26",
diff --git a/yarn.lock b/yarn.lock
index 37046a1f16..3cfe0b84fc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1456,6 +1456,15 @@
"@babel/helper-validator-identifier" "^7.16.7"
to-fast-properties "^2.0.0"
+"@backstage/catalog-client@^0.9.0":
+ version "0.9.0"
+ resolved "https://registry.npmjs.org/@backstage/catalog-client/-/catalog-client-0.9.0.tgz#3e1024fab13fd8e2000d33833d2463ea9be5df9d"
+ integrity sha1-PhAk+rE/2OIADTODPSRj6pvl350=
+ dependencies:
+ "@backstage/catalog-model" "^0.13.0"
+ "@backstage/errors" "^0.2.2"
+ cross-fetch "^3.1.5"
+
"@backstage/catalog-client@^1.0.0":
version "1.0.0"
resolved "https://registry.npmjs.org/@backstage/catalog-client/-/catalog-client-1.0.0.tgz#05f9ee3b771ca17e4800f5116d63bd183fe0c4d6"
@@ -1465,6 +1474,19 @@
"@backstage/errors" "^1.0.0"
cross-fetch "^3.1.5"
+"@backstage/catalog-model@^0.13.0":
+ version "0.13.0"
+ resolved "https://registry.npmjs.org/@backstage/catalog-model/-/catalog-model-0.13.0.tgz#abeb91522ac7ef7907907ad5bc889803131db209"
+ integrity sha1-q+uRUirH73kHkHrVvIiYAxMdsgk=
+ dependencies:
+ "@backstage/config" "^0.1.15"
+ "@backstage/errors" "^0.2.2"
+ "@backstage/types" "^0.1.3"
+ ajv "^7.0.3"
+ json-schema "^0.4.0"
+ lodash "^4.17.21"
+ uuid "^8.0.0"
+
"@backstage/catalog-model@^1.0.0":
version "1.0.0"
resolved "https://registry.npmjs.org/@backstage/catalog-model/-/catalog-model-1.0.0.tgz#0aa8694a3182aaf4232725842da751bf5f78bd68"
@@ -1478,7 +1500,15 @@
lodash "^4.17.21"
uuid "^8.0.0"
-"@backstage/core-components@^0.9.0", "@backstage/core-components@^0.9.2":
+"@backstage/config@^0.1.15":
+ version "0.1.15"
+ resolved "https://registry.npmjs.org/@backstage/config/-/config-0.1.15.tgz#4bad122ad861be5bd61a60639f92d2494fa245c5"
+ integrity sha512-eNJEYYSEu9MkrkBYiMpUBWEc3Bu64YgB9pZZGCMW7/9350tV2wbylEdoBJHslilJlJhiUyTXBckn8Ua7DOH7rw==
+ dependencies:
+ "@backstage/types" "^0.1.3"
+ lodash "^4.17.21"
+
+"@backstage/core-components@^0.9.0", "@backstage/core-components@^0.9.1", "@backstage/core-components@^0.9.2":
version "0.9.2"
resolved "https://registry.npmjs.org/@backstage/core-components/-/core-components-0.9.2.tgz#9a3d79a15039256bbc007e5daa08c983050e0238"
integrity sha512-kh0FB0FmjC55W+xSEkKrAc7D6hvbYLY7N1UUd6M4VBghYXD61Y8RrJFKmBM3bAfPgYaryQNjYgA0BsoTo53PJA==
@@ -1522,6 +1552,43 @@
zen-observable "^0.8.15"
zod "^3.11.6"
+"@backstage/core-plugin-api@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.npmjs.org/@backstage/core-plugin-api/-/core-plugin-api-0.8.0.tgz#e2096bff679183168a7f9b47ed27c50a01970e32"
+ integrity sha1-4glr/2eRgxaKf5tH7SfFCgGXDjI=
+ dependencies:
+ "@backstage/config" "^0.1.15"
+ "@backstage/types" "^0.1.3"
+ "@backstage/version-bridge" "^0.1.2"
+ history "^5.0.0"
+ prop-types "^15.7.2"
+ react-router-dom "6.0.0-beta.0"
+ zen-observable "^0.8.15"
+
+"@backstage/errors@^0.2.2":
+ version "0.2.2"
+ resolved "https://registry.npmjs.org/@backstage/errors/-/errors-0.2.2.tgz#2113e0bc859e645b8b59bfcb435f7535739b02f8"
+ integrity sha1-IRPgvIWeZFuLWb/LQ191NXObAvg=
+ dependencies:
+ "@backstage/types" "^0.1.3"
+ cross-fetch "^3.1.5"
+ serialize-error "^8.0.1"
+
+"@backstage/integration-react@^0.1.25":
+ version "0.1.25"
+ resolved "https://registry.npmjs.org/@backstage/integration-react/-/integration-react-0.1.25.tgz#ebbdd30d66e1d210b7cd33a682ad2be0d5ea5fc0"
+ integrity sha1-673TDWbh0hC3zTOmgq0r4NXqX8A=
+ dependencies:
+ "@backstage/config" "^0.1.15"
+ "@backstage/core-components" "^0.9.1"
+ "@backstage/core-plugin-api" "^0.8.0"
+ "@backstage/integration" "^0.8.0"
+ "@backstage/theme" "^0.2.15"
+ "@material-ui/core" "^4.12.2"
+ "@material-ui/icons" "^4.9.1"
+ "@material-ui/lab" "4.0.0-alpha.57"
+ react-use "^17.2.4"
+
"@backstage/integration-react@^1.0.0":
version "1.0.0"
resolved "https://registry.npmjs.org/@backstage/integration-react/-/integration-react-1.0.0.tgz#8075e65c6b5387631d27a9c242e7a4fff6f92417"
@@ -1537,6 +1604,19 @@
"@material-ui/lab" "4.0.0-alpha.57"
react-use "^17.2.4"
+"@backstage/integration@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.npmjs.org/@backstage/integration/-/integration-0.8.0.tgz#d74131ad347272b4935973aa4bd098fad9548ce6"
+ integrity sha1-10ExrTRycrSTWXOqS9CY+tlUjOY=
+ dependencies:
+ "@backstage/config" "^0.1.15"
+ "@octokit/auth-app" "^3.4.0"
+ "@octokit/rest" "^18.5.3"
+ cross-fetch "^3.1.5"
+ git-url-parse "^11.6.0"
+ lodash "^4.17.21"
+ luxon "^2.0.2"
+
"@backstage/integration@^1.0.0":
version "1.0.0"
resolved "https://registry.npmjs.org/@backstage/integration/-/integration-1.0.0.tgz#e307cfddea014bfb0eb2281a5ae25ea0b742e9cf"
@@ -1550,6 +1630,41 @@
lodash "^4.17.21"
luxon "^2.0.2"
+"@backstage/plugin-catalog-common@^0.2.2":
+ version "0.2.2"
+ resolved "https://registry.npmjs.org/@backstage/plugin-catalog-common/-/plugin-catalog-common-0.2.2.tgz#2f039ecd829d1d8e017609cb0bbf9af7c231ab63"
+ integrity sha1-LwOezYKdHY4BdgnLC7+a98Ixq2M=
+ dependencies:
+ "@backstage/plugin-permission-common" "^0.5.2"
+ "@backstage/search-common" "^0.3.1"
+
+"@backstage/plugin-catalog-react@^0.9.0":
+ version "0.9.0"
+ resolved "https://registry.npmjs.org/@backstage/plugin-catalog-react/-/plugin-catalog-react-0.9.0.tgz#ff8c09ec455655fadb2c2fafd578908138b858bc"
+ integrity sha1-/4wJ7EVWVfrbLC+v1XiQgTi4WLw=
+ dependencies:
+ "@backstage/catalog-client" "^0.9.0"
+ "@backstage/catalog-model" "^0.13.0"
+ "@backstage/core-components" "^0.9.1"
+ "@backstage/core-plugin-api" "^0.8.0"
+ "@backstage/errors" "^0.2.2"
+ "@backstage/integration" "^0.8.0"
+ "@backstage/plugin-permission-common" "^0.5.2"
+ "@backstage/plugin-permission-react" "^0.3.3"
+ "@backstage/types" "^0.1.3"
+ "@backstage/version-bridge" "^0.1.2"
+ "@material-ui/core" "^4.12.2"
+ "@material-ui/icons" "^4.9.1"
+ "@material-ui/lab" "4.0.0-alpha.57"
+ classnames "^2.2.6"
+ jwt-decode "^3.1.0"
+ lodash "^4.17.21"
+ qs "^6.9.4"
+ react-router "6.0.0-beta.0"
+ react-use "^17.2.4"
+ yaml "^1.10.0"
+ zen-observable "^0.8.15"
+
"@backstage/plugin-catalog-react@^1.0.0":
version "1.0.0"
resolved "https://registry.npmjs.org/@backstage/plugin-catalog-react/-/plugin-catalog-react-1.0.0.tgz#4f42c070ffe5c9690e45a5288e18bacd8d4e0e66"
@@ -1578,7 +1693,33 @@
yaml "^1.10.0"
zen-observable "^0.8.15"
-"@backstage/plugin-permission-common@^0.5.3":
+"@backstage/plugin-catalog@^0.10.0":
+ version "0.10.0"
+ resolved "https://registry.npmjs.org/@backstage/plugin-catalog/-/plugin-catalog-0.10.0.tgz#7b7f1b54704380c51f7506bfba948a3e0ff0575d"
+ integrity sha1-e38bVHBDgMUfdQa/upSKPg/wV10=
+ dependencies:
+ "@backstage/catalog-client" "^0.9.0"
+ "@backstage/catalog-model" "^0.13.0"
+ "@backstage/core-components" "^0.9.1"
+ "@backstage/core-plugin-api" "^0.8.0"
+ "@backstage/errors" "^0.2.2"
+ "@backstage/integration-react" "^0.1.25"
+ "@backstage/plugin-catalog-common" "^0.2.2"
+ "@backstage/plugin-catalog-react" "^0.9.0"
+ "@backstage/plugin-search-common" "^0.3.1"
+ "@backstage/theme" "^0.2.15"
+ "@backstage/types" "^0.1.2"
+ "@material-ui/core" "^4.12.2"
+ "@material-ui/icons" "^4.9.1"
+ "@material-ui/lab" "4.0.0-alpha.57"
+ history "^5.0.0"
+ lodash "^4.17.21"
+ react-helmet "6.1.0"
+ react-router "6.0.0-beta.0"
+ react-use "^17.2.4"
+ zen-observable "^0.8.15"
+
+"@backstage/plugin-permission-common@^0.5.2", "@backstage/plugin-permission-common@^0.5.3":
version "0.5.3"
resolved "https://registry.npmjs.org/@backstage/plugin-permission-common/-/plugin-permission-common-0.5.3.tgz#a1a4446e603584f2c82763745051f75f4a942eb1"
integrity sha512-zppDsNZEK9ffgXbf/Zx0sw4ffuOVOEvBZlft1+Oph2rO4+uN7dmCLMRRcKsYeNQ6/F50e6BMyNWpPZQDR/JQsA==
@@ -1589,7 +1730,7 @@
uuid "^8.0.0"
zod "^3.11.6"
-"@backstage/plugin-permission-react@^0.3.4":
+"@backstage/plugin-permission-react@^0.3.3", "@backstage/plugin-permission-react@^0.3.4":
version "0.3.4"
resolved "https://registry.npmjs.org/@backstage/plugin-permission-react/-/plugin-permission-react-0.3.4.tgz#e769dc1489c35d9c924234c0764a584558891716"
integrity sha512-S8s1cvCZFmxP4Dn5V9fOls31s4V1rgx3YUXqHSkgLatYHOXczf+GM/c5rdGLQyOb/+Hb+MQqaPAkojvSxNliow==
@@ -1602,6 +1743,83 @@
react-use "^17.2.4"
swr "^1.1.2"
+"@backstage/plugin-search-common@0.3.2", "@backstage/plugin-search-common@^0.3.1", "@backstage/plugin-search-common@^0.3.2":
+ version "0.3.2"
+ resolved "https://registry.npmjs.org/@backstage/plugin-search-common/-/plugin-search-common-0.3.2.tgz#15984ba4c14f8a9119168e8c79344ef8101863dc"
+ integrity sha1-FZhLpMFPipEZFo6MeTRO+BAYY9w=
+ dependencies:
+ "@backstage/plugin-permission-common" "^0.5.3"
+ "@backstage/types" "^1.0.0"
+
+"@backstage/plugin-search@^0.7.3":
+ version "0.7.4"
+ resolved "https://registry.npmjs.org/@backstage/plugin-search/-/plugin-search-0.7.4.tgz#d6571da128342d122f80253a756ece0a702967f9"
+ integrity sha1-1lcdoSg0LRIvgCU6dW7OCnApZ/k=
+ dependencies:
+ "@backstage/catalog-model" "^1.0.0"
+ "@backstage/config" "^1.0.0"
+ "@backstage/core-components" "^0.9.2"
+ "@backstage/core-plugin-api" "^1.0.0"
+ "@backstage/errors" "^1.0.0"
+ "@backstage/plugin-catalog-react" "^1.0.0"
+ "@backstage/plugin-search-common" "^0.3.2"
+ "@backstage/theme" "^0.2.15"
+ "@backstage/types" "^1.0.0"
+ "@material-ui/core" "^4.12.2"
+ "@material-ui/icons" "^4.9.1"
+ "@material-ui/lab" "4.0.0-alpha.57"
+ qs "^6.9.4"
+ react-router "6.0.0-beta.0"
+ react-router-dom "6.0.0-beta.0"
+ react-text-truncate "^0.18.0"
+ react-use "^17.2.4"
+
+"@backstage/plugin-techdocs@^0.15.1":
+ version "0.15.1"
+ resolved "https://registry.npmjs.org/@backstage/plugin-techdocs/-/plugin-techdocs-0.15.1.tgz#f57b63526976da04f1d926b5b5b50e1a89b29184"
+ integrity sha1-9XtjUml22gTx2Sa1tbUOGomykYQ=
+ dependencies:
+ "@backstage/catalog-model" "^0.13.0"
+ "@backstage/config" "^0.1.15"
+ "@backstage/core-components" "^0.9.1"
+ "@backstage/core-plugin-api" "^0.8.0"
+ "@backstage/errors" "^0.2.2"
+ "@backstage/integration" "^0.8.0"
+ "@backstage/integration-react" "^0.1.25"
+ "@backstage/plugin-catalog" "^0.10.0"
+ "@backstage/plugin-catalog-react" "^0.9.0"
+ "@backstage/plugin-search" "^0.7.3"
+ "@backstage/theme" "^0.2.15"
+ "@material-ui/core" "^4.12.2"
+ "@material-ui/icons" "^4.9.1"
+ "@material-ui/lab" "4.0.0-alpha.57"
+ "@material-ui/styles" "^4.10.0"
+ dompurify "^2.2.9"
+ event-source-polyfill "^1.0.25"
+ git-url-parse "^11.6.0"
+ lodash "^4.17.21"
+ react-router "6.0.0-beta.0"
+ react-router-dom "6.0.0-beta.0"
+ react-text-truncate "^0.18.0"
+ react-use "^17.2.4"
+
+"@backstage/search-common@^0.3.1":
+ version "0.3.2"
+ resolved "https://registry.npmjs.org/@backstage/search-common/-/search-common-0.3.2.tgz#608a4eddf7eae71ed807ec1f723a80c6f7cdf3e4"
+ integrity sha1-YIpO3ffq5x7YB+wfcjqAxvfN8+Q=
+ dependencies:
+ "@backstage/plugin-search-common" "0.3.2"
+
+"@backstage/types@^0.1.2", "@backstage/types@^0.1.3":
+ version "0.1.3"
+ resolved "https://registry.npmjs.org/@backstage/types/-/types-0.1.3.tgz#6613d8cbdf97d42d31cd1e66a833df533e7ccf14"
+ integrity sha512-fJVi4oVrlO+G3PRv1fYSll9/X4pE11HLnkI//Geare9sP6wSfp/2zXpLYfKVsG0e24jOl7Swkc8lwLkQ90zMaQ==
+
+"@backstage/version-bridge@^0.1.2":
+ version "0.1.2"
+ resolved "https://registry.npmjs.org/@backstage/version-bridge/-/version-bridge-0.1.2.tgz#a24f42e0f383d497576f8c9d43851c6538345c03"
+ integrity sha1-ok9C4POD1JdXb4ydQ4UcZTg0XAM=
+
"@balena/dockerignore@^1.0.2":
version "1.0.2"
resolved "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d"
@@ -6022,6 +6240,11 @@
resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
+"@types/event-source-polyfill@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/@types/event-source-polyfill/-/event-source-polyfill-1.0.0.tgz#f93f13433f750c8ea0e3cfa69c72e3c7393e0585"
+ integrity sha512-b8O8/rg7NIW0iJ8i9MNDBZqPljHA+b7AjC3QFqH3dSyW6vgrl3oBgyIv5dw2fibh5enHHDkkPZG5PHza7U4NRw==
+
"@types/expect@^1.20.4":
version "1.20.4"
resolved "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz#8288e51737bf7e3ab5d7c77bfa695883745264e5"
@@ -7857,7 +8080,7 @@ array-ify@^1.0.0:
resolved "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=
-array-includes@^3.1.3, array-includes@^3.1.4:
+array-includes@^3.1.2, array-includes@^3.1.3, array-includes@^3.1.4:
version "3.1.4"
resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9"
integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==
@@ -12111,6 +12334,11 @@ event-source-polyfill@1.0.25:
resolved "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.25.tgz#d8bb7f99cb6f8119c2baf086d9f6ee0514b6d9c8"
integrity sha512-hQxu6sN1Eq4JjoI7ITdQeGGUN193A2ra83qC0Ltm9I2UJVAten3OFVN6k5RX4YWeCS0BoC8xg/5czOCIHVosQg==
+event-source-polyfill@^1.0.25:
+ version "1.0.26"
+ resolved "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.26.tgz#86c04d088ef078279168eefa028f928fec5059a4"
+ integrity sha512-IwDLs9fUTcGAyacHBeS53T8wcEkDyDn0UP4tfQqJ4wQP8AyH0mszuQf2ULTylnpI0sMquzJ4usrNV7+uztwI9A==
+
event-stream@=3.3.4:
version "3.3.4"
resolved "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
@@ -16221,7 +16449,25 @@ jss@10.6.0, jss@^10.5.1:
is-in-browser "^1.1.3"
tiny-warning "^1.0.2"
-"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1:
+jss@~10.8.2:
+ version "10.8.2"
+ resolved "https://registry.npmjs.org/jss/-/jss-10.8.2.tgz#4b2a30b094b924629a64928236017a52c7c97505"
+ integrity sha512-FkoUNxI329CKQ9OQC8L72MBF9KPf5q8mIupAJ5twU7G7XREW7ahb+7jFfrjZ4iy1qvhx1HwIWUIvkZBDnKkEdQ==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ csstype "^3.0.2"
+ is-in-browser "^1.1.3"
+ tiny-warning "^1.0.2"
+
+"jsx-ast-utils@^2.4.1 || ^3.0.0":
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82"
+ integrity sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==
+ dependencies:
+ array-includes "^3.1.2"
+ object.assign "^4.1.2"
+
+jsx-ast-utils@^3.2.1:
version "3.2.1"
resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b"
integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==