or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

field-extensions.mdindex.mdnode-creation.mdplugin-configuration.mdschema-customization.md
tile.json

field-extensions.mddocs/

GraphQL Field Extensions

Extends the MarkdownRemark GraphQL type with rich computed fields for HTML rendering, excerpts, headings, table of contents, and content analysis.

Capabilities

Field Extension Function

Main function that adds computed fields to the MarkdownRemark GraphQL type. This function is exported from the plugin and called by Gatsby during schema building.

/**
 * Extends MarkdownRemark GraphQL type with computed fields
 * @param context - Gatsby GraphQL context
 * @param context.type - GraphQL type being extended
 * @param context.basePath - Base path for URL resolution
 * @param context.getNode - Function to get nodes by ID
 * @param context.getNodesByType - Function to get nodes by type
 * @param context.cache - Gatsby cache instance
 * @param context.getCache - Function to get named cache instances
 * @param context.reporter - Gatsby reporter for logging
 * @param pluginOptions - Plugin configuration options
 * @returns Promise resolving to field definitions object
 */
function setFieldsOnGraphQLNodeType(
  {
    type,
    basePath,
    getNode,
    getNodesByType,
    cache,
    getCache,
    reporter,
    ...rest
  },
  pluginOptions
): Promise<Object>;

GraphQL Fields

HTML Rendering

Converts markdown content to HTML with full remark plugin processing.

html: {
  type: `String`,
  /**
   * Resolves markdown content to HTML
   * @param markdownNode - The MarkdownRemark node
   * @param opt - GraphQL field options (unused)
   * @param context - GraphQL execution context
   * @returns Promise resolving to HTML string
   */
  async resolve(markdownNode, opt, context): Promise<string>
}

Usage Example:

{
  markdownRemark {
    html
  }
}

HTML AST

Provides the HTML Abstract Syntax Tree for programmatic HTML manipulation.

htmlAst: {
  type: `JSON`,
  /**
   * Resolves markdown content to HTML AST
   * @param markdownNode - The MarkdownRemark node
   * @param opt - GraphQL field options (unused)
   * @param context - GraphQL execution context
   * @returns Promise resolving to HTML AST (HAST)
   */
  async resolve(markdownNode, opt, context): Promise<Object>
}

Usage Example:

{
  markdownRemark {
    htmlAst
  }
}

Excerpt Generation

Generates content excerpts in multiple formats with customizable length and truncation.

excerpt: {
  type: `String`,
  args: {
    /**
     * Maximum length of excerpt in characters
     * @default 140
     */
    pruneLength: {
      type: `Int`,
      defaultValue: 140,
    },
    /**
     * Whether to truncate at exact length vs word boundaries
     * @default false
     */
    truncate: {
      type: `Boolean`,
      defaultValue: false,
    },
    /**
     * Output format for the excerpt
     * @default PLAIN
     */
    format: {
      type: `MarkdownExcerptFormats`,
      defaultValue: `PLAIN`,
    },
  },
  /**
   * Generates excerpt from markdown content
   * @param markdownNode - The MarkdownRemark node
   * @param options - Excerpt generation options
   * @param context - GraphQL execution context
   * @returns Promise resolving to excerpt string
   */
  resolve(markdownNode, { format, pruneLength, truncate }, context): Promise<string>
}

Usage Examples:

# Plain text excerpt (default)
{
  markdownRemark {
    excerpt(pruneLength: 200)
  }
}

# HTML excerpt preserving markup
{
  markdownRemark {
    excerpt(format: HTML, pruneLength: 300, truncate: true)
  }
}

# Markdown excerpt with original syntax
{
  markdownRemark {
    excerpt(format: MARKDOWN)
  }
}

Excerpt AST

Provides the Abstract Syntax Tree for the excerpt content.

excerptAst: {
  type: `JSON`,
  args: {
    pruneLength: {
      type: `Int`,
      defaultValue: 140,
    },
    truncate: {
      type: `Boolean`,
      defaultValue: false,
    },
  },
  /**
   * Generates excerpt AST from markdown content
   * @param markdownNode - The MarkdownRemark node
   * @param options - Excerpt generation options
   * @param context - GraphQL execution context
   * @returns Promise resolving to excerpt AST
   */
  async resolve(markdownNode, { pruneLength, truncate }, context): Promise<Object>
}

Headings Extraction

Extracts heading information with optional depth filtering.

headings: {
  type: [`MarkdownHeading`],
  args: {
    /**
     * Filter headings by specific depth level
     */
    depth: `MarkdownHeadingLevels`,
  },
  /**
   * Extracts headings from markdown content
   * @param markdownNode - The MarkdownRemark node
   * @param options - Heading extraction options
   * @param context - GraphQL execution context
   * @returns Promise resolving to array of heading objects
   */
  async resolve(markdownNode, { depth }, context): Promise<MarkdownHeading[]>
}

Usage Examples:

# All headings
{
  markdownRemark {
    headings {
      id
      value
      depth
    }
  }
}

# Only h2 headings
{
  markdownRemark {
    headings(depth: h2) {
      value
    }
  }
}

Reading Time Calculation

Calculates estimated reading time based on content length and language.

timeToRead: {
  type: `Int`,
  /**
   * Calculates reading time in minutes
   * @param markdownNode - The MarkdownRemark node
   * @param opt - GraphQL field options (unused)
   * @param context - GraphQL execution context
   * @returns Promise resolving to reading time in minutes
   */
  async resolve(markdownNode, opt, context): Promise<number>
}

Reading Time Algorithm:

  • Base WPM: 265 words per minute
  • CJK Characters: Multiplied by 0.56 (average 2 characters per word)
  • Minimum: Always returns at least 1 minute

Usage Example:

{
  markdownRemark {
    timeToRead
  }
}

Table of Contents

Generates HTML table of contents with customizable depth and URL resolution.

tableOfContents: {
  type: `String`,
  args: {
    /**
     * Generate absolute URLs instead of relative anchors
     * @default false
     */
    absolute: {
      type: `Boolean`,
      defaultValue: false,
    },
    /**
     * Path to field containing slug for absolute URLs
     * @default ""
     */
    pathToSlugField: {
      type: `String`,
      defaultValue: ``,
    },
    /**
     * Maximum heading depth to include
     */
    maxDepth: `Int`,
    /**
     * Start ToC from this heading onwards
     */
    heading: `String`,
  },
  /**
   * Generates table of contents HTML
   * @param markdownNode - The MarkdownRemark node
   * @param args - ToC generation options
   * @param context - GraphQL execution context
   * @returns Promise resolving to HTML table of contents
   */
  resolve(markdownNode, args, context): Promise<string>
}

Usage Examples:

# Basic table of contents
{
  markdownRemark {
    tableOfContents
  }
}

# Customized table of contents
{
  markdownRemark {
    tableOfContents(
      absolute: true
      pathToSlugField: "frontmatter.slug"
      maxDepth: 3
      heading: "Contents"
    )
  }
}

Word Count Analysis

Provides detailed word, sentence, and paragraph counts using natural language processing.

wordCount: {
  type: `MarkdownWordCount`,
  /**
   * Analyzes content for word count statistics
   * @param markdownNode - The MarkdownRemark node
   * @returns Word count analysis object
   */
  resolve(markdownNode): MarkdownWordCount
}

Analysis Process:

  • Uses unified with remark-parse and remark-retext
  • Processes with retext-english for language understanding
  • Counts ParagraphNode, SentenceNode, and WordNode types

Usage Example:

{
  markdownRemark {
    wordCount {
      words
      sentences
      paragraphs
    }
  }
}

Caching System

The field extension system includes sophisticated caching to optimize build performance:

Cache Types

const CACHE_TYPE_AST = `ast`;
const CACHE_TYPE_HTMLAST = `html-ast`;
const CACHE_TYPE_HTML = `html`;
const CACHE_TYPE_HEADINGS = `headings`;
const CACHE_TYPE_TOC = `toc`;
const CACHE_TYPE_NODE_DEPS = `node-dependencies`;

Cache Invalidation

The system tracks file dependencies and invalidates caches when:

  • Source markdown content changes
  • Plugin configuration changes
  • Dependent files (images, includes) change
  • Path prefix changes

This ensures accurate builds while maximizing performance through intelligent caching.