techdocs: set custom docStorageUrl via appConfig (#1575)
* feat(techdocs): read docStorageUrl from appConfig * docs: updated techdocs plugin README to mention custom baseurl * fix: added config file * fix: use JSON in env variable * fix: add to app-config.yaml * typescript wrestling * Nicer config handling * fix: switch to using useApi(configApiRef) * docs: corrected to new config name * docs: mention app-config.yaml config option * fix: removed unused dep @backstage/config Co-authored-by: Sebastian Qvarfordt <s.qvarfordt@gmail.com>
This commit is contained in:
@@ -12,3 +12,6 @@ backend:
|
||||
|
||||
organization:
|
||||
name: Spotify
|
||||
|
||||
techdocs:
|
||||
storageUrl: https://techdocs-mock-sites.storage.googleapis.com
|
||||
|
||||
@@ -15,3 +15,35 @@ Your plugin has been added to the example app in this repository, meaning you'll
|
||||
You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
|
||||
This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
|
||||
It is only meant for local development, and the setup for it can be found inside the [/dev](/dev) directory.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Custom Storage URL
|
||||
|
||||
TechDocs currently reads a static HTML file, generated by Mkdocs (see our `plugins/techdocs/mkdocs/container` folder for more documentation) and stored on an external server, and loads that into Backstage. By default, we have set up a mock server with some example documentation sites over in Google Cloud Storage:
|
||||
|
||||
```md
|
||||
# Base URL
|
||||
|
||||
https://techdocs-mock-sites.storage.googleapis.com
|
||||
|
||||
# Home Page for the "mkdocs" docs
|
||||
|
||||
https://techdocs-mock-sites.storage.googleapis.com/mkdocs/index.html
|
||||
|
||||
# Home Page for the "backstage-microsite" docs
|
||||
|
||||
https://techdocs-mock-sites.storage.googleapis.com/backstage-microsite/index.html
|
||||
```
|
||||
|
||||
Using your own setup (or ours which is being worked on as of Q3 2020), you can point it to your own server with your own hosted documentation sites. The only requirement is that it the output is from [Mkdocs](https://mkdocs.org) with the Material theme. You can always use our documentation generation tool located at `plugins/techdocs/mkdocs/container` for easy setup.
|
||||
|
||||
To point TechDocs to your own server, simply update the `techdocs.storageUrl` value in your `app-config.yaml` file or set the environment variable `APP_CONFIG_techdocs_storageUrl` in your application:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:spotify/backstage.git
|
||||
cd backstage/
|
||||
yarn install
|
||||
export APP_CONFIG_techdocs_storageUrl='"http://example-docs-site-server.com"'
|
||||
yarn start
|
||||
```
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
export const docStorageURL =
|
||||
'https://techdocs-mock-sites.storage.googleapis.com';
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { useApi, configApiRef } from '@backstage/core';
|
||||
import { useShadowDom } from '..';
|
||||
import { useAsync } from 'react-use';
|
||||
import { AsyncState } from 'react-use/lib/useAsync';
|
||||
@@ -30,7 +31,6 @@ import transformer, {
|
||||
onCssReady,
|
||||
sanitizeDOM,
|
||||
} from '../transformers';
|
||||
import { docStorageURL } from '../../config';
|
||||
import URLFormatter from '../urlFormatter';
|
||||
import { TechDocsNotFound } from './TechDocsNotFound';
|
||||
import { TechDocsPageWrapper } from './TechDocsPageWrapper';
|
||||
@@ -69,12 +69,16 @@ const useEnforcedTrailingSlash = (): void => {
|
||||
export const Reader = () => {
|
||||
useEnforcedTrailingSlash();
|
||||
|
||||
const docStorageUrl =
|
||||
useApi(configApiRef).getOptionalString('techdocs.storageUrl') ??
|
||||
'https://techdocs-mock-sites.storage.googleapis.com';
|
||||
|
||||
const location = useLocation();
|
||||
const { componentId, '*': path } = useParams();
|
||||
const [shadowDomRef, shadowRoot] = useShadowDom();
|
||||
const navigate = useNavigate();
|
||||
const normalizedUrl = new URLFormatter(
|
||||
`${docStorageURL}${location.pathname.replace('/docs', '')}`,
|
||||
`${docStorageUrl}${location.pathname.replace('/docs', '')}`,
|
||||
).formatBaseURL();
|
||||
const state = useFetch(`${normalizedUrl}index.html`);
|
||||
|
||||
@@ -91,7 +95,7 @@ export const Reader = () => {
|
||||
const transformedElement = transformer(state.value as string, [
|
||||
sanitizeDOM(),
|
||||
addBaseUrl({
|
||||
docStorageURL,
|
||||
docStorageUrl,
|
||||
componentId,
|
||||
path,
|
||||
}),
|
||||
@@ -137,7 +141,7 @@ export const Reader = () => {
|
||||
},
|
||||
}),
|
||||
onCssReady({
|
||||
docStorageURL,
|
||||
docStorageUrl,
|
||||
onLoading: (dom: Element) => {
|
||||
(dom as HTMLElement).style.setProperty('opacity', '0');
|
||||
},
|
||||
|
||||
@@ -41,7 +41,7 @@ describe('addBaseUrl', () => {
|
||||
const shadowDom = createTestShadowDom(FIXTURES.FIXTURE_STANDARD_PAGE, {
|
||||
preTransformers: [
|
||||
addBaseUrl({
|
||||
docStorageURL: DOC_STORAGE_URL,
|
||||
docStorageUrl: DOC_STORAGE_URL,
|
||||
componentId: 'example-docs',
|
||||
path: '',
|
||||
}),
|
||||
@@ -76,7 +76,7 @@ describe('addBaseUrl', () => {
|
||||
{
|
||||
preTransformers: [
|
||||
addBaseUrl({
|
||||
docStorageURL: DOC_STORAGE_URL,
|
||||
docStorageUrl: DOC_STORAGE_URL,
|
||||
componentId: 'example-docs',
|
||||
path: 'examplepath',
|
||||
}),
|
||||
@@ -112,7 +112,7 @@ describe('addBaseUrl', () => {
|
||||
{
|
||||
preTransformers: [
|
||||
addBaseUrl({
|
||||
docStorageURL: DOC_STORAGE_URL,
|
||||
docStorageUrl: DOC_STORAGE_URL,
|
||||
componentId: 'example-docs',
|
||||
path: 'examplepath/',
|
||||
}),
|
||||
|
||||
@@ -18,13 +18,13 @@ import URLFormatter from '../urlFormatter';
|
||||
import type { Transformer } from './index';
|
||||
|
||||
type AddBaseUrlOptions = {
|
||||
docStorageURL: string;
|
||||
docStorageUrl: string;
|
||||
componentId: string;
|
||||
path: string;
|
||||
};
|
||||
|
||||
export const addBaseUrl = ({
|
||||
docStorageURL,
|
||||
docStorageUrl,
|
||||
componentId,
|
||||
path,
|
||||
}: AddBaseUrlOptions): Transformer => {
|
||||
@@ -38,8 +38,8 @@ export const addBaseUrl = ({
|
||||
.forEach((elem: T) => {
|
||||
const urlFormatter = new URLFormatter(
|
||||
path.length < 1 || path.endsWith('/')
|
||||
? `${docStorageURL}/${componentId}/${path}`
|
||||
: `${docStorageURL}/${componentId}/${path}/`,
|
||||
? `${docStorageUrl}/${componentId}/${path}`
|
||||
: `${docStorageUrl}/${componentId}/${path}/`,
|
||||
);
|
||||
|
||||
elem.setAttribute(
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
} from '../../test-utils';
|
||||
import { addBaseUrl, onCssReady } from '../transformers';
|
||||
|
||||
const docStorageURL: string =
|
||||
const docStorageUrl: string =
|
||||
'https://techdocs-mock-sites.storage.googleapis.com';
|
||||
|
||||
jest.useFakeTimers();
|
||||
@@ -45,7 +45,7 @@ describe('onCssReady', () => {
|
||||
preTransformers: [],
|
||||
postTransformers: [
|
||||
onCssReady({
|
||||
docStorageURL,
|
||||
docStorageUrl,
|
||||
onLoading,
|
||||
onLoaded,
|
||||
}),
|
||||
@@ -65,12 +65,12 @@ describe('onCssReady', () => {
|
||||
preTransformers: [],
|
||||
postTransformers: [
|
||||
addBaseUrl({
|
||||
docStorageURL,
|
||||
docStorageUrl,
|
||||
componentId: 'mkdocs',
|
||||
path: '',
|
||||
}),
|
||||
onCssReady({
|
||||
docStorageURL,
|
||||
docStorageUrl,
|
||||
onLoading,
|
||||
onLoaded,
|
||||
}),
|
||||
|
||||
@@ -17,20 +17,20 @@
|
||||
import type { Transformer } from './index';
|
||||
|
||||
type OnCssReadyOptions = {
|
||||
docStorageURL: string;
|
||||
docStorageUrl: string;
|
||||
onLoading: (dom: Element) => void;
|
||||
onLoaded: (dom: Element) => void;
|
||||
};
|
||||
|
||||
export const onCssReady = ({
|
||||
docStorageURL,
|
||||
docStorageUrl,
|
||||
onLoading,
|
||||
onLoaded,
|
||||
}: OnCssReadyOptions): Transformer => {
|
||||
return dom => {
|
||||
const cssPages = Array.from(
|
||||
dom.querySelectorAll('head > link[rel="stylesheet"]'),
|
||||
).filter(elem => elem.getAttribute('href')?.startsWith(docStorageURL));
|
||||
).filter(elem => elem.getAttribute('href')?.startsWith(docStorageUrl));
|
||||
|
||||
let count = cssPages.length;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user