Skip to content

Commit

Permalink
feat: flatten namespaces on index pages (#29)
Browse files Browse the repository at this point in the history
Refs #3
  • Loading branch information
kitsonk authored Dec 6, 2021
1 parent d4e523e commit 7411a36
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 50 deletions.
86 changes: 50 additions & 36 deletions components/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ import { gtw } from "./styles.ts";
import type { BaseStyles } from "./styles.ts";

export interface DocNodeCollection {
moduleDoc?: DocNodeModuleDoc[];
import?: DocNodeImport[];
namespace?: DocNodeNamespace[];
class?: DocNodeClass[];
enum?: DocNodeEnum[];
variable?: DocNodeVariable[];
function?: DocNodeFunction[];
interface?: DocNodeInterface[];
typeAlias?: DocNodeTypeAlias[];
moduleDoc?: [string, DocNodeModuleDoc][];
import?: [string, DocNodeImport][];
namespace?: [string, DocNodeNamespace][];
class?: [string, DocNodeClass][];
enum?: [string, DocNodeEnum][];
variable?: [string, DocNodeVariable][];
function?: [string, DocNodeFunction][];
interface?: [string, DocNodeInterface][];
typeAlias?: [string, DocNodeTypeAlias][];
}

export interface DocProps<Node extends DocNode> {
Expand Down Expand Up @@ -62,23 +62,37 @@ export function isAbstract(node: DocNode) {
}
}

export function asCollection(
function append(
collection: DocNodeCollection,
entries: DocNode[],
includePrivate = false,
): DocNodeCollection {
const collection: DocNodeCollection = {};
path?: string,
includePrivate?: boolean,
) {
for (const entry of entries) {
if (includePrivate || entry.declarationKind !== "private") {
const docNodes: DocNode[] = collection[entry.kind] ??
const docNodes: [string, DocNode][] = collection[entry.kind] ??
(collection[entry.kind] = []);
docNodes.push(entry);
const label = path ? `${path}.${entry.name}` : entry.name;
docNodes.push([label, entry]);
if (entry.kind === "namespace") {
append(collection, entry.namespaceDef.elements, label, includePrivate);
}
}
}
}

export function asCollection(
entries: DocNode[],
path?: string,
includePrivate = false,
): DocNodeCollection {
const collection: DocNodeCollection = {};
append(collection, entries, path, includePrivate);
return collection;
}

function byName(a: DocNode, b: DocNode) {
return a.name.localeCompare(b.name);
function byName(a: [string, DocNode], b: [string, DocNode]) {
return a[0].localeCompare(b[0]);
}

function getName(node: DocNode, path?: string[]) {
Expand All @@ -97,13 +111,16 @@ export function DocTitle(
}

function Entry<Node extends DocNode>(
{ children, path, style }: NodeProps<Node>,
{ children, style }: {
children: Child<[string, Node]>;
style: BaseStyles;
},
) {
const node = take(children);
const [label, node] = take(children);
return (
<li>
<h3 class={gtw(style)}>
<NodeLink path={path}>{node}</NodeLink>
<NodeLink>{label}</NodeLink>
{isAbstract(node) ? <Tag color="yellow">abstract</Tag> : undefined}
{isDeprecated(node.jsDoc)
? <Tag color="gray">deprecated</Tag>
Expand All @@ -114,18 +131,11 @@ function Entry<Node extends DocNode>(
);
}

interface NodeLinkProps {
children: Child<DocNode>;
path?: string[];
}

export function NodeLink({ children, path }: NodeLinkProps) {
const node = take(children);
export function NodeLink({ children }: { children: Child<string> }) {
const label = take(children);
const { url } = store.state as StoreState;
const href = `/${url}${url.endsWith("/") ? "" : "/"}~/${
[...path ?? [], node.name].join(".")
}`;
return <a href={href}>{node.name}</a>;
const href = `/${url}${url.endsWith("/") ? "" : "/"}~/${label}`;
return <a href={href}>{label}</a>;
}

export function SectionTitle({ children }: { children: Child<string> }) {
Expand All @@ -140,16 +150,20 @@ export function SectionTitle({ children }: { children: Child<string> }) {
}

export function Section<Node extends DocNode>(
{ children, path, style, title }: NodesProps<Node>,
{ children, style, title }: {
children: Child<[string, Node][]>;
style: BaseStyles;
title: string;
},
) {
const nodes = take(children);
const displayed = new Set();
const items = nodes.sort(byName).map((node) => {
if (displayed.has(node.name)) {
const items = nodes.sort(byName).map(([label, node]) => {
if (displayed.has(label)) {
return;
}
displayed.add(node.name);
return <Entry path={path} style={style}>{node}</Entry>;
displayed.add(label);
return <Entry style={style}>{[label, node]}</Entry>;
});
return (
<div>
Expand Down
6 changes: 3 additions & 3 deletions components/doc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function ModuleToc(
) {
const collection = take(children);
const imports = collection.import
? collection.import.map((imp) => <li>{imp.importDef.src}</li>)
? collection.import.map(([, imp]) => <li>{imp.importDef.src}</li>)
: undefined;
return (
<div>
Expand Down Expand Up @@ -81,7 +81,7 @@ function DocNodes({ children }: { children: Child<DocNodeCollection> }) {
<div class={gtw("mainBox")}>
{collection.moduleDoc && (
<JsDoc style={largeMarkdownStyles}>
{collection.moduleDoc[0].jsDoc}
{collection.moduleDoc[0][1].jsDoc}
</JsDoc>
)}
{collection.namespace && (
Expand Down Expand Up @@ -225,7 +225,7 @@ export function DocPage(
) {
const state = store.state as StoreState;
const { entries, url, includePrivate } = state;
const collection = asCollection(entries, includePrivate);
const collection = asCollection(entries, undefined, includePrivate);
const library = url.startsWith("deno:");
const item = take(children);
if (item) {
Expand Down
23 changes: 13 additions & 10 deletions components/namespaces.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,42 +16,45 @@ export function NamespaceDoc(
const node = take(children);
const { name, namespaceDef: { elements } } = node;
const { includePrivate } = store.state as StoreState;
const collection = asCollection(elements, includePrivate);
const currentPath = [...path, name];
const collection = asCollection(
elements,
[...path, name].join("."),
includePrivate,
);
return (
<div>
{collection.namespace && (
<Section title="Namespace" style="nodeNamespace" path={currentPath}>
<Section title="Namespace" style="nodeNamespace">
{collection.namespace}
</Section>
)}
{collection.class && (
<Section title="Classes" style="nodeClass" path={currentPath}>
<Section title="Classes" style="nodeClass">
{collection.class}
</Section>
)}
{collection.enum && (
<Section title="Enums" style="nodeEnum" path={currentPath}>
<Section title="Enums" style="nodeEnum">
{collection.enum}
</Section>
)}
{collection.variable && (
<Section title="Variables" style="nodeVariable" path={currentPath}>
<Section title="Variables" style="nodeVariable">
{collection.variable}
</Section>
)}
{collection.function && (
<Section title="Functions" style="nodeFunction" path={currentPath}>
<Section title="Functions" style="nodeFunction">
{collection.function}
</Section>
)}
{collection.interface && (
<Section title="Interfaces" style="nodeInterface" path={currentPath}>
<Section title="Interfaces" style="nodeInterface">
{collection.interface}
</Section>
)}
{collection.typeAlias && (
<Section title="Type Aliases" style="nodeTypeAlias" path={currentPath}>
<Section title="Type Aliases" style="nodeTypeAlias">
{collection.typeAlias}
</Section>
)}
Expand All @@ -64,7 +67,7 @@ export function NamespaceToc(
) {
const { name, namespaceDef: { elements } } = take(children);
const { includePrivate } = store.state as StoreState;
const collection = asCollection(elements, includePrivate);
const collection = asCollection(elements, undefined, includePrivate);
return (
<div>
<h3 class={gtw("tocHeader")}>
Expand Down
2 changes: 1 addition & 1 deletion middleware/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Middleware } from "../deps.ts";

export function createBadgeMW(): Middleware {
let badge: Uint8Array | undefined;
return async function favicon(ctx, next) {
return async function badgeMW(ctx, next) {
if (ctx.request.url.pathname !== "/badge.svg") {
return next();
}
Expand Down

0 comments on commit 7411a36

Please sign in to comment.