0
# MIME Type Service
1
2
Service for resolving MIME types based on file extensions, language metadata, and content analysis for proper syntax highlighting.
3
4
## Capabilities
5
6
### CodeMirrorMimeTypeService
7
8
Main service class for MIME type resolution and language detection.
9
10
```typescript { .api }
11
/**
12
* The MIME type service for CodeMirror
13
* Resolves MIME types from file paths and language metadata
14
*/
15
class CodeMirrorMimeTypeService implements IEditorMimeTypeService {
16
constructor(languages: IEditorLanguageRegistry);
17
18
/**
19
* Returns a MIME type for the given language info
20
* Used with Jupyter notebook language metadata
21
*/
22
getMimeTypeByLanguage(info: nbformat.ILanguageInfoMetadata): string;
23
24
/**
25
* Returns a MIME type for the given file path
26
* Analyzes file extension and filename patterns
27
*/
28
getMimeTypeByFilePath(path: string): string;
29
}
30
31
interface IEditorMimeTypeService {
32
getMimeTypeByLanguage(info: nbformat.ILanguageInfoMetadata): string;
33
getMimeTypeByFilePath(path: string): string;
34
}
35
```
36
37
**Usage Examples:**
38
39
```typescript
40
import {
41
CodeMirrorMimeTypeService,
42
EditorLanguageRegistry
43
} from "@jupyterlab/codemirror";
44
45
// Create service with language registry
46
const languages = new EditorLanguageRegistry();
47
const mimeService = new CodeMirrorMimeTypeService(languages);
48
49
// Get MIME type from file path
50
const pythonMime = mimeService.getMimeTypeByFilePath('script.py');
51
console.log(pythonMime); // "text/x-python"
52
53
const jsMime = mimeService.getMimeTypeByFilePath('app.js');
54
console.log(jsMime); // "text/javascript"
55
56
const tsMime = mimeService.getMimeTypeByFilePath('component.tsx');
57
console.log(tsMime); // "text/typescript-jsx"
58
59
// Get MIME type from language metadata
60
const languageInfo = {
61
name: 'python',
62
version: '3.9.0',
63
mimetype: 'text/x-python',
64
file_extension: '.py'
65
};
66
67
const mimeType = mimeService.getMimeTypeByLanguage(languageInfo);
68
console.log(mimeType); // "text/x-python"
69
```
70
71
### File Extension Resolution
72
73
MIME type detection based on file extensions and filename patterns.
74
75
```typescript
76
// File extension to MIME type mapping examples
77
const extensionExamples = {
78
'.py': 'text/x-python',
79
'.js': 'text/javascript',
80
'.ts': 'text/typescript',
81
'.tsx': 'text/typescript-jsx',
82
'.jsx': 'text/jsx',
83
'.html': 'text/html',
84
'.css': 'text/css',
85
'.json': 'application/json',
86
'.md': 'text/markdown',
87
'.yml': 'text/yaml',
88
'.yaml': 'text/yaml',
89
'.xml': 'text/xml',
90
'.sql': 'text/sql',
91
'.sh': 'text/x-sh',
92
'.dockerfile': 'text/x-dockerfile',
93
'.java': 'text/x-java',
94
'.c': 'text/x-csrc',
95
'.cpp': 'text/x-c++src',
96
'.h': 'text/x-chdr',
97
'.php': 'text/x-php',
98
'.rb': 'text/x-ruby',
99
'.go': 'text/x-go',
100
'.rs': 'text/x-rustsrc',
101
'.swift': 'text/x-swift',
102
'.kt': 'text/x-kotlin'
103
};
104
105
// Special filename patterns
106
const filenamePatterns = {
107
'Dockerfile': 'text/x-dockerfile',
108
'Makefile': 'text/x-makefile',
109
'CMakeLists.txt': 'text/x-cmake',
110
'.gitignore': 'text/plain',
111
'.env': 'text/plain',
112
'requirements.txt': 'text/plain',
113
'package.json': 'application/json',
114
'tsconfig.json': 'application/json',
115
'.eslintrc.json': 'application/json'
116
};
117
118
// Usage in service
119
function detectMimeType(filePath: string): string {
120
const service = new CodeMirrorMimeTypeService(languages);
121
return service.getMimeTypeByFilePath(filePath);
122
}
123
124
// Examples
125
console.log(detectMimeType('script.py')); // "text/x-python"
126
console.log(detectMimeType('Dockerfile')); // "text/x-dockerfile"
127
console.log(detectMimeType('component.vue')); // Detected based on registry
128
```
129
130
### Language Metadata Resolution
131
132
Integration with Jupyter notebook language metadata format.
133
134
```typescript
135
import { nbformat } from "@jupyterlab/nbformat";
136
137
// Language metadata examples
138
const pythonLanguageInfo: nbformat.ILanguageInfoMetadata = {
139
name: 'python',
140
version: '3.9.0',
141
mimetype: 'text/x-python',
142
file_extension: '.py',
143
pygments_lexer: 'ipython3',
144
codemirror_mode: 'python'
145
};
146
147
const javascriptLanguageInfo: nbformat.ILanguageInfoMetadata = {
148
name: 'javascript',
149
version: 'ES2020',
150
mimetype: 'text/javascript',
151
file_extension: '.js'
152
};
153
154
const rLanguageInfo: nbformat.ILanguageInfoMetadata = {
155
name: 'R',
156
version: '4.1.0',
157
mimetype: 'text/x-rsrc',
158
file_extension: '.r'
159
};
160
161
// Resolve MIME types from metadata
162
function resolveMimeFromMetadata(info: nbformat.ILanguageInfoMetadata): string {
163
const service = new CodeMirrorMimeTypeService(languages);
164
return service.getMimeTypeByLanguage(info);
165
}
166
167
// Priority order for resolution:
168
// 1. Explicit mimetype in metadata
169
// 2. Language name lookup in registry
170
// 3. File extension lookup
171
// 4. Fallback to 'text/plain'
172
173
const resolvedMime = resolveMimeFromMetadata(pythonLanguageInfo);
174
console.log(resolvedMime); // "text/x-python"
175
```
176
177
### Custom MIME Type Registration
178
179
Extending the service with custom MIME type mappings.
180
181
```typescript
182
// Custom language registration affects MIME type resolution
183
const customLanguage: IEditorLanguage = {
184
name: 'mylang',
185
displayName: 'My Custom Language',
186
mime: ['text/x-mylang', 'application/x-mylang'],
187
extensions: ['.ml', '.mylang'],
188
filename: /^\.mylangrc$/
189
};
190
191
// Register custom language
192
languages.addLanguage(customLanguage);
193
194
// Now MIME service can resolve custom types
195
const customMime = mimeService.getMimeTypeByFilePath('script.ml');
196
console.log(customMime); // "text/x-mylang"
197
198
// Custom MIME type mapping function
199
function createCustomMimeService(
200
languages: IEditorLanguageRegistry,
201
customMappings: Record<string, string>
202
): CodeMirrorMimeTypeService {
203
204
class CustomMimeTypeService extends CodeMirrorMimeTypeService {
205
getMimeTypeByFilePath(path: string): string {
206
// Check custom mappings first
207
const extension = path.toLowerCase().split('.').pop();
208
if (extension && customMappings[`.${extension}`]) {
209
return customMappings[`.${extension}`];
210
}
211
212
// Check filename patterns
213
const filename = path.split('/').pop() || '';
214
if (customMappings[filename]) {
215
return customMappings[filename];
216
}
217
218
// Fall back to default behavior
219
return super.getMimeTypeByFilePath(path);
220
}
221
}
222
223
return new CustomMimeTypeService(languages);
224
}
225
226
// Use custom service
227
const customService = createCustomMimeService(languages, {
228
'.vue': 'text/x-vue',
229
'.svelte': 'text/x-svelte',
230
'.astro': 'text/x-astro',
231
'BUILD': 'text/x-bazel',
232
'WORKSPACE': 'text/x-bazel'
233
});
234
```
235
236
### Integration with Editor
237
238
Using the MIME type service to configure editor language support.
239
240
```typescript
241
import {
242
CodeMirrorEditor,
243
CodeMirrorMimeTypeService,
244
EditorLanguageRegistry
245
} from "@jupyterlab/codemirror";
246
import { CodeEditor } from "@jupyterlab/codeeditor";
247
248
// Create integrated editor factory with MIME type service
249
class IntegratedEditorFactory {
250
private mimeService: CodeMirrorMimeTypeService;
251
private languages: EditorLanguageRegistry;
252
253
constructor() {
254
this.languages = new EditorLanguageRegistry();
255
this.mimeService = new CodeMirrorMimeTypeService(this.languages);
256
}
257
258
// Create editor with automatic language detection
259
createEditorForFile(filePath: string, content: string): CodeMirrorEditor {
260
const model = new CodeEditor.Model();
261
const host = document.createElement('div');
262
263
// Auto-detect MIME type
264
const mimeType = this.mimeService.getMimeTypeByFilePath(filePath);
265
266
// Create editor
267
const editor = new CodeMirrorEditor({
268
model,
269
host,
270
languages: this.languages
271
});
272
273
// Configure editor
274
model.sharedModel.setSource(content);
275
model.mimeType = mimeType;
276
277
return editor;
278
}
279
280
// Create editor from notebook language metadata
281
createEditorFromLanguageInfo(
282
info: nbformat.ILanguageInfoMetadata,
283
content: string
284
): CodeMirrorEditor {
285
const model = new CodeEditor.Model();
286
const host = document.createElement('div');
287
288
// Resolve MIME type from metadata
289
const mimeType = this.mimeService.getMimeTypeByLanguage(info);
290
291
const editor = new CodeMirrorEditor({
292
model,
293
host,
294
languages: this.languages
295
});
296
297
model.sharedModel.setSource(content);
298
model.mimeType = mimeType;
299
300
return editor;
301
}
302
}
303
304
// Usage
305
const factory = new IntegratedEditorFactory();
306
307
// Create editor for Python file
308
const pythonEditor = factory.createEditorForFile(
309
'analysis.py',
310
'import pandas as pd\ndf = pd.read_csv("data.csv")'
311
);
312
313
// Create editor from notebook metadata
314
const notebookEditor = factory.createEditorFromLanguageInfo(
315
{
316
name: 'python',
317
version: '3.9.0',
318
mimetype: 'text/x-python',
319
file_extension: '.py'
320
},
321
'print("Hello from notebook!")'
322
);
323
```
324
325
### Advanced MIME Type Detection
326
327
Complex scenarios for MIME type detection and content analysis.
328
329
```typescript
330
// Content-based MIME type detection
331
function detectMimeFromContent(content: string, filePath?: string): string {
332
const mimeService = new CodeMirrorMimeTypeService(languages);
333
334
// Start with file path if available
335
let detectedMime = filePath ? mimeService.getMimeTypeByFilePath(filePath) : 'text/plain';
336
337
// Override based on content patterns
338
if (content.startsWith('#!/usr/bin/env python') || content.startsWith('#!/usr/bin/python')) {
339
return 'text/x-python';
340
}
341
342
if (content.startsWith('#!/bin/bash') || content.startsWith('#!/usr/bin/bash')) {
343
return 'text/x-sh';
344
}
345
346
if (content.startsWith('#!/usr/bin/env node') || content.startsWith('#!/usr/bin/node')) {
347
return 'text/javascript';
348
}
349
350
if (content.includes('<!DOCTYPE html>')) {
351
return 'text/html';
352
}
353
354
if (content.trim().startsWith('{') || content.trim().startsWith('[')) {
355
try {
356
JSON.parse(content);
357
return 'application/json';
358
} catch {
359
// Not valid JSON, keep original detection
360
}
361
}
362
363
return detectedMime;
364
}
365
366
// Multi-language file detection (e.g., Vue, Svelte)
367
function detectMultiLanguageFile(filePath: string): string[] {
368
const extension = filePath.toLowerCase().split('.').pop();
369
370
switch (extension) {
371
case 'vue':
372
return ['text/html', 'text/javascript', 'text/css']; // Template, script, style
373
case 'svelte':
374
return ['text/html', 'text/javascript', 'text/css'];
375
case 'astro':
376
return ['text/html', 'text/javascript', 'text/css', 'text/markdown'];
377
case 'md':
378
case 'markdown':
379
return ['text/markdown', 'text/javascript', 'text/css']; // With code blocks
380
default:
381
return [new CodeMirrorMimeTypeService(languages).getMimeTypeByFilePath(filePath)];
382
}
383
}
384
385
// Context-aware MIME type service
386
class ContextAwareMimeTypeService extends CodeMirrorMimeTypeService {
387
private context: 'notebook' | 'file-editor' | 'console';
388
389
constructor(languages: IEditorLanguageRegistry, context: string) {
390
super(languages);
391
this.context = context as any;
392
}
393
394
getMimeTypeByFilePath(path: string): string {
395
const baseMime = super.getMimeTypeByFilePath(path);
396
397
// Adjust based on context
398
if (this.context === 'notebook') {
399
// In notebooks, prefer IPython for Python
400
if (baseMime === 'text/x-python') {
401
return 'text/x-ipython';
402
}
403
}
404
405
if (this.context === 'console') {
406
// In console, prefer REPL-friendly modes
407
if (baseMime === 'text/javascript') {
408
return 'text/javascript-repl';
409
}
410
}
411
412
return baseMime;
413
}
414
}
415
```
416
417
## Types
418
419
```typescript { .api }
420
interface IEditorMimeTypeService {
421
getMimeTypeByLanguage(info: nbformat.ILanguageInfoMetadata): string;
422
getMimeTypeByFilePath(path: string): string;
423
}
424
425
namespace nbformat {
426
interface ILanguageInfoMetadata {
427
name: string;
428
version?: string;
429
mimetype?: string;
430
file_extension?: string;
431
pygments_lexer?: string;
432
codemirror_mode?: string | Record<string, any>;
433
}
434
}
435
436
class CodeMirrorMimeTypeService implements IEditorMimeTypeService {
437
constructor(languages: IEditorLanguageRegistry);
438
getMimeTypeByLanguage(info: nbformat.ILanguageInfoMetadata): string;
439
getMimeTypeByFilePath(path: string): string;
440
}
441
```