Cleanups and better navigation between docs
This commit is contained in:
@@ -17,10 +17,14 @@
|
||||
import React from 'react';
|
||||
import { useShadowDom } from '..';
|
||||
import { useAsync } from 'react-use';
|
||||
import transformer, { addBaseUrl, rewriteDocLinks } from '../transformers';
|
||||
import transformer, {
|
||||
addBaseUrl,
|
||||
rewriteDocLinks,
|
||||
addEventListener,
|
||||
} from '../transformers';
|
||||
import { docStorageURL } from '../../config';
|
||||
import { Link } from '@backstage/core';
|
||||
import { useLocation, useParams } from 'react-router-dom';
|
||||
import { useLocation, useParams, useNavigate } from 'react-router-dom';
|
||||
import URLParser from '../urlParser';
|
||||
|
||||
const useFetch = (url: string) => {
|
||||
@@ -33,10 +37,6 @@ const useFetch = (url: string) => {
|
||||
return state;
|
||||
};
|
||||
|
||||
const normalizeUrl = (path: string) => {
|
||||
return path.replace(/\/\/index.html$/, '/index.html');
|
||||
};
|
||||
|
||||
const useEnforcedTrailingSlash = (): void => {
|
||||
React.useEffect(() => {
|
||||
const actualUrl = window.location.href;
|
||||
@@ -52,11 +52,12 @@ export const Reader = () => {
|
||||
const location = useLocation();
|
||||
const { componentId, '*': path } = useParams();
|
||||
const shadowDomRef = useShadowDom();
|
||||
const state = useFetch(
|
||||
normalizeUrl(
|
||||
`${docStorageURL}${location.pathname.replace('/docs', '')}/index.html`,
|
||||
),
|
||||
);
|
||||
const navigate = useNavigate();
|
||||
const normalizedUrl = new URLParser(
|
||||
`${docStorageURL}${location.pathname.replace('/docs', '')}`,
|
||||
'.',
|
||||
).parse();
|
||||
const state = useFetch(`${normalizedUrl}index.html`);
|
||||
|
||||
useEnforcedTrailingSlash();
|
||||
|
||||
@@ -75,10 +76,16 @@ export const Reader = () => {
|
||||
]);
|
||||
|
||||
divElement.shadowRoot.innerHTML = '';
|
||||
if (transformedElement)
|
||||
if (transformedElement) {
|
||||
divElement.shadowRoot.appendChild(transformedElement);
|
||||
transformer(divElement.shadowRoot.children[0], [
|
||||
addEventListener({
|
||||
onClick: navigate,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}, [shadowDomRef, state, componentId, path]);
|
||||
}, [shadowDomRef, state, componentId, path, navigate]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import URLParser from '../urlParser';
|
||||
import type { Transformer } from './index';
|
||||
|
||||
type AddBaseUrlOptions = {
|
||||
docStorageURL: string;
|
||||
@@ -26,10 +27,10 @@ export const addBaseUrl = ({
|
||||
docStorageURL,
|
||||
componentId,
|
||||
path,
|
||||
}: AddBaseUrlOptions) => {
|
||||
return (dom: Document): Document => {
|
||||
}: AddBaseUrlOptions): Transformer => {
|
||||
return dom => {
|
||||
const updateDom = <T extends Element>(
|
||||
list: Array<T>,
|
||||
list: HTMLCollectionOf<T> | NodeListOf<T>,
|
||||
attributeName: string,
|
||||
): void => {
|
||||
Array.from(list)
|
||||
@@ -43,12 +44,9 @@ export const addBaseUrl = ({
|
||||
});
|
||||
};
|
||||
|
||||
updateDom<HTMLImageElement>(Array.from(dom.images), 'src');
|
||||
updateDom<HTMLScriptElement>(Array.from(dom.scripts), 'src');
|
||||
updateDom<HTMLLinkElement>(
|
||||
Array.from(dom.querySelectorAll('link')),
|
||||
'href',
|
||||
);
|
||||
updateDom<HTMLImageElement>(dom.querySelectorAll('img'), 'src');
|
||||
updateDom<HTMLScriptElement>(dom.querySelectorAll('script'), 'src');
|
||||
updateDom<HTMLLinkElement>(dom.querySelectorAll('link'), 'href');
|
||||
|
||||
return dom;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 AddEventListenerOptions = {
|
||||
onClick: (newUrl: string) => void;
|
||||
};
|
||||
|
||||
export const addEventListener = ({
|
||||
onClick,
|
||||
}: AddEventListenerOptions): Transformer => {
|
||||
return dom => {
|
||||
Array.from(dom.getElementsByTagName('a')).forEach(elem => {
|
||||
elem.addEventListener('click', (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
const target = e.target as HTMLAnchorElement;
|
||||
if (target?.getAttribute('href')) {
|
||||
onClick(
|
||||
target.getAttribute('href')!.replace(window.location.origin, ''),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return dom;
|
||||
};
|
||||
};
|
||||
@@ -16,16 +16,48 @@
|
||||
|
||||
export * from './addBaseUrl';
|
||||
export * from './rewriteDocLinks';
|
||||
export * from './addEventListener';
|
||||
|
||||
type Transformer = (dom: Document) => Document;
|
||||
export type Transformer = (dom: Element) => Element;
|
||||
|
||||
export default (
|
||||
html: string,
|
||||
function transform(
|
||||
html: string | Element,
|
||||
transformers: Transformer[],
|
||||
): HTMLElement | undefined => {
|
||||
const dom = new DOMParser().parseFromString(html, 'text/html');
|
||||
): Element {
|
||||
let dom: Element;
|
||||
|
||||
if (typeof html === 'string') {
|
||||
dom = new DOMParser().parseFromString(html, 'text/html').documentElement;
|
||||
} else if (html instanceof Element) {
|
||||
dom = html;
|
||||
} else {
|
||||
throw new Error('dom is not a recognized type');
|
||||
}
|
||||
|
||||
transformers.forEach(transformer => transformer(dom));
|
||||
|
||||
return dom.body.parentElement ?? undefined;
|
||||
};
|
||||
return dom;
|
||||
}
|
||||
|
||||
// function transform(
|
||||
// html: string,
|
||||
// transformers: Transformer[],
|
||||
// ): HTMLElement {
|
||||
// const dom = new DOMParser().parseFromString(html, 'text/html');
|
||||
|
||||
// transformers.forEach(transformer => transformer(dom));
|
||||
|
||||
// return dom.documentElement;
|
||||
// };
|
||||
|
||||
// function transform(
|
||||
// html: HTMLElement,
|
||||
// transformers: Transformer[],
|
||||
// ): HTMLElement {
|
||||
|
||||
// transformers.forEach(transformer => transformer(element));
|
||||
|
||||
// return html;
|
||||
// };
|
||||
|
||||
export default transform;
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
*/
|
||||
|
||||
import URLParser from '../urlParser';
|
||||
import type { Transformer } from './index';
|
||||
|
||||
type AddBaseUrlOptions = {};
|
||||
|
||||
export const rewriteDocLinks = ({}: AddBaseUrlOptions) => {
|
||||
return (dom: Document): Document => {
|
||||
export const rewriteDocLinks = ({}: AddBaseUrlOptions): Transformer => {
|
||||
return dom => {
|
||||
const updateDom = <T extends Element>(
|
||||
list: Array<T>,
|
||||
attributeName: string,
|
||||
|
||||
Reference in New Issue
Block a user