docs(nxdev): extract schema list components (#13917)

This commit is contained in:
Benjamin Cabanes 2022-12-19 18:41:03 -05:00 committed by GitHub
parent 37dc336a0a
commit 6718bf2a84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 533 additions and 81 deletions

View File

@ -6,9 +6,10 @@ import { Breadcrumbs, Footer } from '@nrwl/nx-dev/ui-common';
import { renderMarkdown } from '@nrwl/nx-dev/ui-markdoc';
import { NextSeo } from 'next-seo';
import { useRouter } from 'next/router';
import { ReactNode } from 'react';
import { Heading1 } from './ui/headings';
import { PackageReference } from './ui/package-reference';
import React, { ReactNode } from 'react';
import { Heading1, Heading2 } from './ui/headings';
import { DocumentList, SchemaList } from './ui/package-reference';
import { TopSchemaLayout } from './ui/top.layout';
export function PackageSchemaList({
overview,
@ -74,39 +75,7 @@ export function PackageSchemaList({
<Breadcrumbs path={router.asPath} />
</div>
<div data-document="main">
<div className="mb-8 flex w-full items-center space-x-2">
<div className="w-full flex-grow">
<div
className="relative inline-flex rounded-md border border-slate-200 bg-slate-50 px-4 py-2 text-xs font-medium uppercase dark:border-slate-700 dark:bg-slate-800/60"
aria-hidden="true"
data-tooltip="Installable package"
>
Package
</div>
</div>
<div className="relative z-0 inline-flex flex-shrink-0">
<a
href={vm.githubUrl}
target="_blank"
rel="noreferrer"
aria-hidden="true"
title="See package on Github"
className="relative inline-flex items-center rounded-md border border-slate-200 bg-slate-50 px-4 py-2 text-xs font-medium dark:border-slate-700 dark:bg-slate-800/60"
>
<svg
className="mr-2 h-4 w-4"
viewBox="0 0 16 16"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
{vm.package.packageName}
</a>
</div>
</div>
<TopSchemaLayout name={vm.package.packageName} url={vm.githubUrl} />
<Heading1 title={vm.package.packageName} />
@ -114,11 +83,23 @@ export function PackageSchemaList({
{vm.markdown}
</div>
<PackageReference
documents={vm.package.documents}
executors={vm.package.executors}
generators={vm.package.generators}
/>
<Heading2 title="Package reference" />
<p className="mb-16">
Here is a list of all the executors and generators available from
this package.
</p>
<Heading2 title={'Guides'} />
<DocumentList documents={vm.package.documents} />
<div className="h-12">{/* SPACER */}</div>
<Heading2 title={'Executors'} />
<SchemaList files={vm.package.executors} type={'executor'} />
<div className="h-12">{/* SPACER */}</div>
<Heading2 title={'Generators'} />
<SchemaList files={vm.package.generators} type={'generator'} />
</div>
</div>
</div>

View File

@ -0,0 +1,112 @@
import {
PackageMetadata,
ProcessedPackageMetadata,
} from '@nrwl/nx-dev/models-package';
import { Breadcrumbs, Footer } from '@nrwl/nx-dev/ui-common';
import { NextSeo } from 'next-seo';
import { useRouter } from 'next/router';
import React from 'react';
import { Heading1, Heading2 } from './ui/headings';
import { DocumentList, SchemaList } from './ui/package-reference';
import { TopSchemaLayout } from './ui/top.layout';
export function PackageSchemaSubList({
type,
pkg,
}: {
type: 'document' | 'executor' | 'generator';
pkg: ProcessedPackageMetadata;
}): JSX.Element {
const router = useRouter();
const capitalize = (text: string): string =>
text.charAt(0).toUpperCase() + text.slice(1);
const vm: {
package: PackageMetadata;
githubUrl: string;
seo: { title: string; description: string; url: string; imageUrl: string };
type: 'document' | 'executor' | 'generator';
heading: string;
} = {
package: {
...pkg,
documents: Object.keys(pkg.documents)
.map((k) => pkg.documents[k])
.filter((d) => d.id !== 'overview'),
executors: Object.keys(pkg.executors).map((k) => pkg.executors[k]),
generators: Object.keys(pkg.generators).map((k) => pkg.generators[k]),
},
githubUrl: pkg.githubRoot + pkg.root,
seo: {
title: `${pkg.packageName} | Nx`,
description: pkg.description,
imageUrl: `https://nx.dev/images/open-graph/${router.asPath
.replace('/', '')
.replace(/\//gi, '-')}.jpg`,
url: 'https://nx.dev' + router.asPath,
},
type,
heading: capitalize(type) + ' References',
};
return (
<>
<NextSeo
title={vm.seo.title}
openGraph={{
url: vm.seo.url,
title: vm.seo.title,
description: vm.seo.description,
images: [
{
url: vm.seo.imageUrl,
width: 1600,
height: 800,
alt: 'Nx: Smart, Fast and Extensible Build System',
type: 'image/jpeg',
},
],
site_name: 'Nx',
type: 'website',
}}
/>
<div className="mx-auto w-full grow items-stretch px-4 pb-12 sm:px-6 lg:px-8 2xl:max-w-6xl">
<div id="content-wrapper" className="w-full flex-auto flex-col">
<div className="mb-6 pt-8">
<Breadcrumbs path={router.asPath} />
</div>
<div data-document="main">
<TopSchemaLayout name={vm.package.packageName} url={vm.githubUrl} />
<Heading1 title={vm.package.packageName} />
<Heading2 title={vm.heading} />
<p className="mb-16">
Here is a list of all {vm.type} available for this package.
</p>
{vm.type === 'document' ? (
<>
<DocumentList documents={vm.package.documents} />
</>
) : null}
{vm.type === 'executor' ? (
<>
<SchemaList files={vm.package.executors} type={'executor'} />
</>
) : null}
{vm.type === 'generator' ? (
<>
<SchemaList files={vm.package.generators} type={'generator'} />
</>
) : null}
</div>
</div>
</div>
<Footer />
</>
);
}

View File

@ -9,57 +9,32 @@ import { FileMetadata } from '@nrwl/nx-dev/models-package';
import { renderMarkdown } from '@nrwl/nx-dev/ui-markdoc';
import Link from 'next/link';
import React from 'react';
import { Heading2 } from './headings';
export function PackageReference({
executors,
generators,
export function DocumentList({
documents,
}: {
executors: FileMetadata[];
generators: FileMetadata[];
documents: DocumentMetadata[];
}): JSX.Element {
return (
<>
<Heading2 title="Package reference" />
<p className="mb-16">
Here is a list of all the executors and generators available from this
package.
</p>
<Heading2 title={'Guides'} />
<ul className="divide-y divide-slate-100 dark:divide-slate-800">
{!!documents.length &&
{!!documents.length ? (
documents.map((guide) => (
<DocumentListItem key={guide.id} document={guide} />
))}
{!documents.length && <EmptyList type="guides" />}
</ul>
<div className="h-12">{/* SPACER */}</div>
<Heading2 title={'Executors'} />
<ul className="divide-y divide-slate-100 dark:divide-slate-800">
{executors.map((executor) => (
<SchemaListItem key={executor.name} file={executor} />
))}
{executors.length === 0 && <EmptyList type="executor" />}
</ul>
<div className="h-12">{/* SPACER */}</div>
<Heading2 title={'Generators'} />
<ul className="divide-y divide-slate-100 dark:divide-slate-800">
{generators.map((generator) => (
<SchemaListItem key={generator.name} file={generator} />
))}
{generators.length === 0 && <EmptyList type="generator" />}
))
) : (
<EmptyList type="document" />
)}
</ul>
</>
);
}
function DocumentListItem({ document }: { document: DocumentMetadata }) {
function DocumentListItem({
document,
}: {
document: DocumentMetadata;
}): JSX.Element {
return (
<li
key={document.name}
@ -80,6 +55,28 @@ function DocumentListItem({ document }: { document: DocumentMetadata }) {
);
}
export function SchemaList({
files,
type,
}: {
files: FileMetadata[];
type: 'executor' | 'generator';
}): JSX.Element {
return (
<>
<ul className="divide-y divide-slate-100 dark:divide-slate-800">
{!!files.length ? (
files.map((schema) => (
<SchemaListItem key={schema.name} file={schema} />
))
) : (
<EmptyList type={type} />
)}
</ul>
</>
);
}
function SchemaListItem({ file }: { file: FileMetadata }): JSX.Element {
return (
<li
@ -121,7 +118,7 @@ function SchemaListItem({ file }: { file: FileMetadata }): JSX.Element {
function EmptyList({
type,
}: {
type: 'executor' | 'generator' | 'guides';
type: 'executor' | 'generator' | 'document';
}): JSX.Element {
return (
<li className="relative flex px-2 py-2 transition focus-within:ring-2 focus-within:ring-blue-500 focus-within:ring-offset-2 hover:bg-slate-50 dark:focus-within:ring-sky-500 dark:hover:bg-slate-800/60">

View File

@ -0,0 +1,39 @@
export function TopSchemaLayout({
name,
url,
}: {
name: string;
url: string;
}): JSX.Element {
return (
<div className="mb-8 flex w-full items-center space-x-2">
<div className="w-full flex-grow">
<div
className="relative inline-flex rounded-md border border-slate-200 bg-slate-50 px-4 py-2 text-xs font-medium uppercase dark:border-slate-700 dark:bg-slate-800/60"
aria-hidden="true"
data-tooltip="Installable package"
>
Package
</div>
</div>
<div className="relative z-0 inline-flex flex-shrink-0">
<a
href={url}
target="_blank"
rel="noreferrer"
aria-hidden="true"
title="See package on Github"
className="relative inline-flex items-center rounded-md border border-slate-200 bg-slate-50 px-4 py-2 text-xs font-medium dark:border-slate-700 dark:bg-slate-800/60"
>
<svg className="mr-2 h-4 w-4" viewBox="0 0 16 16" fill="currentColor">
<path
fillRule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
{name}
</a>
</div>
</div>
);
}

View File

@ -0,0 +1,109 @@
import { PackageSchemaList } from '@nrwl/nx-dev-feature-package-schema-viewer';
import { getPackagesSections } from '@nrwl/nx-dev/data-access-menu';
import { sortCorePackagesFirst } from '@nrwl/nx-dev/data-access-packages';
import { Menu, MenuItem, MenuSection } from '@nrwl/nx-dev/models-menu';
import { ProcessedPackageMetadata } from '@nrwl/nx-dev/models-package';
import { DocumentationHeader, SidebarContainer } from '@nrwl/nx-dev/ui-common';
import { GetStaticPaths } from 'next';
import { useRouter } from 'next/router';
import { useEffect, useRef } from 'react';
import { PackageSchemaSubList } from '../../../../../feature-package-schema-viewer/src/lib/package-schema-sub-list';
import { menusApi } from '../../../../lib/menus.api';
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
import { nxPackagesApi } from '../../../../lib/packages.api';
export default function DocumentsIndex({
menu,
pkg,
}: {
menu: MenuItem[];
pkg: ProcessedPackageMetadata;
}): JSX.Element {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
const wrapperElement = useRef(null);
useEffect(() => {
const handleRouteChange = (url: string) => {
if (url.includes('#')) return;
if (!wrapperElement) return;
(wrapperElement as any).current.scrollTo({
top: 0,
left: 0,
behavior: 'smooth',
});
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => router.events.off('routeChangeComplete', handleRouteChange);
}, [router, wrapperElement]);
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
menu: {
sections: sortCorePackagesFirst<MenuSection>(
getPackagesSections(menu),
'id'
),
},
package: pkg,
};
/**
* Show either the docviewer or the package view depending on:
* - docviewer: it is a documentation document
* - packageviewer: it is package generated documentation
*/
return (
<div id="shell" className="flex h-full flex-col">
<div className="w-full flex-shrink-0">
<DocumentationHeader isNavOpen={navIsOpen} toggleNav={toggleNav} />
</div>
<main
id="main"
role="main"
className="flex h-full flex-1 overflow-y-hidden"
>
<SidebarContainer menu={vm.menu} navIsOpen={navIsOpen} />
<div
ref={wrapperElement}
id="wrapper"
data-testid="wrapper"
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
>
<PackageSchemaSubList pkg={vm.package} type={'document'} />
</div>
</main>
</div>
);
}
export const getStaticPaths: GetStaticPaths = () => {
return {
paths: [
...nxPackagesApi.getStaticDocumentPaths().packages.map((x) => ({
params: { name: x.params.segments.slice(1)[0] },
})),
],
fallback: 'blocking',
};
};
export async function getStaticProps({
params,
}: {
params: { name: string };
}): Promise<{
props: {
menu: MenuItem[];
pkg: ProcessedPackageMetadata;
};
}> {
const pkg = nxPackagesApi.getPackage([params.name]);
return {
props: {
menu: menusApi.getMenu('packages', 'packages'),
pkg,
},
};
}

View File

@ -0,0 +1,108 @@
import { getPackagesSections } from '@nrwl/nx-dev/data-access-menu';
import { sortCorePackagesFirst } from '@nrwl/nx-dev/data-access-packages';
import { Menu, MenuItem, MenuSection } from '@nrwl/nx-dev/models-menu';
import { ProcessedPackageMetadata } from '@nrwl/nx-dev/models-package';
import { DocumentationHeader, SidebarContainer } from '@nrwl/nx-dev/ui-common';
import { GetStaticPaths } from 'next';
import { useRouter } from 'next/router';
import { useEffect, useRef } from 'react';
import { PackageSchemaSubList } from '../../../../../feature-package-schema-viewer/src/lib/package-schema-sub-list';
import { menusApi } from '../../../../lib/menus.api';
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
import { nxPackagesApi } from '../../../../lib/packages.api';
export default function ExecutorsIndex({
menu,
pkg,
}: {
menu: MenuItem[];
pkg: ProcessedPackageMetadata;
}): JSX.Element {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
const wrapperElement = useRef(null);
useEffect(() => {
const handleRouteChange = (url: string) => {
if (url.includes('#')) return;
if (!wrapperElement) return;
(wrapperElement as any).current.scrollTo({
top: 0,
left: 0,
behavior: 'smooth',
});
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => router.events.off('routeChangeComplete', handleRouteChange);
}, [router, wrapperElement]);
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
menu: {
sections: sortCorePackagesFirst<MenuSection>(
getPackagesSections(menu),
'id'
),
},
package: pkg,
};
/**
* Show either the docviewer or the package view depending on:
* - docviewer: it is a documentation document
* - packageviewer: it is package generated documentation
*/
return (
<div id="shell" className="flex h-full flex-col">
<div className="w-full flex-shrink-0">
<DocumentationHeader isNavOpen={navIsOpen} toggleNav={toggleNav} />
</div>
<main
id="main"
role="main"
className="flex h-full flex-1 overflow-y-hidden"
>
<SidebarContainer menu={vm.menu} navIsOpen={navIsOpen} />
<div
ref={wrapperElement}
id="wrapper"
data-testid="wrapper"
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
>
<PackageSchemaSubList pkg={vm.package} type={'executor'} />
</div>
</main>
</div>
);
}
export const getStaticPaths: GetStaticPaths = () => {
return {
paths: [
...nxPackagesApi.getStaticDocumentPaths().packages.map((x) => ({
params: { name: x.params.segments.slice(1)[0] },
})),
],
fallback: 'blocking',
};
};
export async function getStaticProps({
params,
}: {
params: { name: string };
}): Promise<{
props: {
menu: MenuItem[];
pkg: ProcessedPackageMetadata;
};
}> {
const pkg = nxPackagesApi.getPackage([params.name]);
return {
props: {
menu: menusApi.getMenu('packages', 'packages'),
pkg,
},
};
}

View File

@ -0,0 +1,108 @@
import { getPackagesSections } from '@nrwl/nx-dev/data-access-menu';
import { sortCorePackagesFirst } from '@nrwl/nx-dev/data-access-packages';
import { Menu, MenuItem, MenuSection } from '@nrwl/nx-dev/models-menu';
import { ProcessedPackageMetadata } from '@nrwl/nx-dev/models-package';
import { DocumentationHeader, SidebarContainer } from '@nrwl/nx-dev/ui-common';
import { GetStaticPaths } from 'next';
import { useRouter } from 'next/router';
import { useEffect, useRef } from 'react';
import { PackageSchemaSubList } from '../../../../../feature-package-schema-viewer/src/lib/package-schema-sub-list';
import { menusApi } from '../../../../lib/menus.api';
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
import { nxPackagesApi } from '../../../../lib/packages.api';
export default function GeneratorsIndex({
menu,
pkg,
}: {
menu: MenuItem[];
pkg: ProcessedPackageMetadata;
}): JSX.Element {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
const wrapperElement = useRef(null);
useEffect(() => {
const handleRouteChange = (url: string) => {
if (url.includes('#')) return;
if (!wrapperElement) return;
(wrapperElement as any).current.scrollTo({
top: 0,
left: 0,
behavior: 'smooth',
});
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => router.events.off('routeChangeComplete', handleRouteChange);
}, [router, wrapperElement]);
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
menu: {
sections: sortCorePackagesFirst<MenuSection>(
getPackagesSections(menu),
'id'
),
},
package: pkg,
};
/**
* Show either the docviewer or the package view depending on:
* - docviewer: it is a documentation document
* - packageviewer: it is package generated documentation
*/
return (
<div id="shell" className="flex h-full flex-col">
<div className="w-full flex-shrink-0">
<DocumentationHeader isNavOpen={navIsOpen} toggleNav={toggleNav} />
</div>
<main
id="main"
role="main"
className="flex h-full flex-1 overflow-y-hidden"
>
<SidebarContainer menu={vm.menu} navIsOpen={navIsOpen} />
<div
ref={wrapperElement}
id="wrapper"
data-testid="wrapper"
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
>
<PackageSchemaSubList pkg={vm.package} type={'generator'} />
</div>
</main>
</div>
);
}
export const getStaticPaths: GetStaticPaths = () => {
return {
paths: [
...nxPackagesApi.getStaticDocumentPaths().packages.map((x) => ({
params: { name: x.params.segments.slice(1)[0] },
})),
],
fallback: 'blocking',
};
};
export async function getStaticProps({
params,
}: {
params: { name: string };
}): Promise<{
props: {
menu: MenuItem[];
pkg: ProcessedPackageMetadata;
};
}> {
const pkg = nxPackagesApi.getPackage([params.name]);
return {
props: {
menu: menusApi.getMenu('packages', 'packages'),
pkg,
},
};
}

View File

@ -14,9 +14,7 @@ export function Breadcrumbs({ path }: { path: string }): JSX.Element {
? segment.slice(0, segment.indexOf('#'))
: segment,
// We do not have dedicated page view for executors & generators
href: ['executors', 'generators'].includes(segment)
? '/' + segments.slice(0, index).join('/') + '#' + segment
: '/' + segments.slice(0, index + 1).join('/'),
href: '/' + segments.slice(0, index + 1).join('/'),
current: '/' + segments.slice(0, index + 1).join('/') === cleanedPath,
})),
];