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

[IDEA] Customize/Override headings via mdx file #208

Open
noxify opened this issue Oct 28, 2024 · 1 comment
Open

[IDEA] Customize/Override headings via mdx file #208

noxify opened this issue Oct 28, 2024 · 1 comment

Comments

@noxify
Copy link
Contributor

noxify commented Oct 28, 2024

Note: Maybe a bit unstructured and confusing - See it as first iteration :) If there are some questions or something is unclear, please let me know.

The headings export is currently auto generated via a remark (?) plugin ( Code ref ).

Which works fine in 99% of all use cases.

If we have some custom logic, we can currently override/extend them by defining our own headings in the page.tsx ( Example ).

This idea is for the approach, where we can't use the page.tsx and want to control the available headings via the current mdx file.


What needs to be changed?

  • Check if a headings export is specified in a mdx file
    • If so, use the value if it's not a function
    • If it's a function, call the function - here we should support async functions
  • We have to find a way to tell the @renoun/mdx package if it's necessary to generate the headings or not ( = loading the addHeadings function conditionally ).
  • Optional: While parsing the mdx file, we could also check if the returned schema/type matches the expected one - if not, throw/show an error?
  • Optional: making it "opt-in" ( via a feature toggle or via a global config? )

Some details:

In my template repo ( which reflects the structure of our internal docs ), I have different collections and the page.tsx is built as generic as possible ( multi-collection support? ), so creating the headings from the page.tsx wasn't an option for me without creating more complexity to the page.tsx.

Use case was to provide some functionality to render an openapi spec.
( as alternative, you could use the existing API Documentation )

  • One helper function to parse the spec ( here I use @apidevtools/swagger-parser )
  • One helper function to generate the headings based on the available sections in the spec
  • One wrapper component to render it

Example mdx file:

---
title: Petstore
description: Getting started with openapi
---

import { parseSpec, generateHeadings } from "@/components/open-api/helpers"
import { OpenApiRenderer } from "@/components/open-api"

const parsedSpec = await parseSpec("https://petstore3.swagger.io/api/v3/openapi.json")

export const headings = await generateHeadings(parsedSpec)

<OpenApiRenderer spec={parsedSpec} />

I know this could be an edge case and this approach would just move the "complexity" from my side to the package side.
I know there is a risk that supporting this could break some pages if they have unexperienced users who doesn't know what they're doing

@souporserious
Copy link
Owner

This looks great, thank you for all of the details! I think this API makes a ton of sense for allowing headings to be overridden.

For the function, it could provide the calculated headings to give you control of how they are ordered:

export const headings = async (currentHeadings) => {
  return [...currentHeadings, await generateHeadings(parsedSpec)]
}

Something to note, imported MDX file headings also need be considered since only the root file is considered right now. The function should work nice for this to read in imported MDX files. For example, the remark plugin can wire this up by default:

import Leaf, { headings as leafHeadings } from './leaf.mdx'

export headings = (currentHeadings) => {
  return [...currentHeadings, ...leafHeadings]
}

# Root File

Root file contents

<Leaf />

It's a little more involved with having to index them properly based on where the import is used, but it shouldn't be too hard. What's nice is this API should solve two problems with one implementation 😎

I'm currently working on making the overall API stable, but will come back to this after the dust settles.

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

No branches or pull requests

2 participants