CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jupyterlab--codemirror

CodeMirror 6 editor provider for JupyterLab with comprehensive language support, themes, extensions, and collaborative editing capabilities

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

mime-type-service.mddocs/

MIME Type Service

Service for resolving MIME types based on file extensions, language metadata, and content analysis for proper syntax highlighting.

Capabilities

CodeMirrorMimeTypeService

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"

File Extension Resolution

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 registry

Language Metadata Resolution

Integration 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"

Custom MIME Type Registration

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'
});

Integration with Editor

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!")'
);

Advanced MIME Type Detection

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;
  }
}

Types

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;
}

docs

editor-commands.md

editor-core.md

editor-factory.md

extension-system.md

index.md

language-support.md

mime-type-service.md

search-replace.md

special-extensions.md

theme-system.md

tile.json