Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented client side hierarchy & expandable hierarchy section, #2744 #2749

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

mrfigg
Copy link
Contributor

@mrfigg mrfigg commented Oct 14, 2024

Resolves #2744.

Feedback & changes welcome.

Copy link
Collaborator

@Gerrit0 Gerrit0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some initial comments, without having played with it much locally yet

private async buildHierarchy(event: RendererEvent) {
const theme = this.owner.theme as DefaultTheme;

const [_, pageEvent] = event.createPageEvent<Reflection>(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait what, why? Shouldn't need an event here... getHierarchy doesn't appear to need to exist on the context at all. The member on the theme should be sufficient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, I did that at the start and forgot to go back to do it properly. Egg on my face. I'll get started on fixing this soon, but it might take me a bit to get to it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, I remember why I did this initially, although I do still want to find a better way. getHierarchy relies on the type partial to render the html property for each element, which takes a DefaultThemeRenderContext argument. The only way I found to create a full DefaultThemeRenderContext instance was to fake a PageEvent. I'll look for an alternative, but do you know of a better way to handle this?

As for getHierarchy being on the context, very true, that should be easy enough to fix.

@@ -214,7 +225,7 @@ export class DefaultTheme extends Theme {
urls.push(new UrlMapping("index.html", project, this.indexTemplate));
}

if (getHierarchyRoots(project).length) {
if (this.application.options.getValue("includeHierarchySummary") && getHierarchyRoots(project).length) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why anyone would ever turn this off... I've found it super useful as a CTRL+F page...

Copy link
Contributor Author

@mrfigg mrfigg Oct 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I admit it might be rare, but I've had a small project that had a single pair of classes that had a hierarchy. Having an entire page just for two lines that already appeared on both of the linked pages seemed like bloat to me.

container.append(list);
});

if (!targetPath && window.location.hash) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be necessary here... we should never have an ID within the hierarchy today

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the "view full" link includes a hash to the interface/class on the hierarchy.html page. To emulate that behavior for content that was loaded dynamically this work around is required, but if I rework the PR to have hierarchy.html be static as seems to be the desire in a comment below it can easily be removed.

item.innerHTML += `<span>${currentBranch.text}</span>`;
} else {
item.innerHTML += currentBranch.html.replace(
/(?<=<a [^>]*(?<=\s)href=")(?![a-zA-Z]+:\/\/)([^"]*)(?="[^>]*>)/g,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's... no... that's not going to be okay. It'd be better to set the innerHTML, then query for anchor elements and update the href attribute.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's totally fair and an easy fix. I might be too used to abusing regex, I didn't even think about it.


const hierarchy = context.getHierarchy();

const hierarchyJs = Path.join(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice to skip writing this if it is empty, and also skip loading a script to handle it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smart.

@@ -39,7 +39,7 @@ export function reflectionTemplate(context: DefaultThemeRenderContext, props: Pa
{hasTypeParameters(props.model) && <> {context.typeParameters(props.model.typeParameters)} </>}
{props.model instanceof DeclarationReflection && (
<>
{context.hierarchy(props.model.typeHierarchy)}
{context.hierarchy(props.model)}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this change is made it has to wait for 0.27 due to being a breaking change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would adding a second argument be considered a breaking change? That could work.

</>
<ul class="tsd-hierarchy tsd-full-hierarchy">
<li class="tsd-hierarchy-item">
<span>{context.i18n.theme_loading()}</span>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This page should not need JS, including the full hierarchy in a place where users without it enabled can see it is useful.

Copy link
Contributor Author

@mrfigg mrfigg Oct 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under the assumption that TypeDoc always requires JavaScript, as the entire navigation section is non-functional without it.

Assuming that was the case, this change was made to improve size on disk (otherwise the same data would be in both hierarchy.html and assets/hierarchy.js) and to make the hierarchy trees match. Currently interface hierarchies with multiple roots get partially rendered multiple times, where as the new rendering logic renders the entire tree once.

It would be possible to duplicate the rendering logic and make the hierarchy.html page static while fixing multi-root hierarchies, but that would still unnecessarily increase the file size if JavaScript is still required.

Should I proceed with this change or is it fine as is? Either way works for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expandable Hierarchy Section
2 participants