@nicodoggie/mdx-language-server 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Remco Haszing <remcohaszing@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,403 @@
1
+ # `@mdx-js/language-server`
2
+
3
+ [![Build][build-badge]][build]
4
+ [![Coverage][coverage-badge]][coverage]
5
+ [![Downloads][downloads-badge]][downloads]
6
+ [![Sponsors][sponsors-badge]][collective]
7
+ [![Backers][backers-badge]][collective]
8
+ [![Chat][chat-badge]][chat]
9
+
10
+ A [language server][lsp] for [MDX][].
11
+
12
+ ## Contents
13
+
14
+ * [What is this?](#what-is-this)
15
+ * [When should I use this?](#when-should-i-use-this)
16
+ * [Install](#install)
17
+ * [Use](#use)
18
+ * [Language server features](#language-server-features)
19
+ * [Initialize Options](#initialize-options)
20
+ * [Configuration](#configuration)
21
+ * [TypeScript](#typescript)
22
+ * [Plugins](#plugins)
23
+ * [Editors](#editors)
24
+ * [Emacs](#emacs)
25
+ * [Neovim](#neovim)
26
+ * [Visual Studio Code](#visual-studio-code)
27
+ * [Compatibility](#compatibility)
28
+ * [Security](#security)
29
+ * [Contribute](#contribute)
30
+ * [Sponsor](#sponsor)
31
+ * [Changelog](#changelog)
32
+ * [License](#license)
33
+
34
+ ## What is this?
35
+
36
+ This package provides a [language server][lsp] for [MDX][].
37
+ The language server provides editor support based on [Volar][].
38
+ This includes support for [TypeScript][] as well as some MDX specific features.
39
+
40
+ ## When should I use this?
41
+
42
+ You can use this package if you want to enhance your editor for [MDX][] files
43
+ with features such as autocomplete and error diagnostics.
44
+ Some editors can consume this package directly, others need a plugin in order to
45
+ consume this package.
46
+
47
+ ## Install
48
+
49
+ In Node.js (version 16+), install with [npm][]:
50
+
51
+ ```sh
52
+ npm install @mdx-js/language-server
53
+ ```
54
+
55
+ ## Use
56
+
57
+ How to use this package depends on your editor integration.
58
+
59
+ This package provides the `mdx-language-server` CLI.
60
+ Because this is based on [`vscode-languageserver`][vscode-languageserver], the
61
+ same transports are supported.
62
+
63
+ ### Language server features
64
+
65
+ This language server supports all features supported by
66
+ [`volar-service-markdown`][volar-service-markdown] and
67
+ [`volar-service-typescript`][volar-service-typescript], plus some additional
68
+ features specific to MDX.
69
+
70
+ #### Commands
71
+
72
+ The language server supports the following [LSP commands][]:
73
+
74
+ ##### `mdx.toggleDelete`
75
+
76
+ Toggle delete syntax at the cursor position.
77
+ It uses the `workspace/applyEdit` command to apply edits.
78
+
79
+ ###### Arguments
80
+
81
+ * `uri` — The URI of the document to apply changes to.
82
+ * `range` — The current selection range of the user.
83
+
84
+ ###### Returns
85
+
86
+ `null`
87
+
88
+ ##### `mdx.toggleEmphasis`
89
+
90
+ Toggle emphasis syntax at the cursor position.
91
+ It uses the `workspace/applyEdit` command to apply edits.
92
+
93
+ ###### Arguments
94
+
95
+ * `uri` — The URI of the document to apply changes to.
96
+ * `range` — The current selection range of the user.
97
+
98
+ ###### Returns
99
+
100
+ `null`
101
+
102
+ ##### `mdx.toggleInlineCode`
103
+
104
+ Toggle inline code syntax at the cursor position.
105
+ It uses the `workspace/applyEdit` command to apply edits.
106
+
107
+ ###### Arguments
108
+
109
+ * `uri` — The URI of the document to apply changes to.
110
+ * `range` — The current selection range of the user.
111
+
112
+ ###### Returns
113
+
114
+ `null`
115
+
116
+ ##### `mdx.toggleStrong`
117
+
118
+ Toggle strong syntax at the cursor position.
119
+ It uses the `workspace/applyEdit` command to apply edits.
120
+
121
+ ###### Arguments
122
+
123
+ * `uri` — The URI of the document to apply changes to.
124
+ * `range` — The current selection range of the user.
125
+
126
+ ###### Returns
127
+
128
+ `null`
129
+
130
+ ### Initialize Options
131
+
132
+ MDX language server supports the following LSP initialization options:
133
+
134
+ * `typescript.enabled` (`boolean`, default: `false`) —
135
+ If true, enable TypeScript.
136
+ * `typescript.tsdk` (`string`, required) —
137
+ The path from which to load TypeScript.
138
+ * `locale` (`string`, optional) —
139
+ The locale to use for TypeScript error messages.
140
+
141
+ ### Configuration
142
+
143
+ MDX language server supports the following LSP configuration options:
144
+
145
+ * `mdx.trace.server.verbosity` (`"off"` | `"messages"` | `"compact"` |
146
+ `"verbose"`, default: `"off"`) —
147
+ Trace MDX language server requests in the output console.
148
+ * `mdx.trace.server.format` (`"text"` | `"json"`, default: `"text"`) —
149
+ How to format traced MDX language server requests.
150
+ * `mdx.validate.validateReferences` (`"ignore"` | `"hint"` | `"warning"` |
151
+ `"error"`, default: `"warning"`) —
152
+ Diagnostic level for invalid reference links, e.g. `[text][no-such-ref]`.
153
+ * `mdx.validate.validateFragmentLinks` (`"ignore"` | `"hint"` | `"warning"` |
154
+ `"error"`, default: `"warning"`) —
155
+ Diagnostic level for fragments links to headers in the current file that don’t
156
+ exist, e.g. `[text](#no-such-header)`
157
+ * `mdx.validate.validateFileLinks` (`"ignore"` | `"hint"` | `"warning"` |
158
+ `"error"`, default: `"warning"`) —
159
+ Diagnostic level for links to local files that don’t exist, e.g.
160
+ `[text](./no-such-file.png)`.
161
+ * `mdx.validate.validateMarkdownFileLinkFragments` (`"ignore"` | `"hint"` |
162
+ `"warning"` | `"error"`, default: `"warning"`) —
163
+ Diagnostic level for the fragment part of links to other local markdown files,
164
+ e.g. `[text](./no-such-file.png)`.
165
+ * `mdx.validate.validateUnusedLinkDefinitions` (`"ignore"` | `"hint"` |
166
+ `"warning"` | `"error"`, default: `"warning"`) —
167
+ Diagnostic level for link definitions that aren’t used anywhere.
168
+ `[never-used]: http://example.com`.
169
+ * `mdx.validate.validateDuplicateLinkDefinitions` (`"ignore"` | `"hint"` |
170
+ `"warning"` | `"error"`, default: `"warning"`) —
171
+ Diagnostic level for duplicate link definitions.
172
+ * `mdx.validate.ignoreLinks` (`Array<string>`, optional) —
173
+ Glob of links that should not be validated.
174
+ * `mdx.frontmatter.schemas` (`Array<object>`, optional) —
175
+ JSON schemas for YAML frontmatter in matching MDX files. Each item accepts
176
+ `fileMatch` as a string or array of strings, and either `url` for a schema
177
+ file or `schema` for an inline JSON schema object.
178
+
179
+ For example, configure schema-aware completions, hovers, and diagnostics for
180
+ YAML frontmatter in matching MDX files:
181
+
182
+ ```json
183
+ {
184
+ "mdx.frontmatter.schemas": [
185
+ {
186
+ "fileMatch": ["astro/src/content/docs/**/*.mdx"],
187
+ "url": "./.generated/mdx-frontmatter/docs.schema.json"
188
+ }
189
+ ]
190
+ }
191
+ ```
192
+
193
+ This applies to YAML frontmatter embedded in MDX files. TOML frontmatter is
194
+ parsed but does not use these YAML schema settings.
195
+
196
+ ### TypeScript
197
+
198
+ This extension offers type safety for MDX files based on TypeScript’s
199
+ [types in JSDoc][jsdoc].
200
+ For MDX specific details, see the
201
+ [TypeScript section](https://github.com/mdx-js/mdx-analyzer#typescript) of the
202
+ repository readme.
203
+
204
+ ### Plugins
205
+
206
+ For information on plugin support, see the
207
+ [Plugins section](https://github.com/mdx-js/mdx-analyzer#plugins) of the
208
+ repository readme.
209
+
210
+ ## Editors
211
+
212
+ MDX language server can be integrated with any editor that supports
213
+ [language servers][lsp].
214
+ Does your editor support MDX language server, but is it not in this list?
215
+ Feel free to add it.
216
+
217
+ ### Emacs
218
+
219
+ Use [`lsp-mode`][lsp-mode] to use the MDX language server with Emacs.
220
+
221
+ ### Neovim
222
+
223
+ You can add MDX support to MDX via [`nvim-lspconfig`][nvim-lspconfig].
224
+ After installing MDX language server, add the language server setup to your
225
+ `init.lua`.
226
+
227
+ ```lua
228
+ require'lspconfig'.mdx_analyzer.setup{}
229
+ ```
230
+
231
+ For more details, see the
232
+ [`nvim-lspconfig` MDX analyzer][nvim-lspconfig mdx-analyzer] documentation.
233
+
234
+ ### Visual Studio Code
235
+
236
+ Use [`unifiedjs.vscode-mdx`][vscode-mdx] to use the MDX language server with
237
+ [Visual Studio Code][vscode].
238
+
239
+ ## Compatibility
240
+
241
+ This project is compatible Node.js 20.19+.
242
+
243
+ This project uses [`vscode-languageserver`][vscode-languageserver] 9, which
244
+ implements language server protocol 3.17.4.
245
+ It should work anywhere where LSP 3.6.0 or later is implemented.
246
+
247
+ ## Security
248
+
249
+ This package provides IntelliSense for [MDX][] files.
250
+ Some IntelliSense features modify your source code, for example suggestions and
251
+ automatic refactors.
252
+ It is recommended to keep your source code under version control.
253
+
254
+ ## Contribute
255
+
256
+ See [§ Contribute][contribute] on our website for ways to get started.
257
+ See [§ Support][support] for ways to get help.
258
+
259
+ This project has a [code of conduct][].
260
+ By interacting with this repository, organization, or community you agree to
261
+ abide by its terms.
262
+
263
+ ## Sponsor
264
+
265
+ See [§ Sponsor][sponsor] on our site for how to help financially.
266
+
267
+ <table>
268
+ <tr valign="middle">
269
+ <td width="20%" align="center" rowspan="2" colspan="2">
270
+ <a href="https://vercel.com">Vercel</a><br><br>
271
+ <a href="https://vercel.com"><img src="https://avatars1.githubusercontent.com/u/14985020?s=256&v=4" width="128"></a>
272
+ </td>
273
+ <td width="20%" align="center" rowspan="2" colspan="2">
274
+ <a href="https://motif.land">Motif</a><br><br>
275
+ <a href="https://motif.land"><img src="https://avatars1.githubusercontent.com/u/74457950?s=256&v=4" width="128"></a>
276
+ </td>
277
+ <td width="20%" align="center" rowspan="2" colspan="2">
278
+ <a href="https://www.hashicorp.com">HashiCorp</a><br><br>
279
+ <a href="https://www.hashicorp.com"><img src="https://avatars1.githubusercontent.com/u/761456?s=256&v=4" width="128"></a>
280
+ </td>
281
+ <td width="20%" align="center" rowspan="2" colspan="2">
282
+ <a href="https://www.gitbook.com">GitBook</a><br><br>
283
+ <a href="https://www.gitbook.com"><img src="https://avatars1.githubusercontent.com/u/7111340?s=256&v=4" width="128"></a>
284
+ </td>
285
+ <td width="20%" align="center" rowspan="2" colspan="2">
286
+ <a href="https://www.gatsbyjs.org">Gatsby</a><br><br>
287
+ <a href="https://www.gatsbyjs.org"><img src="https://avatars1.githubusercontent.com/u/12551863?s=256&v=4" width="128"></a>
288
+ </td>
289
+ </tr>
290
+ <tr valign="middle"></tr>
291
+ <tr valign="middle">
292
+ <td width="20%" align="center" rowspan="2" colspan="2">
293
+ <a href="https://www.netlify.com">Netlify</a><br><br>
294
+ <!--OC has a sharper image-->
295
+ <a href="https://www.netlify.com"><img src="https://images.opencollective.com/netlify/4087de2/logo/256.png" width="128"></a>
296
+ </td>
297
+ <td width="10%" align="center">
298
+ <a href="https://www.coinbase.com">Coinbase</a><br><br>
299
+ <a href="https://www.coinbase.com"><img src="https://avatars1.githubusercontent.com/u/1885080?s=256&v=4" width="64"></a>
300
+ </td>
301
+ <td width="10%" align="center">
302
+ <a href="https://themeisle.com">ThemeIsle</a><br><br>
303
+ <a href="https://themeisle.com"><img src="https://avatars1.githubusercontent.com/u/58979018?s=128&v=4" width="64"></a>
304
+ </td>
305
+ <td width="10%" align="center">
306
+ <a href="https://expo.io">Expo</a><br><br>
307
+ <a href="https://expo.io"><img src="https://avatars1.githubusercontent.com/u/12504344?s=128&v=4" width="64"></a>
308
+ </td>
309
+ <td width="10%" align="center">
310
+ <a href="https://boostnote.io">Boost Note</a><br><br>
311
+ <a href="https://boostnote.io"><img src="https://images.opencollective.com/boosthub/6318083/logo/128.png" width="64"></a>
312
+ </td>
313
+ <td width="10%" align="center">
314
+ <a href="https://markdown.space">Markdown Space</a><br><br>
315
+ <a href="https://markdown.space"><img src="https://images.opencollective.com/markdown-space/e1038ed/logo/128.png" width="64"></a>
316
+ </td>
317
+ <td width="10%" align="center">
318
+ <a href="https://www.holloway.com">Holloway</a><br><br>
319
+ <a href="https://www.holloway.com"><img src="https://avatars1.githubusercontent.com/u/35904294?s=128&v=4" width="64"></a>
320
+ </td>
321
+ <td width="10%"></td>
322
+ <td width="10%"></td>
323
+ </tr>
324
+ <tr valign="middle">
325
+ <td width="100%" align="center" colspan="8">
326
+ <br>
327
+ <a href="https://opencollective.com/unified"><strong>You?</strong></a>
328
+ <br><br>
329
+ </td>
330
+ </tr>
331
+ </table>
332
+
333
+ ## Changelog
334
+
335
+ Detailed changes for each release are documented in [CHANGELOG.md](./CHANGELOG.md).
336
+
337
+ ## License
338
+
339
+ [MIT][] © [Remco Haszing][author]
340
+
341
+ [author]: https://github.com/remcohaszing
342
+
343
+ [backers-badge]: https://opencollective.com/unified/backers/badge.svg
344
+
345
+ [build]: https://github.com/mdx-js/mdx-analyzer/actions
346
+
347
+ [build-badge]: https://github.com/mdx-js/mdx-analyzer/workflows/main/badge.svg
348
+
349
+ [chat]: https://github.com/mdx-js/mdx/discussions
350
+
351
+ [chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg
352
+
353
+ [code of conduct]: https://github.com/mdx-js/.github/blob/main/code-of-conduct.md
354
+
355
+ [collective]: https://opencollective.com/unified
356
+
357
+ [contribute]: https://mdxjs.com/community/contribute/
358
+
359
+ [coverage]: https://codecov.io/github/mdx-js/mdx-analyzer
360
+
361
+ [coverage-badge]: https://img.shields.io/codecov/c/github/mdx-js/mdx-analyzer/main.svg
362
+
363
+ [downloads]: https://www.npmjs.com/package/@mdx-js/language-server
364
+
365
+ [downloads-badge]: https://img.shields.io/npm/dm/@mdx-js/language-server.svg
366
+
367
+ [jsdoc]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html
368
+
369
+ [lsp]: https://microsoft.github.io/language-server-protocol
370
+
371
+ [lsp commands]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#command
372
+
373
+ [lsp-mode]: https://github.com/emacs-lsp/lsp-mode
374
+
375
+ [mdx]: https://mdxjs.com
376
+
377
+ [mit]: LICENSE
378
+
379
+ [npm]: https://docs.npmjs.com/cli/install
380
+
381
+ [nvim-lspconfig]: https://github.com/neovim/nvim-lspconfig
382
+
383
+ [nvim-lspconfig mdx-analyzer]: https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md#mdx_analyzer
384
+
385
+ [sponsor]: https://mdxjs.com/community/sponsor/
386
+
387
+ [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
388
+
389
+ [support]: https://mdxjs.com/community/support/
390
+
391
+ [typescript]: https://typescriptlang.org
392
+
393
+ [volar]: https://volarjs.dev
394
+
395
+ [volar-service-markdown]: https://github.com/volarjs/services/tree/master/packages/markdown
396
+
397
+ [volar-service-typescript]: https://github.com/volarjs/services/tree/master/packages/typescript
398
+
399
+ [vscode]: https://code.visualstudio.com
400
+
401
+ [vscode-languageserver]: https://github.com/microsoft/vscode-languageserver-node/tree/main/server
402
+
403
+ [vscode-mdx]: https://marketplace.visualstudio.com/items?itemName=unifiedjs.vscode-mdx
@@ -0,0 +1,189 @@
1
+ /**
2
+ * @import {LanguageServiceContext} from '@volar/language-service'
3
+ * @import {LanguageSettings} from 'yaml-language-server'
4
+ */
5
+
6
+ import {URI, Utils} from 'vscode-uri'
7
+
8
+ /** @type {LanguageSettings} */
9
+ const defaultYamlSettings = {
10
+ completion: true,
11
+ customTags: [],
12
+ disableAdditionalProperties: false,
13
+ disableDefaultProperties: false,
14
+ flowMapping: 'allow',
15
+ flowSequence: 'allow',
16
+ format: true,
17
+ hover: true,
18
+ hoverAnchor: true,
19
+ hoverSchemaSource: true,
20
+ isKubernetes: false,
21
+ indentation: ' ',
22
+ keyOrdering: false,
23
+ parentSkeletonSelectedFirst: false,
24
+ validate: true,
25
+ yamlVersion: '1.2'
26
+ }
27
+
28
+ /**
29
+ * @param {unknown} value
30
+ * @returns {value is Record<string, unknown>}
31
+ */
32
+ function isRecord(value) {
33
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
34
+ }
35
+
36
+ /**
37
+ * @param {unknown} value
38
+ * @returns {string[]}
39
+ */
40
+ function normalizeFileMatch(value) {
41
+ if (typeof value === 'string') {
42
+ return [value]
43
+ }
44
+
45
+ if (Array.isArray(value)) {
46
+ return value.filter((item) => typeof item === 'string')
47
+ }
48
+
49
+ return []
50
+ }
51
+
52
+ /**
53
+ * @param {string} url
54
+ * @param {URI | undefined} workspaceUri
55
+ * @returns {string}
56
+ */
57
+ function normalizeSchemaUrl(url, workspaceUri) {
58
+ if (/^[a-z][a-z+.-]*:/i.test(url)) {
59
+ return url
60
+ }
61
+
62
+ if (!workspaceUri) {
63
+ return url
64
+ }
65
+
66
+ return Utils.resolvePath(workspaceUri, url).toString()
67
+ }
68
+
69
+ /**
70
+ * @param {unknown} workspaceFolder
71
+ * @returns {URI | undefined}
72
+ */
73
+ function normalizeWorkspaceUri(workspaceFolder) {
74
+ if (workspaceFolder instanceof URI) {
75
+ return workspaceFolder
76
+ }
77
+
78
+ if (typeof workspaceFolder === 'string') {
79
+ return URI.parse(workspaceFolder)
80
+ }
81
+
82
+ if (isRecord(workspaceFolder) && typeof workspaceFolder.uri === 'string') {
83
+ return URI.parse(workspaceFolder.uri)
84
+ }
85
+
86
+ if (
87
+ isRecord(workspaceFolder) &&
88
+ typeof workspaceFolder.external === 'string'
89
+ ) {
90
+ return URI.parse(workspaceFolder.external)
91
+ }
92
+ }
93
+
94
+ /**
95
+ * @param {string[]} fileMatch
96
+ * @returns {string[]}
97
+ */
98
+ function expandMdxFileMatchesForEmbeddedYaml(fileMatch) {
99
+ const expanded = new Set(fileMatch)
100
+
101
+ for (const pattern of fileMatch) {
102
+ if (pattern.endsWith('.mdx')) {
103
+ expanded.add(pattern.replace(/\.mdx$/u, '.yaml'))
104
+ expanded.add(pattern.replace(/\.mdx$/u, '.yml'))
105
+ expanded.add(
106
+ `volar-embedded-content://yaml/*${pattern.replaceAll('/', '*')}`
107
+ )
108
+ }
109
+ }
110
+
111
+ return [...expanded]
112
+ }
113
+
114
+ /**
115
+ * @param {unknown} rawSchemas
116
+ * @param {URI | undefined} workspaceUri
117
+ */
118
+ export function normalizeFrontmatterSchemas(rawSchemas, workspaceUri) {
119
+ if (!Array.isArray(rawSchemas)) {
120
+ return []
121
+ }
122
+
123
+ const schemas = []
124
+
125
+ for (const [index, entry] of rawSchemas.entries()) {
126
+ if (!isRecord(entry)) {
127
+ continue
128
+ }
129
+
130
+ const fileMatch = normalizeFileMatch(entry.fileMatch)
131
+ if (fileMatch.length === 0) {
132
+ continue
133
+ }
134
+
135
+ const schema = isRecord(entry.schema) ? entry.schema : undefined
136
+ const uri =
137
+ typeof entry.url === 'string'
138
+ ? normalizeSchemaUrl(entry.url, workspaceUri)
139
+ : schema
140
+ ? `mdx-frontmatter-inline-schema://${index}`
141
+ : undefined
142
+
143
+ if (!uri) {
144
+ continue
145
+ }
146
+
147
+ /** @type {{fileMatch: string[], uri: string, schema?: Record<string, unknown>}} */
148
+ const schemaSetting = {
149
+ fileMatch: expandMdxFileMatchesForEmbeddedYaml(fileMatch),
150
+ uri
151
+ }
152
+
153
+ if (schema) {
154
+ schemaSetting.schema = schema
155
+ }
156
+
157
+ schemas.push(schemaSetting)
158
+ }
159
+
160
+ return schemas
161
+ }
162
+
163
+ /**
164
+ * @param {LanguageServiceContext} context
165
+ * @param {unknown} fallbackWorkspaceFolder
166
+ * @returns {Promise<LanguageSettings>}
167
+ */
168
+ export async function getFrontmatterYamlSettings(
169
+ context,
170
+ fallbackWorkspaceFolder
171
+ ) {
172
+ const frontmatterConfig =
173
+ (await context.env.getConfiguration?.('mdx.frontmatter')) || {}
174
+ const workspaceFolder =
175
+ fallbackWorkspaceFolder ?? context.env.workspaceFolders?.[0]
176
+ const workspaceUri =
177
+ typeof workspaceFolder === 'string'
178
+ ? URI.parse(workspaceFolder)
179
+ : normalizeWorkspaceUri(workspaceFolder)
180
+ const rawSchemas = isRecord(frontmatterConfig)
181
+ ? frontmatterConfig.schemas
182
+ : undefined
183
+ const schemas = normalizeFrontmatterSchemas(rawSchemas, workspaceUri)
184
+
185
+ return {
186
+ ...defaultYamlSettings,
187
+ schemas
188
+ }
189
+ }
package/lib/index.js ADDED
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @import {VirtualCodePlugin} from '@mdx-js/language-service'
5
+ * @import {PluggableList} from 'unified'
6
+ */
7
+
8
+ import assert from 'node:assert'
9
+ import {createRequire} from 'node:module'
10
+ import path from 'node:path'
11
+ import process from 'node:process'
12
+ import {
13
+ createMdxLanguagePlugin,
14
+ createMdxServicePlugin,
15
+ resolvePlugins
16
+ } from '@mdx-js/language-service'
17
+ import {
18
+ createConnection,
19
+ createServer,
20
+ createTypeScriptProject,
21
+ loadTsdkByPath
22
+ } from '@volar/language-server/node.js'
23
+ import remarkFrontmatter from 'remark-frontmatter'
24
+ import remarkGfm from 'remark-gfm'
25
+ import {create as createMarkdownServicePlugin} from 'volar-service-markdown'
26
+ import {create as createTypeScriptServicePlugin} from 'volar-service-typescript'
27
+ import {create as createTypeScriptSyntacticServicePlugin} from 'volar-service-typescript/lib/plugins/syntactic.js'
28
+ import {create as createYamlServicePlugin} from 'volar-service-yaml'
29
+ import {getFrontmatterYamlSettings} from './frontmatter-schemas.js'
30
+
31
+ process.title = 'mdx-language-server'
32
+
33
+ /** @type {PluggableList} */
34
+ const defaultPlugins = [[remarkFrontmatter, ['toml', 'yaml']], remarkGfm]
35
+ const connection = createConnection()
36
+ const server = createServer(connection)
37
+ let tsEnabled = false
38
+
39
+ connection.onInitialize(async (parameters) => {
40
+ const tsdk = parameters.initializationOptions?.typescript?.tsdk
41
+ tsEnabled = Boolean(parameters.initializationOptions?.typescript?.enabled)
42
+ assert.ok(
43
+ typeof tsdk === 'string',
44
+ 'Missing initialization option typescript.tsdk'
45
+ )
46
+
47
+ const {typescript, diagnosticMessages} = loadTsdkByPath(
48
+ tsdk,
49
+ parameters.locale
50
+ )
51
+
52
+ return server.initialize(
53
+ parameters,
54
+ createTypeScriptProject(
55
+ typescript,
56
+ diagnosticMessages,
57
+ ({configFileName}) => ({
58
+ languagePlugins: getLanguagePlugins(configFileName)
59
+ })
60
+ ),
61
+ getLanguageServicePlugins()
62
+ )
63
+
64
+ function getLanguageServicePlugins() {
65
+ const plugins = [
66
+ createMarkdownServicePlugin({
67
+ getDiagnosticOptions(document, context) {
68
+ return context.env.getConfiguration?.('mdx.validate')
69
+ }
70
+ }),
71
+ createYamlServicePlugin({
72
+ documentSelector: ['yaml'],
73
+ getLanguageSettings(context) {
74
+ return getFrontmatterYamlSettings(
75
+ context,
76
+ parameters.workspaceFolders?.[0]?.uri ?? parameters.rootUri
77
+ )
78
+ }
79
+ }),
80
+ createMdxServicePlugin(/** @type {any} */ (connection.workspace))
81
+ ]
82
+
83
+ if (tsEnabled) {
84
+ plugins.push(...createTypeScriptServicePlugin(typescript, {}))
85
+ } else {
86
+ plugins.push(createTypeScriptSyntacticServicePlugin(typescript))
87
+ }
88
+
89
+ return plugins
90
+ }
91
+
92
+ /**
93
+ * @param {string | undefined} tsconfig
94
+ */
95
+ function getLanguagePlugins(tsconfig) {
96
+ /** @type {PluggableList | undefined} */
97
+ let remarkPlugins
98
+ /** @type {VirtualCodePlugin[] | undefined} */
99
+ let virtualCodePlugins
100
+ let checkMdx = false
101
+ let jsxImportSource = 'react'
102
+
103
+ if (tsconfig) {
104
+ const cwd = path.dirname(tsconfig)
105
+ const configSourceFile = typescript.readJsonConfigFile(
106
+ tsconfig,
107
+ typescript.sys.readFile
108
+ )
109
+ const commandLine = typescript.parseJsonSourceFileConfigFileContent(
110
+ configSourceFile,
111
+ typescript.sys,
112
+ cwd,
113
+ undefined,
114
+ tsconfig
115
+ )
116
+
117
+ const require = createRequire(tsconfig)
118
+
119
+ ;[remarkPlugins, virtualCodePlugins] = resolvePlugins(
120
+ commandLine.raw?.mdx,
121
+ (name) => require(name).default
122
+ )
123
+ checkMdx = Boolean(commandLine.raw?.mdx?.checkMdx)
124
+ jsxImportSource = commandLine.options.jsxImportSource || jsxImportSource
125
+ }
126
+
127
+ return [
128
+ createMdxLanguagePlugin(
129
+ remarkPlugins || defaultPlugins,
130
+ virtualCodePlugins,
131
+ checkMdx,
132
+ jsxImportSource
133
+ )
134
+ ]
135
+ }
136
+ })
137
+
138
+ connection.onInitialized(() => {
139
+ const extensions = ['mdx']
140
+ if (tsEnabled) {
141
+ extensions.push(
142
+ 'cjs',
143
+ 'cts',
144
+ 'js',
145
+ 'jsx',
146
+ 'json',
147
+ 'mjs',
148
+ 'mts',
149
+ 'ts',
150
+ 'tsx'
151
+ )
152
+ }
153
+
154
+ server.initialized()
155
+ server.fileWatcher.watchFiles([`**/*.{${extensions.join(',')}}`])
156
+ })
157
+
158
+ connection.listen()
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@nicodoggie/mdx-language-server",
3
+ "version": "0.6.3",
4
+ "type": "module",
5
+ "description": "A language server for MDX",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/mdx-js/mdx-analyzer.git",
9
+ "directory": "packages/language-server"
10
+ },
11
+ "homepage": "https://mdxjs.com",
12
+ "bugs": "https://github.com/mdx-js/mdx-analyzer/issues",
13
+ "author": "Remco Haszing <remcohaszing@gmail.com>",
14
+ "funding": "https://opencollective.com/unified",
15
+ "license": "MIT",
16
+ "exports": "./lib/index.js",
17
+ "bin": {
18
+ "mdx-language-server": "./lib/index.js"
19
+ },
20
+ "files": [
21
+ "lib"
22
+ ],
23
+ "keywords": [
24
+ "IntelliSense",
25
+ "mdx",
26
+ "typescript",
27
+ "unified"
28
+ ],
29
+ "scripts": {
30
+ "test-api": "node --test",
31
+ "test": "npm run test-api"
32
+ },
33
+ "dependencies": {
34
+ "@mdx-js/language-service": "0.7.3",
35
+ "@volar/language-server": "~2.4.0",
36
+ "remark-frontmatter": "^5.0.0",
37
+ "remark-gfm": "^4.0.0",
38
+ "volar-service-markdown": "0.0.65",
39
+ "volar-service-typescript": "0.0.65",
40
+ "volar-service-yaml": "0.0.71"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^22.0.0",
44
+ "@volar/test-utils": "~2.4.0",
45
+ "unified": "^11.0.0",
46
+ "vscode-uri": "^3.0.0"
47
+ }
48
+ }