getPagesUnderRoute

getPagesUnderRoute

This function is imported from file nextra/context.js (opens in a new tab)

import { getPagesUnderRoute } from 'nextra/context'

When called with a string as argument, it returns an array of Page objects that are under the route passed as argument. Here it is the source code:

export function getPagesUnderRoute(route: string): Page[] {
  const { pageMap } = getContext('getPagesUnderRoute')
  return filter(pageMap, route).activeLevelPages
}

it returns an array of Page objects that are under the route passed as argument. The Page type is defined as follows:

export type Page = (MdxFile | Folder<Page>) & {
  meta?: Exclude<Meta, string>
}

What seems to be interesting is the frontMatter property of the MdxFile type.

export type FrontMatter = GrayMatterFile<string>['data']
export type Meta = string | Record<string, any>
 
export type MdxFile<FrontMatterType = FrontMatter> = {
  kind: 'MdxPage'
  name: string
  route: string
  locale?: string
  frontMatter?: FrontMatterType
}

This way we can access the frontMatter of the MdxFile object and use it to filter the pages we want to display. Here is an example of such a page:

 {
    kind: 'MdxPage',
    name: '2024-01-23-leccion',
    route: '/clases/january/2024-01-23-leccion',
    frontMatter: {
      title: 'Tuesday 2024/01/23',
      published: true,
      summary: 'Encuesta. Primeras prácticas. Un vistazo a las primeras etapas de un compilador: análisis léxico',
      labs: [Array],
      topics: [Array],
      videos: [Array]
    },
    meta: { title: 'Tuesday 2024/01/23' }
}
  • Other properties are name and route that can be used to build links to the pages.
  • The attribute kind is a string that can have the value 'MdxPage' or 'Folder' and it is used to distinguish between pages and folders.

Here is an example of Folder object:

{
    kind: 'Folder',
    name: 'tree-transformations',
    route: '/topics/tree-transformations',
    children: [ [Object], ... [Object] ],
    meta: { title: 'Tree Transformations' }
  },

The children of a Folder is an array of FileType objects:

export interface Folder<FileType = PageMapItem> {
  kind: 'Folder'
  name: string
  route: string
  children: FileType[]
}
 
export type PageMapItem = Folder | MdxFile | MetaJsonFile

The following is the code of a version of the CollectionPage (opens in a new tab) component in this notes:

import Link from 'next/link'
import { useRouter } from 'next/router'
import { getPagesUnderRoute } from 'nextra/context'
import filterRouteLocale from 'nextra/filter-route-locale'
import styles from './counters.module.css'
import LabInfo from '@/components/LabInfo'
import ClassInfo from '@/components/ClassInfo'
 
export function CollectionPage({ path }) {
  const { locale, defaultLocale } = useRouter()
  const pages = getPagesUnderRoute(path)
  let result = filterRouteLocale(pages, locale, defaultLocale).map(page => {
      if (page.frontMatter?.display === 'hidden') return null
      return (
        <li key={page.route}>
          <Link className={styles.link} href={page.route}>{page.meta?.title || page.frontMatter?.title || page?.name}</Link>
          {path === '/labs' && <LabInfo page={page} />} 
          {path.startsWith('/clases') &&  <ClassInfo page={page} />} 
        </li>
       )
    })
    return (<ol className={styles.myList} reversed>{result}</ol>)
}

Example

The following code is an example of how to use the getPagesUnderRoute function to build a list of links to the pages under the route /labs:

 
import GetSpecific from '@/components/getSpecific'
 
<GetSpecific path="/labs"/>

The following is the code of the getSpecific component:

import Link from 'next/link'
import { getPagesUnderRoute } from 'nextra/context'
import filterRouteLocale from 'nextra/filter-route-locale'
import { useRouter } from 'next/router'
import styles from './counters.module.css'
 
import React from 'react'
 
export default function getSpecific({ path }) {
    const { locale, defaultLocale } = useRouter()
    const pages = getPagesUnderRoute(path)
    console.error(pages)
    let result = filterRouteLocale(pages, locale, defaultLocale).map(page => {
        if (page.frontMatter?.display === 'hidden') return null
        return (
          <li key={page.route}>
            <Link className={styles.link} href={page.route}>{page.meta?.title || page.frontMatter?.title || page?.name}</Link> {page.frontMatter?.key} 
          </li>
         )
      })
      return (<ol className={styles.myList} reversed>{result}</ol>)
}

Here is the output of the former code:


  1. Training Exam training-exam
  2. TFA: Final Project tfa
  3. Translating Egg to JS egg-2-js
  4. Extended Egg Interpreter extended-egg
  5. Egg OOP Parser egg-oop-parser
  6. Egg Interpreter egg-interpreter
  7. Pattern Matching pattern-matching
  8. Calculator. Funs on the left side. Multiple arguments left-side
  9. Lexer Generator lexer-generator
  10. Adding Loops to the Calculator while
  11. Egg Parser egg-parser
  12. Functions functions
  13. Scope Intro scope-intro
  14. Hello Compiler hello-compilers
  15. Translating Arithmetic Expressions to JavaScript arith2js
  16. IAAS iaas
  17. Visual Studio Code and Gitpod visual-studio-code
  18. GitHub Project Board github-project-board
  19. GitHub Campus Expert github-campus-expert
  20. Fill the form

If I substitute line 12 by console.error(pages[0]) I've got the following object as the first page of /labs:

{
  kind: 'MdxPage',
  name: 'functions',
  route: '/labs/functions',
  frontMatter: {
    title: 'Adding Functions to the Calculator',
    key: 'functions',
    published: true,
    date: '2023/03/21',
    delivery: '2023/03/30',
    campus: 'https://campusingenieriaytecnologia2223.ull.es/mod/assign/view.php?id=28190&forceview=1',
    order: 12,
    layout: 'Practica',
    sidebar: 'auto',
    prev: 'constant-folding.md',
    next: null,
    rubrica: [
      'El paquete está publicado en GitHub Registry',
      'Se comprueba que el módulo npm se instala desde el GitHub Registry y funciona',
      'Probar que el ejecutable queda correctamente instalado, puede ser ejecutado con el nombre publicado y produce salidas correctas',
      'Opciones en línea de comandos (-o, -V, -h, etc.)',
      'Traduce correctamente las funciones',
      'Traduce correctamente las llamadas encadenadas',
      'Traduce correctamente las expresiones lógicas',
      'Se declaran las variables inicializadas en el preámbulo de las funciones o del programa',
      'Da mensajes de error para variables no declaradas',
      'Los mensajes de error ayudan a la detección de errores',
      'Ha añadido tests suficientes, documentación y cubrimiento',
      'Se publica la documentación usando un static generator, API docs y Covering',
      'Se ha añadido el enlace a las GH pages en el "About" del repo'
    ],
    video20230308: {
      date: '08/03/2023',
      description: 'Clase del 08/03/2023. Se describe el soporte para scopes de ast-types',
      id: 'CR_GI81TFt0'
    },
    video20230313: {
      date: '13/03/2023',
      description: 'Clase del 13/03/2023. Se describe el soporte de ast-types para el recorrrido y modificación de nodos (Métodos visit)',
      url: 'https://youtu.be/CR_GI81TFt0',
      id: 'CR_GI81TFt0'
    },
    video20230322: {
      date: '22/03/2023',
      description: 'Clase del 22/03/2023. Hasta el minuto 25 se explica como realizar el examen parcial del curso 22/23. Le será muy útil para preparar  examenes. A partir del minuto 25 se explican las bases para la práctica functions',
      url: 'https://youtu.be/SfAIHgAqSuQ',
      id: 'SfAIHgAqSuQ'
    },
    video20230327: {
      date: '27/03/2023',
      description: 'Clase del 27/03/2023. Se continúa la explicación de como realizar la práctica de funciones',
      url: 'https://youtu.be/DRP-_bmTdto',
      id: 'DRP-_bmTdto'
    },
    video20230328: {
      date: '28/03/2023',
      description: 'Clase del 28/03/2023. Análisis de tipos en el lab. Lookup en el scope analysis. Soporte a las operaciones para los nuevos tipos. Nueva sintáxis para las calls',
      url: 'https://youtu.be/XpzNZJ-fwx8',
      id: 'XpzNZJ-fwx8'
    }
  },
  meta: {
    type: 'menu',
    title: 'Functions',
    display: 'normal',
    items: {
      'Añadiendo funciones a la calculadora': [Object],
      'Las funciones son expresiones': [Object],
      'Funciones que retornan funciones': [Object],
      'Funciones que reciben funciones y retornan funciones': [Object],
      'Encadenamiento de llamadas': [Object],
      Comentarios: [Object],
      'Operadores Lógicos y de Comparación': [Object],
      'Short Circuit Evaluation and if then else': [Object],
      'Type Handling in Dynamic Languages': [Object],
      'Type Checking: Basic concepts': [Object],
      'Function Arithmetic': [Object],
      'Arithmetic of Functions ad numbers': [Object],
      'Arithmetic of Functions and Booleans': [Object],
      'New Semantic needs New Syntax': [Object],
      'Type Promotion': [Object],
      'Language Symmetry': [Object],
      'Be bold in your designs but keep them simple.': [Object],
      Videos: [Object],
      'Vídeos sobre manejo del AST con ast-types': [Object],
      'Smells, The Open Closed Principle, the Switch Smell and the Strategy pattern': [Object],
      'Pruebas, Covering e Integración Continua': [Object],
      'Avoiding the preamble in the tests': [Object],
      'Documentación': [Object],
      References: [Object]
    }
  }
}

Notice the meta attribute of the MdxPage object that seems to correspond to the information inside the _meta.json file about page[0](lab functions).

Getting a lab by key

import GetLabByKey from '@/components/getLabByKey'
 
<GetLabByKey labKey="functions"/>
➜  pl2324-apuntes git:(main) cat components/getLabByKey.jsx 
import { getPagesUnderRoute } from 'nextra/context'
import filterRouteLocale from 'nextra/filter-route-locale'
import { useRouter } from 'next/router'
 
// returns the page for a given labKey
export default function getLabByKey({ labKey }) {
    const pages = getPagesUnderRoute("/labs")
    console.error("labKey=", labKey)
    //console.error(pages[0])
    let result = pages.filter(page => {
        return (page?.frontMatter?.key === labKey) 
    })
    //console.error("Result\n", result)
    return (<div>{result[0].frontMatter.title}</div>)
}