docs(core): fix 500 error when directing from framework specific pages to intro page (#6492)
This commit is contained in:
parent
0bacdf3181
commit
59fa59fddc
@ -8,6 +8,10 @@ import {
|
|||||||
VersionMetadata,
|
VersionMetadata,
|
||||||
} from './documents.models';
|
} from './documents.models';
|
||||||
|
|
||||||
|
export interface StaticDocumentPaths {
|
||||||
|
params: { segments: string[] };
|
||||||
|
}
|
||||||
|
|
||||||
export const flavorList: {
|
export const flavorList: {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
@ -26,10 +30,16 @@ export class DocumentsApi {
|
|||||||
versions: VersionMetadata[];
|
versions: VersionMetadata[];
|
||||||
documentsMap: Map<string, DocumentMetadata[]>;
|
documentsMap: Map<string, DocumentMetadata[]>;
|
||||||
}
|
}
|
||||||
) {}
|
) {
|
||||||
|
if (!options.archiveRoot || !options.previewRoot) {
|
||||||
|
throw new Error('archive and preview roots cannot be undefined');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getDefaultVersion(): VersionMetadata {
|
getDefaultVersion(): VersionMetadata {
|
||||||
return this.options.versions.find((v) => v.default);
|
const found = this.options.versions.find((v) => v.default);
|
||||||
|
if (found) return found;
|
||||||
|
throw new Error('Cannot find default version');
|
||||||
}
|
}
|
||||||
|
|
||||||
getVersions(): VersionMetadata[] {
|
getVersions(): VersionMetadata[] {
|
||||||
@ -72,8 +82,8 @@ export class DocumentsApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getStaticDocumentPaths(version: string) {
|
getStaticDocumentPaths(version: string): StaticDocumentPaths[] {
|
||||||
const paths = [];
|
const paths: StaticDocumentPaths[] = [];
|
||||||
const defaultVersion = this.getDefaultVersion();
|
const defaultVersion = this.getDefaultVersion();
|
||||||
|
|
||||||
function recur(curr, acc) {
|
function recur(curr, acc) {
|
||||||
@ -111,11 +121,12 @@ export class DocumentsApi {
|
|||||||
return this.options.previewRoot;
|
return this.options.previewRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version === 'latest' || version === 'previous') {
|
const versionPath = this.options.versions.find(
|
||||||
return join(
|
(x) => x.id === version
|
||||||
this.options.archiveRoot,
|
)?.path;
|
||||||
this.options.versions.find((x) => x.id === version).path
|
|
||||||
);
|
if (versionPath) {
|
||||||
|
return join(this.options.archiveRoot, versionPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Cannot find root for ${version}`);
|
throw new Error(`Cannot find root for ${version}`);
|
||||||
@ -132,7 +143,7 @@ export class DocumentsApi {
|
|||||||
|
|
||||||
let found;
|
let found;
|
||||||
for (const part of path) {
|
for (const part of path) {
|
||||||
found = items.find((item) => item.id === part);
|
found = items?.find((item) => item.id === part);
|
||||||
if (found) {
|
if (found) {
|
||||||
items = found.itemList;
|
items = found.itemList;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
export function extractTitle(markdownContent: string): string | null {
|
export function extractTitle(markdownContent: string): string | null {
|
||||||
return (
|
return (
|
||||||
/^\s*#\s+(?<title>.+)[\n.]+/.exec(markdownContent)?.groups.title ?? null
|
/^\s*#\s+(?<title>.+)[\n.]+/.exec(markdownContent)?.groups?.title ?? null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ describe('MenuApi', () => {
|
|||||||
|
|
||||||
// first basic section item should have prefix by version and flavor
|
// first basic section item should have prefix by version and flavor
|
||||||
// e.g. "latest/react/getting-started/intro"
|
// e.g. "latest/react/getting-started/intro"
|
||||||
expect(menu.sections[0].itemList[0].itemList[0].path).toMatch(
|
expect(menu?.sections?.[0]?.itemList?.[0]?.itemList?.[0].path).toMatch(
|
||||||
/latest\/react/
|
/latest\/react/
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -23,12 +23,14 @@ export function createMenuItems(
|
|||||||
return pathData;
|
return pathData;
|
||||||
};
|
};
|
||||||
|
|
||||||
return items.map((item) => {
|
return (
|
||||||
|
items?.map((item) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
itemList: item.itemList?.map((ii) => createPathMetadata(ii, item.id)),
|
itemList: item.itemList?.map((ii) => createPathMetadata(ii, item.id)),
|
||||||
};
|
};
|
||||||
});
|
}) ?? []
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBasicSection(items: MenuItem[]): MenuSection {
|
export function getBasicSection(items: MenuItem[]): MenuSection {
|
||||||
@ -73,7 +75,7 @@ export function getDeepDiveSection(items: MenuItem[]): MenuSection {
|
|||||||
.map((m) => ({
|
.map((m) => ({
|
||||||
...m,
|
...m,
|
||||||
disableCollapsible: true,
|
disableCollapsible: true,
|
||||||
itemList: m.itemList.map((item) => ({
|
itemList: m.itemList?.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
disableCollapsible: true,
|
disableCollapsible: true,
|
||||||
})),
|
})),
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.base.json",
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"strictNullChecks": true
|
||||||
|
},
|
||||||
"files": [],
|
"files": [],
|
||||||
"include": [],
|
"include": [],
|
||||||
"references": [
|
"references": [
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
"allowSyntheticDefaultImports": true
|
"allowSyntheticDefaultImports": true
|
||||||
},
|
},
|
||||||
"files": [],
|
"files": [],
|
||||||
|
|||||||
@ -7,6 +7,8 @@ describe('Content', () => {
|
|||||||
it('should render successfully', () => {
|
it('should render successfully', () => {
|
||||||
const { baseElement } = render(
|
const { baseElement } = render(
|
||||||
<Content
|
<Content
|
||||||
|
versionList={[]}
|
||||||
|
flavorList={[]}
|
||||||
version="1.0.0"
|
version="1.0.0"
|
||||||
flavor="react"
|
flavor="react"
|
||||||
document={{
|
document={{
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export interface DocumentationFeatureDocViewerProps {
|
|||||||
menu: Menu;
|
menu: Menu;
|
||||||
document: DocumentData;
|
document: DocumentData;
|
||||||
toc: any;
|
toc: any;
|
||||||
navIsOpen: boolean;
|
navIsOpen?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DocViewer({
|
export function DocViewer({
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export interface SidebarProps {
|
|||||||
versionList: VersionMetadata[];
|
versionList: VersionMetadata[];
|
||||||
flavorList: any[];
|
flavorList: any[];
|
||||||
flavor: any;
|
flavor: any;
|
||||||
navIsOpen: boolean;
|
navIsOpen?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exported for testing
|
// Exported for testing
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
"allowSyntheticDefaultImports": true
|
"allowSyntheticDefaultImports": true
|
||||||
},
|
},
|
||||||
"files": [],
|
"files": [],
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export function AlgoliaSearch({ flavorId, versionId }: AlgoliaSearchProps) {
|
|||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const searchButtonRef = useRef();
|
const searchButtonRef = useRef<HTMLButtonElement>(null);
|
||||||
const [initialQuery, setInitialQuery] = useState(null);
|
const [initialQuery, setInitialQuery] = useState(null);
|
||||||
const [browserDetected, setBrowserDetected] = useState(false);
|
const [browserDetected, setBrowserDetected] = useState(false);
|
||||||
const [actionKey, setActionKey] = useState(ACTION_KEY_DEFAULT);
|
const [actionKey, setActionKey] = useState(ACTION_KEY_DEFAULT);
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
"allowSyntheticDefaultImports": true
|
"allowSyntheticDefaultImports": true
|
||||||
},
|
},
|
||||||
"files": [],
|
"files": [],
|
||||||
|
|||||||
@ -5,7 +5,7 @@ const isServer = typeof window === 'undefined';
|
|||||||
export function useStorage(key: string) {
|
export function useStorage(key: string) {
|
||||||
const initialValue = isServer ? undefined : window.localStorage.getItem(key);
|
const initialValue = isServer ? undefined : window.localStorage.getItem(key);
|
||||||
|
|
||||||
const [value, _setValue] = useState<string>(initialValue);
|
const [value, _setValue] = useState<string>(initialValue ?? '');
|
||||||
|
|
||||||
const setValue = (newValue: string) => {
|
const setValue = (newValue: string) => {
|
||||||
if (newValue !== value && !isServer) {
|
if (newValue !== value && !isServer) {
|
||||||
|
|||||||
@ -17,8 +17,11 @@ import { documentsApi, menuApi } from '../lib/api';
|
|||||||
import { useStorage } from '../lib/use-storage';
|
import { useStorage } from '../lib/use-storage';
|
||||||
|
|
||||||
const versionList = documentsApi.getVersions();
|
const versionList = documentsApi.getVersions();
|
||||||
const defaultVersion = versionList.find((v) => v.default);
|
const defaultVersion = versionList.find((v) => v.default) as VersionMetadata;
|
||||||
const defaultFlavor = flavorList.find((f) => f.default);
|
const defaultFlavor = flavorList.find((f) => f.default) as {
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
};
|
||||||
|
|
||||||
interface DocumentationPageProps {
|
interface DocumentationPageProps {
|
||||||
version: VersionMetadata;
|
version: VersionMetadata;
|
||||||
@ -277,12 +280,16 @@ function findDocumentAndMenu(
|
|||||||
version: VersionMetadata,
|
version: VersionMetadata,
|
||||||
flavor: { label: string; value: string },
|
flavor: { label: string; value: string },
|
||||||
segments: string[]
|
segments: string[]
|
||||||
): { menu?: Menu; document?: DocumentData; isFallback?: boolean } {
|
): {
|
||||||
|
menu: undefined | Menu;
|
||||||
|
document: undefined | DocumentData;
|
||||||
|
isFallback?: boolean;
|
||||||
|
} {
|
||||||
const isFallback = segments[0] !== version.id;
|
const isFallback = segments[0] !== version.id;
|
||||||
const path = isFallback ? segments : segments.slice(2);
|
const path = isFallback ? segments : segments.slice(2);
|
||||||
|
|
||||||
let menu: Menu;
|
let menu: undefined | Menu = undefined;
|
||||||
let document: DocumentData;
|
let document: undefined | DocumentData = undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
menu = menuApi.getMenu(version.id, flavor.value);
|
menu = menuApi.getMenu(version.id, flavor.value);
|
||||||
|
|||||||
@ -9,7 +9,8 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true
|
"isolatedModules": true,
|
||||||
|
"strictNullChecks": true
|
||||||
},
|
},
|
||||||
"files": [],
|
"files": [],
|
||||||
"include": [],
|
"include": [],
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import cx from 'classnames';
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
export interface FooterProps {
|
export interface FooterProps {
|
||||||
useDarkBackground: boolean;
|
useDarkBackground?: boolean;
|
||||||
}
|
}
|
||||||
export function Footer({ useDarkBackground }: FooterProps) {
|
export function Footer({ useDarkBackground }: FooterProps) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -4,12 +4,12 @@ import { AlgoliaSearch } from '@nrwl/nx-dev/feature-search';
|
|||||||
|
|
||||||
interface HeaderPropsWithoutFlavorAndVersion {
|
interface HeaderPropsWithoutFlavorAndVersion {
|
||||||
showSearch: false;
|
showSearch: false;
|
||||||
useDarkBackground: boolean;
|
useDarkBackground?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HeaderPropsWithFlavorAndVersion {
|
interface HeaderPropsWithFlavorAndVersion {
|
||||||
showSearch: boolean;
|
showSearch: boolean;
|
||||||
useDarkBackground: boolean;
|
useDarkBackground?: boolean;
|
||||||
flavor: { name: string; value: string };
|
flavor: { name: string; value: string };
|
||||||
version: { name: string; value: string };
|
version: { name: string; value: string };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
"allowSyntheticDefaultImports": true
|
"allowSyntheticDefaultImports": true
|
||||||
},
|
},
|
||||||
"files": [],
|
"files": [],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user