From 67ec2dbdbba8404de24872d50e15f3d15652f8fb Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 11 Oct 2021 19:52:03 +0000 Subject: [PATCH] Surface category labels in the JS API doc sidebar (#587) This is kind of a hacky workaround until TypeStrong/typedoc#1532 is implemented for real. --- source/assets/css/vendor/typedoc/_style.css | 21 ++++++-- tool/typedoc-theme.js | 56 +++++++++++++++++++++ 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/source/assets/css/vendor/typedoc/_style.css b/source/assets/css/vendor/typedoc/_style.css index 587c554..d74750b 100644 --- a/source/assets/css/vendor/typedoc/_style.css +++ b/source/assets/css/vendor/typedoc/_style.css @@ -85,10 +85,6 @@ } } -.typedoc .container-main { - padding-bottom: 200px; -} - .typedoc .row { display: flex; position: relative; @@ -1274,3 +1270,20 @@ input[type="checkbox"]:checked + .tsd-widget:before { .typedoc h1, .typedoc h2, .typedoc h3, .typedoc h4, .typedoc h5, .typedoc h6 { font-weight: 700; } + +/* Undo the global link style for the TypeDoc navigation. */ +.tsd-navigation a { + border-bottom: none; +} + +/* Add styles for our custom category labels in the navigation. */ +.tsd-navigation .sl-tsd-category-label { + font-weight: bold; + padding-left: 25px; +} +.tsd-navigation .sl-tsd-category-label span { + display: block; + padding-top: 2px; + padding-bottom: 2px; + border-left: 2px solid transparent; +} diff --git a/tool/typedoc-theme.js b/tool/typedoc-theme.js index 01381d5..4a2324e 100644 --- a/tool/typedoc-theme.js +++ b/tool/typedoc-theme.js @@ -38,6 +38,62 @@ class SassSiteRenderContext extends DefaultThemeRenderContext { return context.oldMember(props); }, this); + // Make categories visible in the sidebar as well as in the main page's index. + // Hopefully this will no longer be necessary once TypeStrong/typedoc#1532 is + // implemented. + oldNavigation = this.navigation; + navigation = bind(function(context, props) { + const navigation = context.oldNavigation(props); + const childrenByCategories = context._groupByCategory(props.model); + if (childrenByCategories.size === 0) return navigation; + + const secondary = navigation.children[navigation.children.length - 1]; + if (!secondary) return navigation; + + const firstLI = secondary.children[0].children[0]; + const ul = firstLI.props["class"].startsWith("current ") + ? firstLI.children[1] + : secondary.children[0]; + + ul.children = Array.from(childrenByCategories).map(([title, children]) => + JSX.createElement(JSX.Fragment, null, + JSX.createElement("li", {class: "sl-tsd-category-label"}, + JSX.createElement("span", null, title)), + ...children.map(child => + JSX.createElement("li", {class: child.cssClasses}, + JSX.createElement("a", { + href: context.urlTo(child), class: "tsd-kind-icon" + }, child.name))))); + + return navigation; + }, this); + + // Returns a map from category titles to the set of members of those + // categories. + _groupByCategory = (model) => { + const map = new Map(); + function addCategoriesToMap(categories) { + for (const category of categories) { + const children = map.get(category.title); + if (children) { + children.push(...category.children); + } else { + map.set(category.title, [...category.children]); + } + } + } + + if (model.categories) { + addCategoriesToMap(model.categories); + } else if (model.groups) { + for (const group of model.groups) { + if (group.categories) addCategoriesToMap(group.categories); + } + } + + return map; + }; + // Add compatibility indicators to the beginning of documentation blocks. oldComment = this.comment; comment = bind((context, props) => {