Skip to the content.

Compiler Reference

The dotchalk compiler transforms .chalk source code into structured JSON documents. This reference covers the two main compilation functions.

Installation & Importing

ESM (ECMAScript Modules)

// Default import (namespace)
import chalk from '@jackhgns/dotchalk';

chalk.compile(source, library);
chalk.library();

// Named imports
import { compile, compileFile, library, validateLibrary } from '@jackhgns/dotchalk';

// Type imports
import type { Library, Document, Element, Attribute, CompileResult } from '@jackhgns/dotchalk';

CommonJS

const chalk = require('@jackhgns/dotchalk');

chalk.compile(source, library);
chalk.library();

Both import styles provide identical functionality. ESM is recommended for new projects as it enables tree-shaking and static analysis.

Table of Contents

compile

Compiles .chalk source code into a structured document.

Important: The compile function automatically validates the library before compilation. If the library is invalid, compilation will fail immediately with a validation error. This ensures that only well-formed libraries can be used for compilation.

Signature:

chalk.compile(
  source: string,
  library: Library,
  documentClass?: string,
  inputConstants?: Record<string, any>,
  files?: FileMap
): CompileResult

Parameters:

Returns: CompileResult with compiled document or error

Example:

import chalk from '@jackhgns/dotchalk';

const source = `
*(title: Hello World; author: John Doe)

This is a **paragraph** with formatting.
`;

const result = chalk.compile(source, myLibrary);

if (result.ok) {
  console.log('Document:', result.data);
  console.log('Class:', result.data.class);
  console.log('Header:', result.data.header);
  console.log('Body:', result.data.body);
} else {
  console.error('Compilation failed:', result.error);
}

With Document Class:

// Compile as a tutorial document
const result = chalk.compile(source, myLibrary, 'tutorial');

// Compile as an article document
const result = chalk.compile(source, myLibrary, 'article');

With Input Constants:

const result = chalk.compile(source, myLibrary, undefined, {
  version: '1.0.0',
  author: 'Jane Smith',
  buildDate: new Date().toISOString()
});

// Constants can be used in the source as {{version}}, {{author}}, {{buildDate}}

In-Memory File Resolution

The compile function supports resolving @include directives from in-memory file maps instead of the filesystem. This is useful for:

Signature:

chalk.compile(
  source: string,
  library: Library,
  documentClass?: string,
  inputConstants?: Record<string, any>,
  files?: Record<string, string>  // FileMap
): CompileResult

Example: Basic In-Memory Include

const result = chalk.compile(
  '@include(src: header.part.chalk)',
  myLibrary,
  undefined,
  undefined,
  {
    'header.part.chalk': 'para{Welcome to my article}'
  }
);

if (result.ok) {
  console.log('Included header:', result.data.body[0].body);
}

Example: Nested In-Memory Includes

const result = chalk.compile(
  '@include(src: components/main.part.chalk)',
  myLibrary,
  undefined,
  undefined,
  {
    'components/main.part.chalk': '@include(src: header.part.chalk)\n\nMain content',
    'components/header.part.chalk': 'para{Site Header}'
  }
);

Example: Mixed Filesystem and In-Memory

When using compile() with a files map, includes are resolved first from the map, then fall back to the filesystem if not found:

// Files in the map are used; others are read from disk
const result = chalk.compile(
  '@include(src: header.part.chalk)\n@include(src: footer.part.chalk)',
  myLibrary,
  undefined,
  undefined,
  {
    'header.part.chalk': 'para{In-memory header}'
    // footer.part.chalk will be read from disk if it exists
  }
);

Important Notes:

compileFile

Compiles a .chalk file and all its dependencies referenced via @include metaelements.

Important: Like compile, the compileFile function automatically validates the library before compilation. If the library is invalid, compilation will fail immediately with a validation error.

This function:

  1. Validates the library definition
  2. Resolves the main file path
  3. Builds a dependency graph of all @include references
  4. Compiles files in dependency order (dependencies first)
  5. Returns the compiled main document

Signature:

chalk.compileFile(
  mainFile: string,
  baseDir: string,
  library: Library,
  documentClass?: string,
  inputConstants?: Record<string, any>
): CompileResult

Parameters:

Returns: CompileResult with compiled document or error

Example:

import chalk from '@jackhgns/dotchalk';
import path from 'path';

const result = chalk.compileFile(
  'article.chalk',
  __dirname,
  myLibrary
);

if (result.ok) {
  console.log('Compiled document:', result.data);
} else {
  console.error('Compilation failed:', result.error);
}

With Document Class:

// Compile as a tutorial
const result = chalk.compileFile(
  'guide.chalk',
  __dirname,
  myLibrary,
  'tutorial'
);

With Input Constants:

const result = chalk.compileFile(
  'article.chalk',
  path.join(__dirname, 'content'),
  myLibrary,
  undefined,
  {
    version: '2.0.0',
    buildDate: new Date().toISOString()
  }
);

File Structure Example:

project/
├── content/
│   ├── main.chalk       # Uses @include(src: header.part.chalk)
│   ├── header.part.chalk    # Reusable header content
│   └── footer.part.chalk    # Reusable footer content
└── compile.js

main.chalk:

*(title: My Article; author: Jane Doe)

@include(src: header.part.chalk)

This is the main content.

@include(src: footer.part.chalk)

Important Notes:

CompileResult

The return type for compilation functions, providing either a successful result or an error.

For complete type definitions, see the Type Reference page.

Type Definition:

type CompileResult = 
  | { ok: true; data: ChalkDocument }
  | { ok: false; error: string };

Handling Results:

const result = chalk.compile(source, library);

if (result.ok) {
  // Success - access result.data
  const document = result.data;
  console.log('Document class:', document.class);
  console.log('Header attributes:', document.header);
  console.log('Body elements:', document.body);
} else {
  // Failure - access result.error
  console.error('Error:', result.error);
}

For the complete ChalkDocument structure, see Type Reference - ChalkDocument.

Constants

Both compile and compileFile support injecting constants at compile time via the inputConstants parameter.

How Constants Work

  1. Definition: Constants can be defined in source using @const(key: value) or injected via inputConstants
  2. Reference: Use {{key}} syntax to reference constants in your source
  3. Scope: Input constants are document-scoped and available throughout the entire document
  4. Conversion: All input constant values are converted to strings

Multi-word Constant Keys

Constant identifiers can contain spaces:

const result = chalk.compile(source, library, {
  'app version': '1.0.0',
  'build date': '2025-12-19',
  'is production': true
});

In source:

*(title: My App)

Version: {{app version}}
Built: {{build date}}
Production: {{is production}}

Combining Source and Input Constants

// Input constants
const result = chalk.compile(`
@const(author: John Doe)
@const(title: {{app name}} Documentation)

*(title: {{title}}; author: {{author}})

Welcome to {{app name}} version {{version}}.
`, library, {
  'app name': 'MyApp',
  'version': '2.0.0'
});

Error Handling

Undefined Constants:

const result = chalk.compile(`
{{undefined constant}}
`, library);

// result.ok === false
// result.error === "Undefined constants: undefined constant. Constants must be declared..."

Invalid Constant Keys:

const result = chalk.compile(`
@const(invalid!key: value)
`, library);

// result.ok === false
// result.error === "Invalid constant key format..."

Complete Examples

Basic Compilation

import chalk from '@jackhgns/dotchalk';

// Create a library
const library = chalk.library({
  document: {
    class: 'article',
    body: 'all',
    attributes: {
      title: { type: 'string', required: true },
      author: { type: 'string', required: true }
    }
  }
});

// Compile source
const source = `
*(title: Getting Started; author: Jane Doe)

# Introduction

This is a **simple** article with *formatting*.

# Conclusion

That's all!
`;

const result = chalk.compile(source, library);

if (result.ok) {
  console.log(JSON.stringify(result.data, null, 2));
}

File Compilation with Includes

compile.js:

import chalk from '@jackhgns/dotchalk';
import path from 'path';

const library = chalk.library({
  document: {
    class: 'documentation',
    body: 'all',
    attributes: {
      title: { type: 'string', required: true },
      version: { type: 'string', required: true }
    }
  }
});

const result = chalk.compileFile(
  'docs/main.chalk',
  __dirname,
  library,
  { version: '1.0.0' }
);

if (result.ok) {
  console.log('Compiled:', result.data.class);
} else {
  console.error('Error:', result.error);
}

docs/main.chalk:

*(title: API Documentation; version: {{version}})

@include(intro.part.chalk)

# API Reference

Content here...

@include(footer.part.chalk)

Error Handling Pattern

function compileAndHandle(source, library) {
  const result = chalk.compile(source, library);
  
  if (!result.ok) {
    // Log error
    console.error('Compilation Error:', result.error);
    
    // Return default or throw
    throw new Error(`Failed to compile: ${result.error}`);
  }
  
  // Process successful result
  return processDocument(result.data);
}

Validation Pattern

function validateAndCompile(source, library) {
  const result = chalk.compile(source, library);
  
  if (!result.ok) {
    return {
      valid: false,
      errors: [result.error]
    };
  }
  
  // Additional validation
  const doc = result.data;
  const errors = [];
  
  if (!doc.header.title) {
    errors.push('Document missing title');
  }
  
  if (doc.body.length === 0) {
    errors.push('Document has no content');
  }
  
  return {
    valid: errors.length === 0,
    errors,
    document: doc
  };
}

Best Practices

1. Check Results

Always check the ok property before accessing data:

// Good
const result = chalk.compile(source, library);
if (result.ok) {
  process(result.data);
}

// Avoid
const result = chalk.compile(source, library);
process(result.data); // May be undefined if compilation failed

2. Use Absolute Paths for compileFile

// Good
const result = chalk.compileFile(
  'article.chalk',
  path.join(__dirname, 'content'),
  library
);

// Avoid
const result = chalk.compileFile(
  'article.chalk',
  './content',  // Relative to cwd, not script location
  library
);

3. Provide Meaningful Input Constants

// Good - descriptive keys
const constants = {
  'app version': packageJson.version,
  'build timestamp': new Date().toISOString(),
  'environment': process.env.NODE_ENV
};

// Avoid - cryptic keys
const constants = {
  v: '1.0',
  t: Date.now(),
  e: 'prod'
};

4. Handle Errors Gracefully

function safeCompile(source, library) {
  try {
    const result = chalk.compile(source, library);
    
    if (!result.ok) {
      logger.error('Compilation failed:', result.error);
      return null;
    }
    
    return result.data;
  } catch (err) {
    logger.error('Unexpected error:', err);
    return null;
  }
}