nuxt / content

The file-based CMS for your Nuxt application, powered by Markdown and Vue components.
https://content.nuxt.com
MIT License
3.13k stars 625 forks source link

Custom ProseCode.vue component possibly breaking builds (500 error) #2161

Open cossssmin opened 1 year ago

cossssmin commented 1 year ago

Environment

Nuxt project info:


Reproduction

https://github.com/cossssmin/docs-nuxt3

Describe the bug

Hi there!

Working on migrating the Maizzle docs to Nuxt 3/Content 2 and running into an issue with a custom ProseCode.vue component for the Content module.

Builds on both local and Netlify fail with a 500, but it's not clear to me why. Everything works great in local dev. I'm also running the Netlify build command with CI='' npm run generate so that it doesn't trip on any warnings or anything.

Weirdly enough, it used to work at some point, and it's very strange because no code related to this component was changed when it started failing. Here's an almost-functional site preview of when it worked:

https://amazing-trifle-bf003d.netlify.app/

So my questions are:

This is my custom ProseCode.vue:

https://github.com/cossssmin/docs-nuxt3/blob/main/components/content/Prose/ProseCode.vue

Using it, build fails on random pages, for example here's the latest deploy log error:

5:22:08 PM: [log] [nitro]   ├─ /docs/examples/google-fonts (500)
5:22:08 PM: [log] [nitro]   ├─ /docs/plaintext (500)
5:22:08 PM: [log] [nitro]   ├─ /docs/configuration/templates (500)
5:22:08 PM: [log] [nitro]   ├─ /docs/expressions (500)
5:22:08 PM: [log] [nitro]   ├─ /guides/syntax-highlighting-prismjs (500)
5:22:08 PM: [log] [nitro]   ├─ /docs/cli (500)
5:22:08 PM: [log] [nitro]   ├─ /docs/tailwindcss (500)
5:22:08 PM: [log] [nitro]   ├─ /guides/markdown-emails (500)
5:22:08 PM: [log] [nitro]   ├─ /docs/components (500)
5:22:08 PM: [log] [nitro]   ├─ /docs/configuration/components (500)
5:22:08 PM: [log] [nitro]
5:22:08 PM: [error] Exiting due to prerender errors.
5:22:08 PM:   at prerender (node_modules/nitropack/dist/shared/nitro.1db3349c.mjs:189:11)
5:22:08 PM:   at async node_modules/nuxt/dist/index.mjs:2634:7
5:22:08 PM:   at async build (node_modules/nuxt/dist/index.mjs:3785:5)
5:22:08 PM:   at async Object.invoke (node_modules/nuxi/dist/chunks/build.mjs:59:5)
5:22:08 PM:   at async Object.invoke (node_modules/nuxi/dist/chunks/generate.mjs:36:5)
5:22:08 PM:   at async _main (node_modules/nuxi/dist/cli.mjs:49:20)

However it's always different, here's the one before it (no changes to code):

5:15:03 PM: Errors prerendering:
5:15:03 PM: [log] [nitro]   ├─ /docs/examples/google-fonts (500)
5:15:03 PM: [log] [nitro]   ├─ /docs/plaintext (500)
5:15:03 PM: [log] [nitro]   ├─ /docs/configuration/templates (500)
5:15:03 PM: [log] [nitro]   ├─ /docs/expressions (500)
5:15:03 PM: [log] [nitro]   ├─ /guides/syntax-highlighting-prismjs (500)
5:15:03 PM: [log] [nitro]   ├─ /guides/markdown-emails (500)
5:15:03 PM: [log] [nitro]   ├─ /docs/components (500)
5:15:03 PM: [log] [nitro]   ├─ /docs/configuration/components (500)

The moment I remove the custom ProseCode component, it builds successfully.

cossssmin commented 1 year ago

The issue is with the getHighlighter function:

const highlighter = await getHighlighter({
  theme: shikiTheme,
  langs: [props.language]
})

async functions work fine in ProseCode.vue, tried a simple $fetch to a local server/api/test.get.js and it builds successfully.

I tried writing a plugin that provides the highlighter, like so:

// plugins/highlighter.js

import { getHighlighter, toShikiTheme } from 'shiki-es'
import vsCodeTheme from '@/assets/shiki/github-light.json'

const shikiTheme = toShikiTheme(vsCodeTheme)

export default defineNuxtPlugin( async () => {
  return {
    provide: {
      highlighter: async ({theme, langs}) => {
        const h = await getHighlighter({
          theme: theme || shikiTheme,
          langs: langs || ['js', 'sh', 'json', 'liquid', 'xml', 'html', 'hbs', 'postcss', 'css', 'jsx', 'md']
        })

        return h
      }
    }
  }
})

... and using it like this:

const { $highlighter } = useNuxtApp()
const highlighter = await $highlighter({
  langs: [props.language],
})

const tokens = highlighter.codeToThemedTokens(
  props.code.trim().replace(/^\n+/, ''),
  props.language ?? undefined,
  )

// ... use `renderToHtml` to render `tokens` using custom markup for pre/code and lines

In the end, I guess it's the same thing, it looks like it gets called for each code block, which at some point fails for some reason.

Is there any way to provide a custom highlighter to a ProseCode.vue component?

cossssmin commented 1 year ago

Ended up creating a custom Transformer:

https://github.com/maizzle/maizzle.com/tree/main/modules/shiki

Barbapapazes commented 1 year ago

Hello,

Could you provide more informations about you issue? I'm not sure to fully understand where does this item getHighlighter come from and where you want to use it.

cossssmin commented 1 year ago

getHighlighter comes from shiki-es, you can see import { getHighlighter, toShikiTheme } from 'shiki-es' in my code above.