Skip to the content.

Complete guide to creating custom Chalk libraries with elements, attributes, and types.

Document Definitions

Documents are defined using the DocumentDefinition interface:

interface DocumentDefinition {
  class: string;
  bodyPolicy: string[] | ContentPolicy;
  headerAttributes?: AttributeDefinition[];
}

Example:

const blogDoc = {
  class: 'blog-post',
  bodyPolicy: ['paragraph', 'image', 'code-block'],
  headerAttributes: [
    { identifier: 'title', type: 'string', required: true },
    { identifier: 'author', type: 'string', required: true },
    { identifier: 'published', type: 'date', required: false }
  ]
};

Element Definitions

Elements are defined using the ElementDefinition interface:

interface ElementDefinition {
  identifier: string;
  aliases?: string[];
  bodyPolicy: string[] | ContentPolicy | 'literal';
  detailPolicy?: string[] | ContentPolicy | null;
  attributes?: AttributeDefinition[];
  parser?: (input: string) => Result<ChalkElement[], string>;
}

Example:

const imageElement = {
  identifier: 'image',
  bodyPolicy: [],  // No content allowed in body
  attributes: [
    { identifier: 'src', type: 'string', required: true },
    { identifier: 'alt', type: 'string', required: false },
    { identifier: 'caption', type: 'formatted-string', required: false }
  ]
};

Attribute Definitions

Attributes are defined using the AttributeDefinition interface:

interface AttributeDefinition {
  identifier: string;
  aliases?: string[];
  type: string;
  required?: boolean;
  default?: any;
}

Default Values

Attributes can have default values that are used when the attribute is not specified in the Chalk source:

const articleElement = {
  identifier: "article",
  attributes: [
    {
      identifier: "published",
      type: "boolean",
      required: false,
      default: false  // Defaults to false if not specified
    },
    {
      identifier: "priority",
      type: "string",
      required: false,
      default: "medium"  // Defaults to "medium" if not specified
    }
  ]
};

Default values are applied during compilation when an attribute is missing from the element definition.

Custom Types

You can define custom attribute types and enums:

Custom Type with Validation

const dateType = {
  identifier: 'date',
  validate: (value) => /^\d{4}-\d{2}-\d{2}$/.test(value)
};

Enum Type

const priorityEnum = {
  identifier: 'priority',
  values: ['low', 'medium', 'high', 'urgent']
};

Using Primitive Types

Chalk provides built-in primitive attribute types:

// Basic types
type: "string"      // Text values
type: "number"      // Numeric values
type: "boolean"     // True/false (accepts: true/false, yes/no, 1/0)

// List types
type: "string-list" // Comma-separated strings
type: "number-list" // Comma-separated numbers

// Formatted types
type: "formatted-string" // Text with markdown support

Complete Example

const articleElement = {
  identifier: "article",
  aliases: ["art"],
  bodyPolicy: ["paragraph", "heading"],
  attributes: [
    {
      identifier: "title",
      type: "string",
      required: true
    },
    {
      identifier: "tags",
      type: "string-list",
      required: false
    },
    {
      identifier: "published",
      type: "boolean",
      required: false,
      default: false
    }
  ]
};

// Create the library
const library = chalk.createLibrary(blogDoc)
  .add(articleElement, imageElement, dateType, priorityEnum);

Next Steps