let assert = require('assert')
let XDate = require('xdate')
+let arrays_equal =
+ (a, b) =>
+ a.length === b.length && a.every((value, index) => value === b[index])
+
return async (env, head, body, scripts) => {
//let cart = await _require('/online_store/cart.jst')
let fa_arrow_circle_left = await env.site.get_min_svg('/_svg/fa_arrow-circle-left.svg')
let icon_cross = await env.site.get_min_svg('/_svg/icon_cross.svg')
//let icon_tick = await env.site.get_min_svg('/_svg/icon_tick.svg')
let logo_large = await env.site.get_min_svg('/_svg/logo_large.svg')
- let menu = await env.site.get_menu('/_menu.json')
let page = await _require('/_lib/page.jst')
// initialize env.cart
//await cart(env)
+ // compute breadcrumbs from directories of the path
+ let component_names = env.parsed_url.pathname.split('/')
+ assert(component_names.length >= 2)
+ assert(component_names[0].length === 0)
+ assert(component_names[component_names.length - 1].length)
+ component_names = component_names.slice(1, -1)
+
let transaction = await env.site.database.Transaction()
let signed_in_as
let site_title, copyright
+ let component_titles // collects breadcrumb titles for current page
+ let menu_names, menu_titles // collects top level of menu for the navbar
let feedback_draft
try {
- let root = await transaction.get({})
+ let root = await transaction.get()
let session = await get_session(env, root)
signed_in_as = await session.get_json('signed_in_as')
- let globals = await root.get('globals', {})
+ let globals = await root.get('globals')
site_title = await globals.get_json('site_title')
copyright = await globals.get_json('copyright')
+ let navigation = await root.get('navigation')
+
+ let p = navigation
+ component_titles = [await p.get_json('title')] // Home
+ for (let i = 0; i < component_names.length; ++i) {
+ let children = await p.get('children')
+ p = await children.get(component_names[i])
+ component_titles.push(await p.get_json('title'))
+ }
+
+ menu_names = await navigation.get_json('menu')
+ let children = await navigation.get('children')
+ menu_titles = [await navigation.get_json('title')] // Home
+ for (let i = 0; i < menu_names.length; ++i) {
+ let child = await children.get(menu_names[i])
+ menu_titles.push(await child.get('title'))
+ }
+
feedback_draft = await session.get_json('feedback_draft')
if (feedback_draft === undefined || env.now >= feedback_draft.expires)
feedback_draft = null
transaction.rollback()
}
+ // save breadcrumbs and their titles for breadcrumbs.jst
+ // note: component_titles.length === component_names.length + 1
+ // component_titles[0] corresponds to /, is 'Home' or similar
+ // component_titles[i] corresponds to component_names[i - 1], i >= 1
+ env.component_names = component_names
+ env.component_titles = component_titles
+ console.log('cn', component_names)
+ console.log('ct', component_titles)
+
+ // note: menu_titles.length === menu_names.length + 1
+ // menu_titles[0] corresponds to /, is 'Home' or similar
+ // menu_titles[i] corresponds to menu_names[i - 1], i >= 1a
+ // (navbar has Home appearing at same level as its immediate children)
+ console.log('mn', menu_names)
+ console.log('mt', menu_titles)
+
await page(
env,
// head
async _out => {
- // extract top-level directory name
- assert(env.parsed_url.pathname.slice(0, 1) === '/')
- let index = env.parsed_url.pathname.indexOf('/', 1)
- let dir = index === -1 ? '' : env.parsed_url.pathname.slice(1, index)
-
title {
`${site_title}: ${
- dir.length === 0 ?
- 'Home' :
- menu.entries[menu.index[dir]].name
- }`
+ component_titles[
+ component_names.length >= 2 ? 1 : component_names.length
+ ]
+ }`
}
await head(_out)
}
div.collapse.navbar-collapse#navbarSupportedContent {
ul.navbar-nav.mr-auto {
- if (dir.length === 0)
- li.nav-item.active {
- a.nav-link(href="/index.html") {
- 'Home'
- span.sr-only {' (current)'}
- }
- }
- else
- li.nav-item {
- a.nav-link(href="/index.html") {'Home'}
- }
- let entries = menu.entries
- for (let i = 0; i < entries.length; ++i)
- if (entries[i].navbar)
- if (entries[i].dir === dir)
- li.nav-item.active {
- a.nav-link(href=`/${entries[i].dir}/index.html`) {
- `${entries[i].name}`
- span.sr-only {' (current)'}
- }
+ // the active entry in the navbar bar is based on which top-level
+ // page we are under, even if we are not directly on that page
+ // but one of its children, this may be unexpected as the active
+ // entry does not highlight on hover, but you can still click it;
+ // we determine here the path to the corresponding top-level page
+ let component_prefix = component_names.slice(0, 1)
+
+ for (let i = 0; i < menu_titles.length; ++i) {
+ // construct path to the top-level page about to be described
+ let menu_prefix =
+ i == 0 ? [] : [menu_names[i - 1]]
+ let menu_prefix_path =
+ menu_prefix.map(name => '/' + name).join('') + '/index.html'
+
+ if (arrays_equal(menu_prefix, component_prefix))
+ li.nav-item.active {
+ a.nav-link(href=menu_prefix_path) {
+ `${menu_titles[i]}`
+ span.sr-only {' (current)'}
}
- else
- li.nav-item {
- a.nav-link(href=`/${entries[i].dir}/index.html`) {
- `${entries[i].name}`
- }
+ }
+ else
+ li.nav-item {
+ a.nav-link(href=menu_prefix_path) {
+ `${menu_titles[i]}`
}
+ }
+ }
//li.nav-item.dropdown {
// a.nav-link.dropdown-toggle#navbarDropdown(href="#" role="button" data-toggle="dropdown" aria-expanded="false") {
// 'Dropdown'