From 56c621cbc0facbdab26626e434023c7a5a81d54d Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Wed, 2 Aug 2023 16:08:55 +0200 Subject: [PATCH 1/2] fix: nav & toc active state breaks with external urls --- templates/modern/src/nav.ts | 28 +++++++++++++++------------- templates/modern/src/toc.ts | 6 +++++- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/templates/modern/src/nav.ts b/templates/modern/src/nav.ts index f8ff91bd65c..52db4db0596 100644 --- a/templates/modern/src/nav.ts +++ b/templates/modern/src/nav.ts @@ -35,21 +35,20 @@ export async function renderNavbar(): Promise { } const menu = html` - ` } } @@ -131,6 +130,9 @@ function findActiveItem(items: (NavItem | NavItemContainer)[]): NavItem { let activeItem: NavItem let maxPrefix = 0 for (const item of items.map(i => 'items' in i ? i.items : i).flat()) { + if (item.href.hostname !== window.location.hostname || item.href.port !== window.location.port) { + continue + } const prefix = commonUrlPrefix(url, item.href) if (prefix > maxPrefix) { maxPrefix = prefix diff --git a/templates/modern/src/toc.ts b/templates/modern/src/toc.ts index b149a47ee42..ac33f45c2dc 100644 --- a/templates/modern/src/toc.ts +++ b/templates/modern/src/toc.ts @@ -54,7 +54,7 @@ export async function renderToc(): Promise { if (node.href) { const url = new URL(node.href, tocUrl) node.href = url.href - active = normalizeUrlPath(url) === normalizeUrlPath(window.location) + active = isExternal(url) ? false : normalizeUrlPath(url) === normalizeUrlPath(window.location) if (active) { if (node.items) { node.expanded = true @@ -79,6 +79,10 @@ export async function renderToc(): Promise { return false } + function isExternal(url: URL): boolean { + return url.hostname !== window.location.hostname || url.port !== window.location.port + } + function renderToc() { render(html`${renderTocFilter()} ${renderTocNodes(items) || renderNoFilterResult()}`, tocContainer) } From 1c1b72fc0235fbafc5f0d2e350bcf0a1590fb1a0 Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Thu, 3 Aug 2023 11:40:27 +0200 Subject: [PATCH 2/2] chore: move check to helper & add tests --- samples/seed/articles/toc.yml | 2 ++ templates/modern/src/helper.ts | 9 +++++++++ templates/modern/src/nav.ts | 4 ++-- templates/modern/src/toc.ts | 8 ++------ .../SamplesTest.Seed/toc.html.view.verified.json | 11 ++++++++++- .../SamplesTest.Seed/toc.json.view.verified.json | 4 ++-- .../SamplesTest.Seed/toc.verified.json | 7 ++++++- 7 files changed, 33 insertions(+), 12 deletions(-) diff --git a/samples/seed/articles/toc.yml b/samples/seed/articles/toc.yml index 905fbf66f05..3637c8113e4 100644 --- a/samples/seed/articles/toc.yml +++ b/samples/seed/articles/toc.yml @@ -10,3 +10,5 @@ href: csharp_coding_standards.md - name: Markdown href: markdown.md +- name: Microsoft Docs + href: https://docs.microsoft.com/en-us/ diff --git a/templates/modern/src/helper.ts b/templates/modern/src/helper.ts index 613f669e3de..78e95f79865 100644 --- a/templates/modern/src/helper.ts +++ b/templates/modern/src/helper.ts @@ -45,3 +45,12 @@ export function breakWordLit(text: string): TemplateResult { }) return html`${result}` } + +/** + * Check if the url is external. + * @param url The url to check. + * @returns True if the url is external. + */ +export function isExternalHref(url: URL): boolean { + return url.hostname !== window.location.hostname || url.protocol !== window.location.protocol +} diff --git a/templates/modern/src/nav.ts b/templates/modern/src/nav.ts index 52db4db0596..45ca72ba75b 100644 --- a/templates/modern/src/nav.ts +++ b/templates/modern/src/nav.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import { render, html, TemplateResult } from 'lit-html' -import { breakWordLit, meta } from './helper' +import { breakWordLit, meta, isExternalHref } from './helper' import { themePicker } from './theme' import { TocNode } from './toc' @@ -130,7 +130,7 @@ function findActiveItem(items: (NavItem | NavItemContainer)[]): NavItem { let activeItem: NavItem let maxPrefix = 0 for (const item of items.map(i => 'items' in i ? i.items : i).flat()) { - if (item.href.hostname !== window.location.hostname || item.href.port !== window.location.port) { + if (isExternalHref(item.href)) { continue } const prefix = commonUrlPrefix(url, item.href) diff --git a/templates/modern/src/toc.ts b/templates/modern/src/toc.ts index ac33f45c2dc..37679c6bada 100644 --- a/templates/modern/src/toc.ts +++ b/templates/modern/src/toc.ts @@ -3,7 +3,7 @@ import { TemplateResult, html, render } from 'lit-html' import { classMap } from 'lit-html/directives/class-map.js' -import { breakWordLit, meta } from './helper' +import { breakWordLit, meta, isExternalHref } from './helper' export type TocNode = { name: string @@ -54,7 +54,7 @@ export async function renderToc(): Promise { if (node.href) { const url = new URL(node.href, tocUrl) node.href = url.href - active = isExternal(url) ? false : normalizeUrlPath(url) === normalizeUrlPath(window.location) + active = isExternalHref(url) ? false : normalizeUrlPath(url) === normalizeUrlPath(window.location) if (active) { if (node.items) { node.expanded = true @@ -79,10 +79,6 @@ export async function renderToc(): Promise { return false } - function isExternal(url: URL): boolean { - return url.hostname !== window.location.hostname || url.port !== window.location.port - } - function renderToc() { render(html`${renderTocFilter()} ${renderTocNodes(items) || renderNoFilterResult()}`, tocContainer) } diff --git a/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.html.view.verified.json b/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.html.view.verified.json index c8247b47122..ba1dcb37aeb 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.html.view.verified.json +++ b/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.html.view.verified.json @@ -44,6 +44,15 @@ "topicHref": null, "tocHref": null, "level": 2.0 + }, + { + "name": "Microsoft Docs", + "href": "https://docs.microsoft.com/en-us/", + "topicHref": "https://docs.microsoft.com/en-us/", + "tocHref": null, + "level": 2.0, + "items": [], + "leaf": true } ], "_appName": "Seed", @@ -65,4 +74,4 @@ "leaf": false, "title": "Table of Content", "_disableToc": true -} \ No newline at end of file +} diff --git a/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.json.view.verified.json b/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.json.view.verified.json index 3b6d61138cf..be25e0c6372 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.json.view.verified.json +++ b/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.json.view.verified.json @@ -1,3 +1,3 @@ { - "content": "{\"items\":[{\"name\":\"Home\",\"href\":\"index.html\",\"topicHref\":\"index.html\"},{\"name\":\"Articles\",\"href\":\"articles/docfx_getting_started.html\",\"tocHref\":\"articles/toc.html\",\"topicHref\":\"articles/docfx_getting_started.html\"},{\"name\":\"API Documentation\",\"items\":[{\"name\":\".NET API\",\"href\":\"api/BuildFromAssembly.html\",\"tocHref\":\"api/toc.html\",\"topicHref\":\"api/BuildFromAssembly.html\",\"topicUid\":\"BuildFromAssembly\"},{\"name\":\"REST API\",\"href\":\"restapi/petstore.html\",\"tocHref\":\"restapi/toc.html\",\"topicHref\":\"restapi/petstore.html\"}]}]}" -} \ No newline at end of file + "content": "{\"items\":[{\"name\":\"Home\",\"href\":\"index.html\",\"topicHref\":\"index.html\"},{\"name\":\"Articles\",\"href\":\"articles/docfx_getting_started.html\",\"tocHref\":\"articles/toc.html\",\"topicHref\":\"articles/docfx_getting_started.html\"},{\"name\":\"API Documentation\",\"items\":[{\"name\":\".NET API\",\"href\":\"api/BuildFromAssembly.html\",\"tocHref\":\"api/toc.html\",\"topicHref\":\"api/BuildFromAssembly.html\",\"topicUid\":\"BuildFromAssembly\"},{\"name\":\"REST API\",\"href\":\"restapi/petstore.html\",\"tocHref\":\"restapi/toc.html\",\"topicHref\":\"restapi/petstore.html\"}]},{\"name\":\"Microsoft Docs\",\"href\":\"https://docs.microsoft.com/en-us/\",\"topicHref\":\"https://docs.microsoft.com/en-us/\"}]}" +} diff --git a/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.verified.json b/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.verified.json index 94a24832c96..a3c4eed67e8 100644 --- a/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.verified.json +++ b/test/docfx.Snapshot.Tests/SamplesTest.Seed/toc.verified.json @@ -28,6 +28,11 @@ "topicHref": "restapi/petstore.html" } ] + }, + { + "name": "Microsoft Docs", + "href": "https://docs.microsoft.com/en-us/", + "topicHref": "https://docs.microsoft.com/en-us/" } ] -} \ No newline at end of file +}