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

feat: find nearest exclusive parent for currentNav #395

Merged
merged 4 commits into from
Jun 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nuxtjs.org/components/HeaderNavigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default defineComponent({
const route = useRoute()
const hover = ref(false)
const itemIndex = ref(null)
const currentNav = computed(() => $docus.currentNav.value)
const currentNav = computed(() => $docus.get({ depth: 1 }).links)

// computed
const headerLinks = computed(() =>
Expand Down
1 change: 0 additions & 1 deletion nuxtjs.org/content/0.discover/0.framework/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
title: Framework
slug: framework
description: Framework page.
---

Expand Down
3 changes: 2 additions & 1 deletion nuxtjs.org/content/0.discover/1.features/index.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
title: Features
slug: features
navigation:
exclusive: true
---
Empty file.
4 changes: 4 additions & 0 deletions nuxtjs.org/content/1.learn/2.internals/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
navigation:
exclusive: true
---
2 changes: 2 additions & 0 deletions nuxtjs.org/content/1.learn/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
---
title: Learn
navigation:
exclusive: true
---
70 changes: 42 additions & 28 deletions src/core/runtime/composables/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,38 +47,62 @@ export const useDocusNavigation = ({ context, state, api }: DocusAddonContext) =
const nav = state.navigation[locale || currentLocale] || []

let items = nav
let match

// The deepest exclusive navigation that can be found based on `from`
let exclusiveContent
// Parent of exclusive Content
let parent

// `from` parameter handling
if (from) {
let lastMatch

const paths = from.split('/')

items = paths.reduce((links: NavItem[], path: string, index: number) => {
// Empty path, skip iteration
if (!path) return links

// If we iterated on the latest path, return links
if (index + 1 === paths.length) return links

// If this path links are only 1 long, set the current path children as root
if (links.length === 1) {
links = links[0].children

return links
// Remember last matched content
// This content will use as navigation parent if it has an exclusive decendant
if (match && !match.shadow) {
lastMatch = match
}

// Otherwise, find matching path and get its childrens
links = links.find(item => {
const itemPaths = item.to.split('/')
// Find matched content
match = links.find(item => item.to.split('/')[index] === path)
if (match) {
// Update parent and exclusiveContent if the matched content marked as exclusive navigation
if (match && match.navigation && match.navigation.exclusive) {
parent = lastMatch || parent
exclusiveContent = match
}

return itemPaths[index] === path
}).children
return match.children
}

return links
}, items)

if (exclusiveContent) {
// Use exclusive links
items = exclusiveContent.children
} else {
items = nav
}
}

// Start filtering loop
return all ? items : filterLinks(items, depth, 1)
return {
// matched page info
title: exclusiveContent && exclusiveContent.title,
to: exclusiveContent && exclusiveContent.to,
navigation: exclusiveContent ? exclusiveContent.navigation : {},
// matched parent
parent,
// filter children
links: all ? items : filterLinks(items, depth, 1)
}
}

/**
Expand Down Expand Up @@ -120,20 +144,10 @@ export const useDocusNavigation = ({ context, state, api }: DocusAddonContext) =
// eslint-disable-next-line no-unused-expressions
fetchCounter.value

// Get links from path
const links = get({
from: path.value,
all: true
// Calcualte navigatin based on current path
return get({
from: path.value
})

// Get current link
const currentLink = links.find(link => link.to === path.value)

// Return filtered items for exclusive page
if (currentLink && currentLink.navigation && currentLink.navigation.exclusive) return links

// Return whole navigation
return get()
})

// Update content on update.
Expand Down
9 changes: 6 additions & 3 deletions src/core/runtime/composables/templates.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { pascalCase } from 'scule'
import Vue from 'vue'
import { ComputedRef } from '@nuxtjs/composition-api'
import { DocusAddonContext, DocusDocument, NavItem } from '../../../types'
import { DocusAddonContext, DocusCurrentNav, DocusDocument } from '../../../types'

export const useDocusTemplates = ({ api, state }: Partial<DocusAddonContext>, currentNav: ComputedRef<NavItem[]>) => {
export const useDocusTemplates = (
{ api, state }: Partial<DocusAddonContext>,
currentNav: ComputedRef<DocusCurrentNav>
) => {
function getPageTemplate(page: DocusDocument) {
let template = typeof page.template === 'string' ? page.template : page.template?.self

if (!template) {
// Fetch from nav (root to link) and fallback to settings.template
const slugs: string[] = page.to.split('/').filter(Boolean).slice(0, -1) // no need to get latest slug since it is current page

let links = currentNav?.value || []
let { links } = currentNav?.value || {}

slugs.forEach((_slug: string, index: number) => {
// generate full path of parent
Expand Down
17 changes: 3 additions & 14 deletions src/core/utils/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ const findLink = (links: NavItem[], to: string) => links.find(link => link.to ==
*/
const slugToTitle = title => title && title.replace(/-/g, ' ').split(' ').map(pascalCase).join(' ')

/**
* Get a page directory index.md page if exists
*/
const getPageIndex = (pages, page): NavItem | undefined =>
pages.find(_page => _page.dir === page.dir && _page.slug === '')

/**
* Get navigation link for a page
*/
Expand All @@ -45,6 +39,7 @@ const getPageLink = (page: any): NavItem => {
return {
slug,
to,
shadow: !!page.shadow,
title: page.title,
draft: page.draft,
template,
Expand Down Expand Up @@ -117,8 +112,6 @@ function createNav(pages: any[]) {
return
}

const $index = getPageIndex(pages, _page)

const $page = getPageLink(_page)

// To: '/docs/guide/hello.md' -> dirs: ['docs', 'guide']
Expand All @@ -127,11 +120,6 @@ function createNav(pages: any[]) {
// Remove the file part (except if index.md)
if (_page.slug !== '') dirs = dirs.slice(0, -1)

// Merge index exclusive parameter
if ($index && $index.navigation && $index.navigation.exclusive && $page.navigation) {
$page.navigation.exclusive = $index.navigation.exclusive
}

if (!dirs.length) {
if ($page.navigation) {
$page.navigation.slot = $page.navigation.slot || 'header'
Expand All @@ -154,7 +142,8 @@ function createNav(pages: any[]) {
if (!link) {
link = getPageLink({
slug: dir,
to
to,
shadow: true
})

currentLinks.push(link)
Expand Down
9 changes: 8 additions & 1 deletion src/defaultTheme/components/molecules/AsideNavigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
>
<div class="py-4 pl-4 pr-24 sm:pl-6 lg:pr-0 lg:pt-10">
<AsideTop />
<NuxtLink v-if="parent" class="mb-3 block" :to="$contentLocalePath(parent.to)">
<IconArrowLeft width="16" height="16" class="inline-block mr-2" /> {{ parent.title }}
</NuxtLink>
<ul>
<template v-for="link in links">
<AsideNavigationItem
Expand All @@ -78,7 +81,11 @@ import { defineComponent } from '@nuxtjs/composition-api'
export default defineComponent({
computed: {
links() {
return this.$docus.currentNav.value
const nav = this.$docus.currentNav.value
return nav.links
},
parent() {
return this.$docus.currentNav.value.parent
},
lastRelease() {
return this.$docus.lastRelease?.value
Expand Down
9 changes: 9 additions & 0 deletions src/types/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface NavItem {
slug: string
to: string
title: string
shadow: boolean
draft?: boolean
template?: {
self: string
Expand All @@ -49,6 +50,14 @@ export type DocusNavigation = {
[language: string]: NavItem[]
}

export type DocusCurrentNav = {
title?: string
to?: string
navigation?: NavItemNavigationConfig | false
parent?: NavItem
links: NavItem[]
}

export interface DocusDocument {
// FrontMatter
title: string
Expand Down