13g10n
Contact me
Home

Extending possibilities of code blocks in Nuxt Content

Even though the default Nuxt Content markdown parser works reasonably well with code blocks out of the box, I still had to spend a relatively large amount of time improving their appearance and functionality.

I won’t talk about highlighter styles, because a huge number of topics (including those in the style of popular IDEs) are quite easy to google.

As for the functional part, by default we do not have a file and language indication, although this information can be specified and even passed to the final component.

For example, for a main.py python file, where we want to highlight the first line, the block will look like this:

example.md
```python [main.py] {1}
def sum(a: int, b: int) -> int:
    """Sum two numbers."""
    ...

The Nuxt Content module uses the components/content folder to define global custom components available in markdown files. To extend a standard component, we must create a file in the components/content folder called ProseCode.vue.

Be careful with the naming of your components, as the same folder allows you to override the built-in components used in rendering.

In the new component, we get code, language, filename and highlights as props and have a default slot for inserting a rendered HTML block.

components/content/ProseCode.vue
<script setup>
const props = defineProps({
  code: {
    type: String,
    default: ''
  },
  language: {
    type: String,
    default: null
  },
  filename: {
    type: String,
    default: null
  },
  highlights: {
    type: Array,
    default: []
  }
})
</script>

Further, it all comes down only to your fantasies and skills. For example, we display the language and file name, add a code copy button:

components/content/ProseCode.vue
<template>
  <div>
    <section>
        <span>{{ props.language }}</span>
        <span>{{ props.filename }}</span>
        <button @click="navigator.clipboard.writeText(props.code)")>Copy</button>
    </section>
    <slot/>
  </div>
</template>

Actually, I use about the same scheme in this blog. Result for the original block of code:

main.py
def sum(a: int, b: int) -> int:
    """Sum two numbers."""
    ...

Nuxt
SSG
Nuxt Content