CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-remark-lint-maximum-line-length

remark-lint rule to warn when lines are too long

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

index.mddocs/

remark-lint-maximum-line-length

remark-lint-maximum-line-length is a specialized lint rule for the unified/remark ecosystem that validates maximum line length in Markdown documents. It intelligently handles various Markdown constructs by ignoring non-wrappable elements and provides detailed error reporting with precise character counts and removal suggestions.

Package Information

  • Package Name: remark-lint-maximum-line-length
  • Package Type: npm
  • Language: JavaScript (ES Modules)
  • Installation: npm install remark-lint-maximum-line-length
  • Dependencies: pluralize, mdast-util-mdx, unified-lint-rule, unist-util-position, unist-util-visit

Core Imports

import remarkLintMaximumLineLength from 'remark-lint-maximum-line-length';

For use with the unified processor:

import remarkLint from 'remark-lint';
import remarkLintMaximumLineLength from 'remark-lint-maximum-line-length';
import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';
import { unified } from 'unified';

Basic Usage

import remarkLint from 'remark-lint';
import remarkLintMaximumLineLength from 'remark-lint-maximum-line-length';
import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';
import { read } from 'to-vfile';
import { unified } from 'unified';
import { reporter } from 'vfile-reporter';

const file = await read('example.md');

await unified()
  .use(remarkParse)
  .use(remarkLint)
  .use(remarkLintMaximumLineLength) // Default: 60 characters
  .use(remarkStringify)
  .process(file);

console.error(reporter(file));

With custom configuration:

// Configure maximum line length to 120 characters
await unified()
  .use(remarkParse)
  .use(remarkLint)
  .use(remarkLintMaximumLineLength, 120)
  .use(remarkStringify)
  .process(file);

// Configure with options object
await unified()
  .use(remarkParse)
  .use(remarkLint)
  .use(remarkLintMaximumLineLength, {
    size: 100,
    stringLength: (value) => value.length // Custom length calculation
  })
  .use(remarkStringify)
  .process(file);

Architecture

The lint rule follows the unified ecosystem patterns:

  • Lint Rule Integration: Built with unified-lint-rule framework for seamless integration
  • AST Processing: Uses mdast (Markdown Abstract Syntax Tree) for intelligent content analysis
  • Smart Ignoring: Automatically excludes non-wrappable content (code blocks, HTML, headings, tables, definitions, math, MDX)
  • Inline Element Handling: Special logic for inline code, images, and links that span across line boundaries
  • Error Reporting: Leverages unified's VFile messaging system for detailed diagnostics

Capabilities

Line Length Validation

Validates that lines in Markdown documents don't exceed a specified character limit with intelligent content-aware processing.

/**
 * remark-lint rule to warn when lines are too long
 * @param options - Configuration options (number or Options object)
 * @returns Transform function for unified processor
 */
function remarkLintMaximumLineLength(
  options?: Options | number
): Transformer<Root, Root>;

Parameters:

  • options (Options | number, optional): Configuration options (default: 60)

Behavior:

  • Ignores non-wrappable elements: code blocks, HTML, headings, tables, definitions, math expressions, MDX
  • Handles inline elements (code, images, links) that cross line boundaries intelligently
  • Reports violations with exact character counts and removal suggestions
  • Supports custom string length calculation functions

Configuration Options

Configure the maximum line length and string measurement behavior.

/**
 * Configuration options for line length validation
 */
interface Options {
  /**
   * Preferred maximum line length in characters
   * @default 60
   */
  size?: number;
  
  /**
   * Custom function to calculate string length
   * Useful for Unicode handling or visual width calculation
   * @param value - The string to measure
   * @returns The calculated length
   */
  stringLength?: (value: string) => number;
}

Usage Examples:

Simple numeric configuration:

// Set maximum line length to 120 characters  
.use(remarkLintMaximumLineLength, 120)

Options object configuration:

// Advanced configuration with custom string length function
.use(remarkLintMaximumLineLength, {
  size: 100,
  stringLength: (value) => {
    // Example: Use visual width for CJK characters
    return Array.from(value).length;
  }
})

Error Messages

The rule generates detailed error messages for lines that exceed the maximum length.

Error Message Format:

Unexpected `{actualLength}` character line, expected at most `{maxLength}` characters, remove `{difference}` character{s}

Example Output:

1:24: Unexpected `23` character line, expected at most `20` characters, remove `3` characters
4:37: Unexpected `36` character line, expected at most `20` characters, remove `16` characters

Smart Content Handling

The rule intelligently handles different Markdown constructs:

Ignored Elements (Non-wrappable):

  • Code blocks (fenced and indented)
  • HTML elements
  • Headings
  • Tables
  • Definitions/reference links
  • Math expressions (with remark-math)
  • MDX elements: mdxjsEsm, mdxFlowExpression, mdxTextExpression (with remark-mdx)
  • YAML/TOML frontmatter

Special Handling (Inline Elements):

  • Inline code spans
  • Images
  • Links and autolinks

These elements are allowed to exceed the line limit when they:

  1. Start before the maximum column and end after it
  2. Contain no internal whitespace
  3. Don't have following content with break opportunities on the same line

Types

/**
 * Root node type from mdast
 */
interface Root {
  type: 'root';
  children: Array<Content>;
}

/**
 * Transformer function type from unified
 */
type Transformer<In, Out> = (tree: In, file: VFile) => Out | undefined | void;

/**
 * Virtual file type from unified ecosystem
 */
interface VFile {
  // Core VFile properties and methods
  message(reason: string, position?: Position): VFileMessage;
  fail(reason: string, position?: Position): never;
}

/**
 * Position information for error reporting
 */
interface Position {
  line: number;
  column: number;
  offset?: number;
}

Integration Examples

CLI Usage

# Basic usage with remark CLI
remark --frail --use remark-lint --use remark-lint-maximum-line-length .

# With custom configuration in package.json
{
  "remarkConfig": {
    "plugins": [
      "remark-lint",
      ["remark-lint-maximum-line-length", 120]
    ]
  }
}

Programmatic Usage with Configuration

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkLint from 'remark-lint';
import remarkLintMaximumLineLength from 'remark-lint-maximum-line-length';
import { read } from 'to-vfile';
import { reporter } from 'vfile-reporter';

// Process multiple files with different configurations
const files = ['README.md', 'CHANGELOG.md', 'docs/api.md'];

for (const filePath of files) {
  const file = await read(filePath);
  
  const processor = unified()
    .use(remarkParse)
    .use(remarkLint)
    .use(remarkLintMaximumLineLength, {
      size: filePath.includes('CHANGELOG') ? 120 : 60,
      stringLength: (value) => {
        // Custom logic for different file types
        return Array.from(value).length;
      }
    });
    
  await processor.process(file);
  
  if (file.messages.length > 0) {
    console.error(`Issues in ${filePath}:`);
    console.error(reporter(file));
  }
}

Integration with Other remark-lint Rules

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkLint from 'remark-lint';
import remarkLintMaximumLineLength from 'remark-lint-maximum-line-length';
import remarkLintNoHeadingPunctuation from 'remark-lint-no-heading-punctuation';
import remarkLintListItemIndent from 'remark-lint-list-item-indent';

const processor = unified()
  .use(remarkParse)
  .use(remarkLint)
  .use(remarkLintMaximumLineLength, {
    size: 100,
    stringLength: (line) => {
      // Account for tab characters as 4 spaces
      return line.replace(/\t/g, '    ').length;
    }
  })
  .use(remarkLintNoHeadingPunctuation)
  .use(remarkLintListItemIndent, 'space');

docs

index.md

tile.json