Skip to content

Commit

Permalink
Support custom components provided via a provider (#402)
Browse files Browse the repository at this point in the history
This adds support for components provided via the `providerImportSource`
option.

The user can specify which components are available by specifying the
`MDXProvidedComponents` type either locally inside the MDX file or for
all MDX files by declaring it globally.

Closes #399
  • Loading branch information
remcohaszing committed Feb 26, 2024
1 parent 48be843 commit cd59565
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 9 deletions.
7 changes: 7 additions & 0 deletions .changeset/quiet-beds-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@mdx-js/language-service": patch
"@mdx-js/language-server": patch
"vscode-mdx": patch
---

Support custom components provided via a provider
3 changes: 2 additions & 1 deletion fixtures/fixtures.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
{"path": "demo"},
{"path": "frontmatter"},
{"path": "no-tsconfig"},
{"path": "node16"}
{"path": "node16"},
{"path": "provide"}
]
}
31 changes: 31 additions & 0 deletions fixtures/provide/components.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {type ReactNode} from 'react'

export type PlanetProps = {
distanceFromStar: number

name: string

radius: number
}

/**
* A planet in a solar system.
*/
export function Planet({
distanceFromStar,
name,
radius
}: PlanetProps): ReactNode {
return (
<section>
<dl>
<dd>Name</dd>
<dt>{name}</dt>
<dd>Radius</dd>
<dt>{radius}</dt>
<dd>Distance from star</dd>
<dt>{distanceFromStar}</dt>
</dl>
</section>
)
}
3 changes: 3 additions & 0 deletions fixtures/provide/solar-system.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Solar system

<Planet name="Earth" radius={6371} />
10 changes: 10 additions & 0 deletions fixtures/provide/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"jsx": "react-jsx",
"module": "node16",
"strict": true
},
"mdx": {
"checkMdx": true
}
}
8 changes: 8 additions & 0 deletions fixtures/provide/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {type Planet} from './components.js'

declare global {
// eslint-disable-next-line @typescript-eslint/naming-convention
type MDXProvidedComponents = {
Planet: typeof Planet
}
}
45 changes: 45 additions & 0 deletions packages/language-server/test/diagnostics.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,48 @@ test('does not resolve shadow content', async () => {
kind: 'full'
})
})

test('provided components', async () => {
const {uri} = await serverHandle.openTextDocument(
fixturePath('provide/solar-system.mdx'),
'mdx'
)
const diagnostics = await serverHandle.sendDocumentDiagnosticRequest(uri)

assert.deepEqual(diagnostics, {
items: [
{
code: 2741,
data: {
documentUri: fixtureUri('provide/solar-system.mdx?virtualCodeId=jsx'),
isFormat: false,
original: {},
serviceIndex: 2,
uri: fixtureUri('provide/solar-system.mdx'),
version: 1
},
message:
"Property 'distanceFromStar' is missing in type '{ name: string; radius: number; }' but required in type 'PlanetProps'.",
range: {
end: {character: 7, line: 2},
start: {character: 1, line: 2}
},
relatedInformation: [
{
location: {
range: {
end: {character: 18, line: 3},
start: {character: 2, line: 3}
},
uri: fixtureUri('provide/components.tsx')
},
message: "'distanceFromStar' is declared here."
}
],
severity: 1,
source: 'ts'
}
],
kind: 'full'
})
})
2 changes: 2 additions & 0 deletions packages/language-service/lib/virtual-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ ${isAsync ? 'async ' : ''}function _createMdxContent(props) {
* **Do not use.** This is an MDX internal.
*/
const _components = {
// @ts-ignore
.../** @type {0 extends 1 & MDXProvidedComponents ? {} : MDXProvidedComponents} */ ({}),
...props.components,
/** The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component. */
props${Array.from(variables, (name) => ',\n /** {@link ' + name + '} */\n ' + name).join('')}
Expand Down

0 comments on commit cd59565

Please sign in to comment.