or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdindex.mdlanguages.mdprocessor.mdrules.md
tile.json

processor.mddocs/

Processor

Processor for extracting fenced code blocks from Markdown files to enable individual linting of embedded JavaScript, TypeScript, and other code languages.

Capabilities

Markdown Processor

The processor extracts fenced code blocks from Markdown files and presents them as separate virtual files to ESLint for individual linting.

/**
 * ESLint processor for Markdown files
 * Extracts code blocks for individual linting
 */
interface Processor {
  /**
   * Processor metadata
   */
  meta: {
    name: "@eslint/markdown/markdown";
    version: "7.2.0";
  };

  /**
   * Extract code blocks from Markdown content
   * @param text - The Markdown file content
   * @param filename - The Markdown file name
   * @returns Array of extracted code blocks as virtual files
   */
  preprocess(text: string, filename: string): Array<{
    text: string;
    filename: string;
  }>;

  /**
   * Combine lint messages from code blocks back to original positions
   * @param messages - Array of message arrays from each code block
   * @param filename - The original Markdown file name
   * @returns Combined messages with corrected positions
   */
  postprocess(
    messages: Array<Message[]>,
    filename: string
  ): Message[];

  /**
   * Whether the processor supports ESLint's --fix flag
   */
  supportsAutofix: true;
}

Usage Example:

// Using the processor configuration
import markdown from "@eslint/markdown";

export default [
    ...markdown.configs.processor
];
// Manual processor configuration
import markdown from "@eslint/markdown";

export default [
    {
        plugins: { markdown }
    },
    {
        files: ["**/*.md"],
        processor: "markdown/markdown"
    },
    {
        files: ["**/*.md/*.js"],
        rules: {
            "no-console": "off",
            "no-undef": "off"
        }
    }
];

Code Block Extraction

The processor automatically extracts fenced code blocks from Markdown files based on their language identifiers.

Supported Code Block Formats:

```javascript
// This will be extracted as .js file
console.log("Hello, world!");
```

```typescript
// This will be extracted as .ts file
const message: string = "Hello, TypeScript!";
```

```jsx
// This will be extracted as .jsx file
const element = <div>Hello, React!</div>;
```

```python
# This will be extracted as .py file
print("Hello, Python!")
```

Virtual File Naming

Each extracted code block becomes a virtual file with a predictable naming pattern:

/**
 * Virtual filename pattern for extracted code blocks
 * Format: {original-filename}/{block-index}.{extension}
 * 
 * Examples:
 * - README.md/0.js (first JavaScript block in README.md)
 * - docs/api.md/1.ts (second TypeScript block in docs/api.md)
 * - guide.md/0.jsx (first JSX block in guide.md)
 */
interface VirtualFile {
  text: string;
  filename: string;
}

Language Mapping:

  • javascript, ecmascript.js
  • typescript.ts
  • jsx.jsx
  • tsx.tsx
  • python.py
  • java.java
  • c.c
  • cpp, c++.cpp
  • markdown, md.md

Configuration Comments

The processor supports ESLint configuration comments in HTML format immediately preceding code blocks:

<!-- eslint-disable no-console -->
<!-- eslint-env node -->
```javascript
console.log("This won't trigger no-console rule");
```

<!-- global jQuery -->
```javascript
jQuery("#element").hide();
```

Skipping Code Blocks

Use the special <!-- eslint-skip --> comment to prevent a code block from being processed:

<!-- eslint-skip -->
```javascript
{
    // This block won't be linted (useful for JSON with comments)
    "config": "value"
}
```
```

### Filename Meta Support

Code blocks can specify virtual filenames using the `filename` meta attribute:

````markdown
```javascript filename="src/utils.js"
export function helper() {
    return "Hello!";
}
```

This allows ESLint configurations to target specific virtual files:

// Target specific virtual files
export default [
    {
        files: ["*.md/**/utils.js"],
        rules: {
            "prefer-const": "error"
        }
    }
];

Auto-fixing Support

The processor supports ESLint's --fix flag and can automatically fix issues in code blocks:

eslint --fix README.md

Fixed code is properly merged back into the original Markdown content while preserving formatting and indentation.

Message Processing

Lint messages from code blocks are transformed back to the original Markdown file positions.

/**
 * ESLint message with position information
 */
interface Message {
  ruleId?: string;
  severity: 1 | 2;
  message: string;
  line: number;
  column: number;
  nodeType?: string;
  source?: string;
  endLine?: number;
  endColumn?: number;
  fix?: Fix;
}

/**
 * Auto-fix information
 */
interface Fix {
  range: [number, number];
  text: string;
}

Types

Processor Types

/**
 * Code block with metadata and range mapping
 */
interface Block extends Code {
  /**
   * Base indentation text for the code block
   */
  baseIndentText: string;

  /**
   * Configuration comments preceding the block
   */
  comments: string[];

  /**
   * Range mapping between Markdown and extracted code positions
   */
  rangeMap: RangeMap[];
}

/**
 * Position mapping between different coordinate systems
 */
interface RangeMap {
  /**
   * Indentation offset
   */
  indent: number;

  /**
   * JavaScript code position
   */
  js: number;

  /**
   * Markdown source position
   */
  md: number;
}

Processing State

/**
 * Internal state for tracking code blocks during processing
 */
interface ProcessorState {
  /**
   * Cache of extracted blocks by filename
   */
  blocksCache: Map<string, Block[]>;

  /**
   * Whether autofix is supported
   */
  supportsAutofix: boolean;

  /**
   * Rules that cannot be satisfied in code blocks
   */
  unsatisfiableRules: Set<string>;
}

Usage Patterns

Basic Processor Setup

import markdown from "@eslint/markdown";

export default [
    ...markdown.configs.processor
];

Advanced Processor Configuration

import markdown from "@eslint/markdown";

export default [
    {
        plugins: { markdown }
    },
    {
        // Enable processor for all .md files
        files: ["**/*.md"],
        processor: "markdown/markdown"
    },
    {
        // Configure JavaScript code blocks
        files: ["**/*.md/*.js"],
        languageOptions: {
            parserOptions: {
                ecmaFeatures: {
                    impliedStrict: true
                }
            }
        },
        rules: {
            "no-undef": "off",
            "no-unused-vars": "off",
            "no-console": "off"
        }
    },
    {
        // Configure TypeScript code blocks
        files: ["**/*.md/*.ts"],
        rules: {
            "@typescript-eslint/no-unused-vars": "off"
        }
    }
];

Targeting Specific Files

export default [
    {
        // Target specific virtual files
        files: ["README.md/*.js"],
        rules: {
            "prefer-const": "error"
        }
    },
    {
        // Target all JS blocks in docs directory
        files: ["docs/**/*.md/*.js"],
        rules: {
            "no-console": "warn"
        }
    }
];