Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions docs/0.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,72 @@ export default defineNuxtConfig({

Checkout [`ModuleOptions` typesβ†—οΈŽ](https://github.com/nuxt-content/mdc/blob/main/src/module.ts).

## Using Custom Elements
When using custom elements in Vue, you can configure Vue to recognize them by adding the `compilerOptions.isCustomElement` function in your `nuxt.config.ts` file.

For example, if you include
```ts [nuxt.config.ts]
export default defineNuxtConfig({
vue: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('mjx')
}
}
})
```
in your `nuxt.config.ts`, Vue will allow tags starting with `mjx` like `<mjx-container>`.
However, this function is unavailable to MDC at runtime, thus adding an MDC component to your markdown will yield a warning suggesting to add the element to `compilerOptions.isCustomElement`.

In order to avoid this warning, you must export a default function inside `utils/compilerOptions/isCustomElement.ts` which will be used when ignoring custom elements in the MDC markdown.
```ts [~/utils/compilerOptions/isCustomElement.ts]

export default function isCustomElement(tag: string) {
return tag.startsWith('mjx')
}
```

Additionally, this function can be imported and used in your `nuxt.config.ts` to ensure consistency between Vue and MDC.

```ts [nuxt.config.ts]

// Import from ./utils/compilerOptions/isCustomElement.ts if using Nuxt 3 or below
import isCustomElement from './app/utils/compilerOptions/isCustomElement'

export default defineNuxtConfig({
vue: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('mjx')
}
}
})
```
Now you can use custom elements as below.

```html [custom-element.vue]
<script setup>
const mdc = `
# Custom elements can now be used

::mjx-container
Elements starting with "my" are ignored when rendering
::
`
</script>

<style>
my-element {
color: red;
}
</style>

<template>
<div>
<MDC :value="mdc" />
<my-element>Another custom element</my-element>
</div>
</template>
```

## Contributing

You can contribute to this module online with CodeSandbox:
Expand Down
19 changes: 18 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fs from 'node:fs'
import { defineNuxtModule, extendViteConfig, addComponent, addComponentsDir, createResolver, addServerHandler, addTemplate, addImports, addServerImports } from '@nuxt/kit'
import { defineNuxtModule, extendViteConfig, addComponent, addComponentsDir, createResolver, addServerHandler, addTemplate, addImports, addServerImports, type Resolver } from '@nuxt/kit'
import { defu } from 'defu'
import { resolve } from 'pathe'
import type { BundledLanguage } from 'shiki'
Expand Down Expand Up @@ -189,6 +189,17 @@
},
})

// Add isCustomElement util from app utils if defined by user, otherwise use default

Check failure on line 192 in src/module.ts

View workflow job for this annotation

GitHub Actions / test

Trailing spaces not allowed
const appResolver = createResolver(nuxt.options.srcDir)
const cusElemPath = "./utils/compilerOptions/isCustomElement"

Check failure on line 194 in src/module.ts

View workflow job for this annotation

GitHub Actions / test

Strings must use singlequote
addImports({
from: !(await fileExists(appResolver, cusElemPath))

Check failure on line 196 in src/module.ts

View workflow job for this annotation

GitHub Actions / test

Trailing spaces not allowed

Check failure on line 196 in src/module.ts

View workflow job for this annotation

GitHub Actions / test

Extra space before value for key 'from'
? resolver.resolve("./runtime", cusElemPath)

Check failure on line 197 in src/module.ts

View workflow job for this annotation

GitHub Actions / test

Trailing spaces not allowed

Check failure on line 197 in src/module.ts

View workflow job for this annotation

GitHub Actions / test

Strings must use singlequote
: appResolver.resolve(cusElemPath),
name: 'default',

Check failure on line 199 in src/module.ts

View workflow job for this annotation

GitHub Actions / test

Trailing spaces not allowed
as: 'isCustomElement'

Check failure on line 200 in src/module.ts

View workflow job for this annotation

GitHub Actions / test

Missing trailing comma
})

// Update Vite optimizeDeps
extendViteConfig((config) => {
const include = [
Expand Down Expand Up @@ -290,3 +301,9 @@
}
}
}

// resolver.resolvePath returns file path with extension (e.g. filepath/my-file.ts) if file exists
// Returns same path as resolver.resolve if file doesn't exist
async function fileExists(resolver: Resolver, path: string) {
return resolver.resolve(path) !== await resolver.resolvePath(path)
}
15 changes: 12 additions & 3 deletions src/runtime/components/MDCRenderer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import htmlTags from '../parser/utils/html-tags-list'
import { flatUnwrap, nodeTextContent } from '../utils/node'
import { pick } from '../utils'
import { isCustomElement } from '#imports';

Check failure on line 11 in src/runtime/components/MDCRenderer.vue

View workflow job for this annotation

GitHub Actions / test

Extra semicolon

type CreateElement = typeof h

Expand Down Expand Up @@ -99,7 +100,7 @@
const contentKey = computed(() => {
const components = (props.body?.children || [])
.map(n => (n as any).tag || n.type)
.filter(t => !htmlTags.includes(t))
.filter(t => !ignoreTag(t))

return Array.from(new Set(components)).sort().join('.')
})
Expand Down Expand Up @@ -400,7 +401,7 @@
*/
const resolveComponentInstance = (component: any) => {
if (typeof component === 'string') {
if (htmlTags.includes(component)) {
if (ignoreTag(component)) {
return component
}

Expand Down Expand Up @@ -514,7 +515,7 @@

const components: string[] = []

if (node.type !== 'root' && !htmlTags.includes(renderTag as any)) {
if (node.type !== 'root' && !ignoreTag(renderTag as any)) {
components.push(renderTag)
}
for (const child of (node.children || [])) {
Expand All @@ -533,4 +534,12 @@

return tags[tag] || tags[pascalCase(tag)] || tags[kebabCase(node.tag)] || tag
}

function ignoreTag(tag: string) {
// Checks if input tag is an html tag or

Check failure on line 539 in src/runtime/components/MDCRenderer.vue

View workflow job for this annotation

GitHub Actions / test

Trailing spaces not allowed
let isCustomEl = (typeof tag === "string")
? isCustomElement(tag)
: false
return htmlTags.includes(tag) || isCustomEl
}
</script>
4 changes: 4 additions & 0 deletions src/runtime/utils/compilerOptions/isCustomElement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Default isCustomElement function
export default function (tag: string) {
return false
}