1
+ import { autocompletion } from "@codemirror/autocomplete" ;
1
2
import { markdown } from "@codemirror/lang-markdown" ;
2
3
import { tooltips } from "@codemirror/view" ;
3
4
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js" ;
@@ -9,7 +10,17 @@ import type {
9
10
PromptMessage ,
10
11
} from "@modelcontextprotocol/sdk/types.js" ;
11
12
import { EditorView , basicSetup } from "codemirror" ;
12
- import { extractResources , mcpExtension } from "../src/mcp" ;
13
+ import {
14
+ extractResources ,
15
+ hoverResource ,
16
+ resourceCompletion ,
17
+ resourceInputFilter ,
18
+ resourceTheme ,
19
+ resourcesField ,
20
+ } from "../src" ;
21
+ import type { Resource } from "../src" ;
22
+ import { mcpExtension } from "../src/mcp" ;
23
+ import { resourceDecorations } from "../src/resources/decoration" ;
13
24
14
25
class DemoTransport implements Transport {
15
26
mockPrompts = [
@@ -196,15 +207,17 @@ Try typing @ to see MCP completions!
196
207
const formattedResources = resources
197
208
. map (
198
209
( { resource } ) =>
199
- `${ resource . uri } (${ resource . type } ): ${ resource . description || resource . name } ` ,
210
+ `<resource> ${ resource . uri } (${ resource . type } ): ${ resource . description || resource . name } </resource> ` ,
200
211
)
201
212
. join ( "\n" ) ;
202
213
203
214
if ( formattedResources . length === 0 ) {
204
215
prompt . textContent = "No resources found" ;
205
216
} else {
206
217
prompt . textContent = `
218
+ <doc>
207
219
${ editor . state . doc . toString ( ) }
220
+ </doc>
208
221
209
222
Resources:
210
223
${ formattedResources }
@@ -214,5 +227,125 @@ ${formattedResources}
214
227
document . querySelector ( "#editor" ) ?. parentElement ?. appendChild ( button ) ;
215
228
document . querySelector ( "#editor" ) ?. parentElement ?. appendChild ( prompt ) ;
216
229
217
- return { editor, promptEditor } ;
230
+ // Create a demo using lower-level primitives without MCP extension
231
+ const mockResources : Resource [ ] = [
232
+ {
233
+ name : "userGuide" ,
234
+ uri : "file://docs/user-guide.md" ,
235
+ mimeType : "text/markdown" ,
236
+ description : "Complete user guide with examples and best practices" ,
237
+ type : "file" ,
238
+ data : { } ,
239
+ } ,
240
+ {
241
+ name : "apiDocs" ,
242
+ uri : "file://docs/api.md" ,
243
+ mimeType : "text/markdown" ,
244
+ description : "API reference documentation" ,
245
+ type : "file" ,
246
+ data : { } ,
247
+ } ,
248
+ {
249
+ name : "config" ,
250
+ uri : "var://app/config" ,
251
+ mimeType : "application/json" ,
252
+ description : "Application configuration object" ,
253
+ type : "variable" ,
254
+ data : { } ,
255
+ } ,
256
+ {
257
+ name : "processData" ,
258
+ uri : "function://utils/processData" ,
259
+ mimeType : "application/javascript" ,
260
+ description : "Processes user input data and returns formatted results" ,
261
+ type : "function" ,
262
+ data : { } ,
263
+ } ,
264
+ ] ;
265
+
266
+ const markdownLanguage = markdown ( ) ;
267
+
268
+ // Create extensions using primitives
269
+ const primitivesExtensions = [
270
+ basicSetup ,
271
+ markdownLanguage ,
272
+ resourcesField ,
273
+ resourceDecorations ,
274
+ resourceInputFilter ,
275
+ autocompletion ( {
276
+ override : [
277
+ resourceCompletion (
278
+ async ( ) => mockResources ,
279
+ // Custom formatter for completions
280
+ ( resource ) => ( {
281
+ detail : `${ resource . mimeType || "unknown" } - ${ resource . uri } ` ,
282
+ boost : resource . description ? 90 : 50 ,
283
+ } ) ,
284
+ ) ,
285
+ ] ,
286
+ } ) ,
287
+ hoverResource ( {
288
+ createTooltip : ( resource ) => {
289
+ const dom = document . createElement ( "div" ) ;
290
+ dom . className = "cm-tooltip-cursor cm-tooltip-below" ;
291
+ dom . style . padding = "8px" ;
292
+ dom . style . backgroundColor = "#f8f9fa" ;
293
+ dom . style . border = "1px solid #dee2e6" ;
294
+ dom . style . borderRadius = "4px" ;
295
+ dom . style . maxWidth = "300px" ;
296
+
297
+ const title = document . createElement ( "strong" ) ;
298
+ title . textContent = resource . name ;
299
+ title . style . color = "#495057" ;
300
+ dom . appendChild ( title ) ;
301
+
302
+ const uri = document . createElement ( "div" ) ;
303
+ uri . style . fontSize = "0.85em" ;
304
+ uri . style . color = "#6c757d" ;
305
+ uri . style . fontFamily = "monospace" ;
306
+ uri . textContent = resource . uri ;
307
+ dom . appendChild ( uri ) ;
308
+
309
+ if ( resource . description ) {
310
+ const desc = document . createElement ( "div" ) ;
311
+ desc . style . marginTop = "6px" ;
312
+ desc . style . fontSize = "0.9em" ;
313
+ desc . textContent = resource . description ;
314
+ dom . appendChild ( desc ) ;
315
+ }
316
+
317
+ if ( resource . mimeType ) {
318
+ const mime = document . createElement ( "div" ) ;
319
+ mime . style . marginTop = "4px" ;
320
+ mime . style . fontSize = "0.8em" ;
321
+ mime . style . color = "#868e96" ;
322
+ mime . textContent = `Type: ${ resource . mimeType } ` ;
323
+ dom . appendChild ( mime ) ;
324
+ }
325
+
326
+ return { dom } ;
327
+ } ,
328
+ } ) ,
329
+ resourceTheme ,
330
+ tooltips ( ) ,
331
+ ] ;
332
+
333
+ const primitivesEditor = new EditorView ( {
334
+ doc : `# Primitives Demo
335
+
336
+ This editor demonstrates using the lower-level exported primitives:
337
+ - \`resourceCompletion\` for autocomplete functionality
338
+ - \`hoverResource\` for hover tooltips
339
+ - \`resourcesField\` for state management
340
+ - \`resourceTheme\` for styling
341
+ - Standard CodeMirror markdown support
342
+
343
+ Try typing @ to see resource completions, then hover over the inserted resources:
344
+
345
+ @` ,
346
+ extensions : primitivesExtensions ,
347
+ parent : document . querySelector ( "#primitives-editor" ) ?? undefined ,
348
+ } ) ;
349
+
350
+ return { editor, promptEditor, primitivesEditor } ;
218
351
} ) ( ) ;
0 commit comments