CodeMirror 6 editor provider for JupyterLab with comprehensive language support, themes, extensions, and collaborative editing capabilities
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Service for resolving MIME types based on file extensions, language metadata, and content analysis for proper syntax highlighting.
Main service class for MIME type resolution and language detection.
/**
* The MIME type service for CodeMirror
* Resolves MIME types from file paths and language metadata
*/
class CodeMirrorMimeTypeService implements IEditorMimeTypeService {
constructor(languages: IEditorLanguageRegistry);
/**
* Returns a MIME type for the given language info
* Used with Jupyter notebook language metadata
*/
getMimeTypeByLanguage(info: nbformat.ILanguageInfoMetadata): string;
/**
* Returns a MIME type for the given file path
* Analyzes file extension and filename patterns
*/
getMimeTypeByFilePath(path: string): string;
}
interface IEditorMimeTypeService {
getMimeTypeByLanguage(info: nbformat.ILanguageInfoMetadata): string;
getMimeTypeByFilePath(path: string): string;
}Usage Examples:
import {
CodeMirrorMimeTypeService,
EditorLanguageRegistry
} from "@jupyterlab/codemirror";
// Create service with language registry
const languages = new EditorLanguageRegistry();
const mimeService = new CodeMirrorMimeTypeService(languages);
// Get MIME type from file path
const pythonMime = mimeService.getMimeTypeByFilePath('script.py');
console.log(pythonMime); // "text/x-python"
const jsMime = mimeService.getMimeTypeByFilePath('app.js');
console.log(jsMime); // "text/javascript"
const tsMime = mimeService.getMimeTypeByFilePath('component.tsx');
console.log(tsMime); // "text/typescript-jsx"
// Get MIME type from language metadata
const languageInfo = {
name: 'python',
version: '3.9.0',
mimetype: 'text/x-python',
file_extension: '.py'
};
const mimeType = mimeService.getMimeTypeByLanguage(languageInfo);
console.log(mimeType); // "text/x-python"MIME type detection based on file extensions and filename patterns.
// File extension to MIME type mapping examples
const extensionExamples = {
'.py': 'text/x-python',
'.js': 'text/javascript',
'.ts': 'text/typescript',
'.tsx': 'text/typescript-jsx',
'.jsx': 'text/jsx',
'.html': 'text/html',
'.css': 'text/css',
'.json': 'application/json',
'.md': 'text/markdown',
'.yml': 'text/yaml',
'.yaml': 'text/yaml',
'.xml': 'text/xml',
'.sql': 'text/sql',
'.sh': 'text/x-sh',
'.dockerfile': 'text/x-dockerfile',
'.java': 'text/x-java',
'.c': 'text/x-csrc',
'.cpp': 'text/x-c++src',
'.h': 'text/x-chdr',
'.php': 'text/x-php',
'.rb': 'text/x-ruby',
'.go': 'text/x-go',
'.rs': 'text/x-rustsrc',
'.swift': 'text/x-swift',
'.kt': 'text/x-kotlin'
};
// Special filename patterns
const filenamePatterns = {
'Dockerfile': 'text/x-dockerfile',
'Makefile': 'text/x-makefile',
'CMakeLists.txt': 'text/x-cmake',
'.gitignore': 'text/plain',
'.env': 'text/plain',
'requirements.txt': 'text/plain',
'package.json': 'application/json',
'tsconfig.json': 'application/json',
'.eslintrc.json': 'application/json'
};
// Usage in service
function detectMimeType(filePath: string): string {
const service = new CodeMirrorMimeTypeService(languages);
return service.getMimeTypeByFilePath(filePath);
}
// Examples
console.log(detectMimeType('script.py')); // "text/x-python"
console.log(detectMimeType('Dockerfile')); // "text/x-dockerfile"
console.log(detectMimeType('component.vue')); // Detected based on registryIntegration with Jupyter notebook language metadata format.
import { nbformat } from "@jupyterlab/nbformat";
// Language metadata examples
const pythonLanguageInfo: nbformat.ILanguageInfoMetadata = {
name: 'python',
version: '3.9.0',
mimetype: 'text/x-python',
file_extension: '.py',
pygments_lexer: 'ipython3',
codemirror_mode: 'python'
};
const javascriptLanguageInfo: nbformat.ILanguageInfoMetadata = {
name: 'javascript',
version: 'ES2020',
mimetype: 'text/javascript',
file_extension: '.js'
};
const rLanguageInfo: nbformat.ILanguageInfoMetadata = {
name: 'R',
version: '4.1.0',
mimetype: 'text/x-rsrc',
file_extension: '.r'
};
// Resolve MIME types from metadata
function resolveMimeFromMetadata(info: nbformat.ILanguageInfoMetadata): string {
const service = new CodeMirrorMimeTypeService(languages);
return service.getMimeTypeByLanguage(info);
}
// Priority order for resolution:
// 1. Explicit mimetype in metadata
// 2. Language name lookup in registry
// 3. File extension lookup
// 4. Fallback to 'text/plain'
const resolvedMime = resolveMimeFromMetadata(pythonLanguageInfo);
console.log(resolvedMime); // "text/x-python"Extending the service with custom MIME type mappings.
// Custom language registration affects MIME type resolution
const customLanguage: IEditorLanguage = {
name: 'mylang',
displayName: 'My Custom Language',
mime: ['text/x-mylang', 'application/x-mylang'],
extensions: ['.ml', '.mylang'],
filename: /^\.mylangrc$/
};
// Register custom language
languages.addLanguage(customLanguage);
// Now MIME service can resolve custom types
const customMime = mimeService.getMimeTypeByFilePath('script.ml');
console.log(customMime); // "text/x-mylang"
// Custom MIME type mapping function
function createCustomMimeService(
languages: IEditorLanguageRegistry,
customMappings: Record<string, string>
): CodeMirrorMimeTypeService {
class CustomMimeTypeService extends CodeMirrorMimeTypeService {
getMimeTypeByFilePath(path: string): string {
// Check custom mappings first
const extension = path.toLowerCase().split('.').pop();
if (extension && customMappings[`.${extension}`]) {
return customMappings[`.${extension}`];
}
// Check filename patterns
const filename = path.split('/').pop() || '';
if (customMappings[filename]) {
return customMappings[filename];
}
// Fall back to default behavior
return super.getMimeTypeByFilePath(path);
}
}
return new CustomMimeTypeService(languages);
}
// Use custom service
const customService = createCustomMimeService(languages, {
'.vue': 'text/x-vue',
'.svelte': 'text/x-svelte',
'.astro': 'text/x-astro',
'BUILD': 'text/x-bazel',
'WORKSPACE': 'text/x-bazel'
});Using the MIME type service to configure editor language support.
import {
CodeMirrorEditor,
CodeMirrorMimeTypeService,
EditorLanguageRegistry
} from "@jupyterlab/codemirror";
import { CodeEditor } from "@jupyterlab/codeeditor";
// Create integrated editor factory with MIME type service
class IntegratedEditorFactory {
private mimeService: CodeMirrorMimeTypeService;
private languages: EditorLanguageRegistry;
constructor() {
this.languages = new EditorLanguageRegistry();
this.mimeService = new CodeMirrorMimeTypeService(this.languages);
}
// Create editor with automatic language detection
createEditorForFile(filePath: string, content: string): CodeMirrorEditor {
const model = new CodeEditor.Model();
const host = document.createElement('div');
// Auto-detect MIME type
const mimeType = this.mimeService.getMimeTypeByFilePath(filePath);
// Create editor
const editor = new CodeMirrorEditor({
model,
host,
languages: this.languages
});
// Configure editor
model.sharedModel.setSource(content);
model.mimeType = mimeType;
return editor;
}
// Create editor from notebook language metadata
createEditorFromLanguageInfo(
info: nbformat.ILanguageInfoMetadata,
content: string
): CodeMirrorEditor {
const model = new CodeEditor.Model();
const host = document.createElement('div');
// Resolve MIME type from metadata
const mimeType = this.mimeService.getMimeTypeByLanguage(info);
const editor = new CodeMirrorEditor({
model,
host,
languages: this.languages
});
model.sharedModel.setSource(content);
model.mimeType = mimeType;
return editor;
}
}
// Usage
const factory = new IntegratedEditorFactory();
// Create editor for Python file
const pythonEditor = factory.createEditorForFile(
'analysis.py',
'import pandas as pd\ndf = pd.read_csv("data.csv")'
);
// Create editor from notebook metadata
const notebookEditor = factory.createEditorFromLanguageInfo(
{
name: 'python',
version: '3.9.0',
mimetype: 'text/x-python',
file_extension: '.py'
},
'print("Hello from notebook!")'
);Complex scenarios for MIME type detection and content analysis.
// Content-based MIME type detection
function detectMimeFromContent(content: string, filePath?: string): string {
const mimeService = new CodeMirrorMimeTypeService(languages);
// Start with file path if available
let detectedMime = filePath ? mimeService.getMimeTypeByFilePath(filePath) : 'text/plain';
// Override based on content patterns
if (content.startsWith('#!/usr/bin/env python') || content.startsWith('#!/usr/bin/python')) {
return 'text/x-python';
}
if (content.startsWith('#!/bin/bash') || content.startsWith('#!/usr/bin/bash')) {
return 'text/x-sh';
}
if (content.startsWith('#!/usr/bin/env node') || content.startsWith('#!/usr/bin/node')) {
return 'text/javascript';
}
if (content.includes('<!DOCTYPE html>')) {
return 'text/html';
}
if (content.trim().startsWith('{') || content.trim().startsWith('[')) {
try {
JSON.parse(content);
return 'application/json';
} catch {
// Not valid JSON, keep original detection
}
}
return detectedMime;
}
// Multi-language file detection (e.g., Vue, Svelte)
function detectMultiLanguageFile(filePath: string): string[] {
const extension = filePath.toLowerCase().split('.').pop();
switch (extension) {
case 'vue':
return ['text/html', 'text/javascript', 'text/css']; // Template, script, style
case 'svelte':
return ['text/html', 'text/javascript', 'text/css'];
case 'astro':
return ['text/html', 'text/javascript', 'text/css', 'text/markdown'];
case 'md':
case 'markdown':
return ['text/markdown', 'text/javascript', 'text/css']; // With code blocks
default:
return [new CodeMirrorMimeTypeService(languages).getMimeTypeByFilePath(filePath)];
}
}
// Context-aware MIME type service
class ContextAwareMimeTypeService extends CodeMirrorMimeTypeService {
private context: 'notebook' | 'file-editor' | 'console';
constructor(languages: IEditorLanguageRegistry, context: string) {
super(languages);
this.context = context as any;
}
getMimeTypeByFilePath(path: string): string {
const baseMime = super.getMimeTypeByFilePath(path);
// Adjust based on context
if (this.context === 'notebook') {
// In notebooks, prefer IPython for Python
if (baseMime === 'text/x-python') {
return 'text/x-ipython';
}
}
if (this.context === 'console') {
// In console, prefer REPL-friendly modes
if (baseMime === 'text/javascript') {
return 'text/javascript-repl';
}
}
return baseMime;
}
}interface IEditorMimeTypeService {
getMimeTypeByLanguage(info: nbformat.ILanguageInfoMetadata): string;
getMimeTypeByFilePath(path: string): string;
}
namespace nbformat {
interface ILanguageInfoMetadata {
name: string;
version?: string;
mimetype?: string;
file_extension?: string;
pygments_lexer?: string;
codemirror_mode?: string | Record<string, any>;
}
}
class CodeMirrorMimeTypeService implements IEditorMimeTypeService {
constructor(languages: IEditorLanguageRegistry);
getMimeTypeByLanguage(info: nbformat.ILanguageInfoMetadata): string;
getMimeTypeByFilePath(path: string): string;
}