0.8.0 • Published 9 months ago

@petalo/contracts-wizard v0.8.0

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

Contracts Wizard

A powerful document generation system that transforms Markdown templates and CSV data into professionally formatted contracts. Perfect for legal teams, freelancers, and businesses looking to streamline their document generation workflow.

License: MIT Node.js Version ESLint PRs Welcome Contributions Welcome

Table of Contents

✨ Features

Core Features

  • Template Processing: Support for Markdown templates with Handlebars syntax
  • Multiple Output Formats: Generate HTML and PDF documents with customizable styling
  • Interactive CLI: User-friendly command-line interface with guided prompts
  • Data Management: CSV-based data storage with validation and manual input options
  • Custom Styling: Apply CSS styling to your documents with built-in responsive design
  • Date Handling: Comprehensive date formatting and manipulation with full Spanish locale support and timezone configuration
  • Robust Logging: Comprehensive logging system with rotation and debug support
  • Internal Links: Automatic generation of clickable links in PDF table of contents that navigate to corresponding sections

Advanced Features

  • Nested Fields: Support for complex data structures using dot notation
  • Custom Helpers: Built-in Handlebars helpers for common operations
  • Responsive Tables: Automatic table wrapping for better mobile display
  • Accessibility: Built-in image accessibility improvements
  • Missing Data Highlighting: Visual indicators for missing or empty values
  • Error Recovery: Graceful handling of missing files and invalid data
  • Extensible Design: Easy to add new template helpers and output formats

šŸš€ Quick Start

  1. Install globally:

    npm install -g @petalo/contracts-wizard
  2. Create a new project:

    contracts-wizard init my-contracts
    cd my-contracts
  3. Create and edit the .env file with your desired settings:

    cp .env.example .env
  4. Run the setup script:

    npm run setup
  5. Start using the wizard:

    contracts-wizard

šŸ“ Example Files

The package includes example files in the examples/ directory to help you get started:

  • office_lease_EN.example.md - Example lease contract template
  • office_lease_EN.example.csv - Example data for the lease contract (some values have been deleted or left empty to show the missing data highlighting)
  • contract.example.css - Example CSS styling

These files are for reference only. To use them in your project, either:

  • Run npm run setup to copy them to your working directories
  • Create a new project with contracts-wizard init which will copy them automatically

The working directories for your files (by default) are:

  • Templates → templates/markdown/
  • CSS files → templates/css/
  • CSV files → data-csv/

šŸ“– Installation

There are two ways to install Contracts Wizard:

1. Global Installation (Recommended for users)

If you just want to use the tool to generate contracts:

# Install globally
npm install -g contracts-wizard

# Create a new project
contracts-wizard init my-contracts
cd my-contracts

# Copy the .env.example file and edit it with your desired settings
cp .env.example .env

# Start using
contracts-wizard

This installation:

  • Provides the contracts-wizard command globally
  • Creates a clean project structure
  • Includes basic templates and examples

2. Local Installation (For development)

If you want to contribute to the project or customize it:

# Clone the repository
git clone https://github.com/petalo/contracts-wizard.git
cd contracts-wizard

# Install dependencies
npm install

# Configure the project
npm run setup

# Start in development mode
npm run dev

This installation:

  • Provides full access to the source code
  • Includes development tools
  • Allows contributing to the project

Prerequisites

Before installing Contracts Wizard, ensure you have:

  • Node.js: >= 14.0.0

    node --version
  • npm: >= 6.0.0

    npm --version
  • Git: Latest version (for development)

    git --version
  • Memory: Minimum 1GB RAM available

  • Disk Space: At least 100MB free space
  • Operating System: Windows 10+, macOS 10.15+, or Linux (Ubuntu 18.04+)

System Requirements

  • CPU: 1GHz or faster
  • Network: Internet connection for initial setup
  • Browser: For PDF preview (if needed)
    • Chrome/Chromium >= 85
    • Firefox >= 80

šŸ“– Usage

CLI Mode

Basic usage with examples:

# Generate contract from template and CSV
contracts-wizard generate -t contract.md -d input.csv

# Use custom styling
contracts-wizard generate -t contract.md -d input.csv -c style.css

# List available resources
contracts-wizard list templates
contracts-wizard list data
contracts-wizard list styles

# Get help
contracts-wizard --help

Interactive Mode

The interactive mode guides you through the process:

# Start the wizard with no arguments
contracts-wizard

Command Line Options

Options for the generate command:

OptionShortDescriptionExample
--template-tTemplate file path-t contract.md
--data-dCSV data file path-d input.csv
--css-cCSS style file path-c style.css

Global options:

OptionDescriptionExample
--helpShow help--help
--versionShow version--version

Available Commands

# Interactive mode (default)
contracts-wizard

# Generate contract (with options)
contracts-wizard generate -t template.md [-d data.csv] [-c style.css]

# List available resources
contracts-wizard list templates  # List markdown templates
contracts-wizard list data      # List CSV data files
contracts-wizard list styles    # List CSS style files

# Initialize new project
contracts-wizard init my-project

# Show help for specific commands
contracts-wizard --help
contracts-wizard generate --help
contracts-wizard list --help
contracts-wizard init --help

Creating Templates

Templates use Handlebars syntax with built-in helpers:

# {{title}}

This agreement is made on {{formatDate now "DD/MM/YYYY"}}
between {{client.name}} ("Client") and {{consultant.name}} ("Consultant").

## 1. Services

{{services}}

## 2. Term

From {{formatDate startDate "DD/MM/YYYY"}} to {{formatDate endDate "DD/MM/YYYY"}}

## 3. Compensation

{{currency compensation "EUR"}}

## 4. Signatures

{{#each signatures}}
- {{name}}: _________________
{{/each}}

Data Input

CSV structure with examples:

key,value,comment
title,Consulting Agreement,Contract title
client.name,Acme Corp,Client company name
consultant.name,Jane Doe,Consultant full name
services,"Web development services",Description of services
startDate,2024-01-01,Contract start date
endDate,2024-12-31,Contract end date
compensation,10000,Monthly compensation
signatures[0].name,Client Representative,
signatures[1].name,Consultant,

Handling Missing Data

The wizard handles missing data with:

  1. Visual indicators in red: [[missing.field]]
  2. CSS styling for missing values (see examples/css/missing-data.css)
  3. Validation warnings
  4. Detailed logging

Available Helpers

Built-in Handlebars helpers:

Value Comparison

{{eq value1 value2}}

Compares two values for equality with type coercion:

  • Case-insensitive string comparison
  • HTML-wrapped content extraction
  • Numeric values with type coercion
  • Boolean values and their string representations
  • Proper handling of null/undefined values with configurable error messages

Object Lookup

{{lookup object "property"}}

Extracts values from:

  • Nested objects
  • HTML-wrapped content
  • SafeString instances
  • Objects with string properties
  • Handles missing or invalid values with configurable error messages

Date Formatting

{{formatDate date "DD/MM/YYYY"}}
{{addYears date 1}}
{{now "YYYY-MM-DD"}}

Date manipulation and formatting with:

  • Full Spanish locale support
  • Configurable timezone handling
  • Predefined date formats from configuration
  • Consistent error handling for invalid dates
  • HTML wrapping with configurable classes
  • Support for chained operations

Example with predefined formats:

{{! Using predefined formats from configuration }}
{{formatDate date "DEFAULT"}}  {{! D [de] MMMM [de] YYYY }}
{{formatDate date "ISO"}}      {{! YYYY-MM-DD }}
{{formatDate date "FULL"}}     {{! D [de] MMMM [de] YYYY }}
{{formatDate date "SHORT"}}    {{! DD/MM/YYYY }}
{{formatDate date "TIME"}}     {{! HH:mm:ss }}

{{! Chaining operations }}
{{formatDate (addYears now 1) "FULL"}}

Empty Value Handling

All helpers now use consistent empty value handling from configuration:

{{! Missing or invalid values }}
<span class="missing-value" data-field="fieldName">[[fieldName]]</span>

{{! Successfully imported values }}
<span class="imported-value" data-field="fieldName">value</span>

The styling and messages are configurable through HANDLEBARS_CONFIG:

const HANDLEBARS_CONFIG = {
  emptyValue: {
    class: 'missing-value',
    importedClass: 'imported-value',
    template: '<span class="{class}" data-field="{key}">{value}</span>'
  },
  errorMessages: {
    invalidDate: '[[Invalid date]]',
    missingValue: '(Empty value)',
    processingError: '[Error processing {type}]'
  },
  dateFormats: {
    DEFAULT: 'D [de] MMMM [de] YYYY',
    ISO: 'YYYY-MM-DD',
    FULL: 'D [de] MMMM [de] YYYY',
    SHORT: 'DD/MM/YYYY',
    TIME: 'HH:mm:ss'
  }
};

Examples

{{! Value comparison with error handling }}
{{#if (eq user.age 18)}}
  User is 18 years old
{{else}}
  {{! Will show configured error message if age is missing }}
{{/if}}

{{! Date formatting with predefined formats }}
Created on: {{now "SHORT"}}
Expires on: {{formatDate (addYears startDate 1) "FULL"}}
Today is: {{now "DEFAULT"}}

{{! Error handling }}
{{#if (eq undefined_value "test")}}
  {{! Will show: <span class="missing-value" data-field="undefined_value">(Empty value)</span> }}
{{/if}}

{{formatDate invalid_date "SHORT"}}
{{! Will show: <span class="missing-value" data-field="date">[[Invalid date]]</span> }}

All helpers include:

  • Consistent error handling through configuration
  • Detailed debug logging
  • HTML safety with proper escaping
  • Type coercion where appropriate
  • Locale support for dates and numbers
  • Configurable styling and messages

Built-in Helpers

The system includes several built-in Handlebars helpers to format and manipulate data:

Date Helpers

{{! Current date with Spanish locale }}
{{now "D [de] MMMM [de] YYYY"}}  {{! Returns: "31 de enero de 2024" }}

{{! Format specific dates with locale support }}
{{formatDate someDate "D [de] MMMM [de] YYYY"}}

{{! Add years to a date }}
{{addYears someDate 5}}

{{! Chain operations }}
{{formatDate (addYears now 1) "D [de] MMMM [de] YYYY"}}

The date helpers include:

  • Full Spanish locale support (months, days, etc.)
  • Timezone configuration (default: Europe/Madrid)
  • Consistent formatting across all date operations
  • Proper handling of undefined values and edge cases
  • Debug logging for troubleshooting

Number Formatting

The system automatically formats numbers according to the Spanish locale (configurable in LOCALE_CONFIG). You can use the formatNumber helper explicitly for more control:

{{! Basic number formatting - adds thousands separator and decimal comma }}
{{formatNumber 1234.56}}  -> "1.234,56"

{{! Currency formatting }}
{{formatNumber value style="currency" currency="EUR"}}  -> "1.234,56 €"

{{! Percentage formatting }}
{{formatNumber 0.1234 style="percent"}}  -> "12,34 %"

{{! Custom decimal places }}
{{formatNumber value minimumFractionDigits=2 maximumFractionDigits=4}}

The helper handles:

  • Thousands separator (punto)
  • Decimal separator (coma)
  • Currency symbols with proper spacing
  • Percentage formatting
  • Custom decimal places
  • Invalid or empty values

Note: Numbers in the template are automatically formatted - you don't need to use formatNumber unless you want specific formatting options.

Other Helpers

  • eq: Compare values with type coercion

    {{#if (eq value 0)}}
  • lookup: Access nested object properties

    {{lookup object "property"}}

Using the with Helper

The with helper is used to change the context within a block, making it easier to access nested properties without repeating the parent object name. It's particularly useful when working with deeply nested objects.

Basic Usage

{{#with user}}
  Name: {{name}}
  Email: {{email}}
  Address: {{address.street}}, {{address.city}}
{{/with}}

Instead of writing:

Name: {{user.name}}
Email: {{user.email}}
Address: {{user.address.street}}, {{user.address.city}}

Key Features

  1. Context Change: Inside the with block, this refers to the specified object
  2. Nested Properties: Access child properties directly without parent reference
  3. Fallback Handling: If the object is undefined, the block is skipped
  4. Combining with Other Helpers: Can be used with if, each, etc.

Advanced Examples

{{! Nested with blocks }}
{{#with user}}
  {{#with address}}
    Street: {{street}}
    City: {{city}}
    Country: {{country}}
  {{/with}}
{{/with}}

{{! With + if combination }}
{{#with user}}
  {{#if address}}
    {{#with address}}
      Full Address: {{street}}, {{city}}
    {{/with}}
  {{else}}
    No address provided
  {{/if}}
{{/with}}

{{! With + each combination }}
{{#with company}}
  Company: {{name}}
  {{#each employees}}
    - {{name}} ({{position}})
  {{/each}}
{{/with}}

Best Practices

  1. Depth Control: Avoid nesting more than 2-3 levels deep for readability
  2. Fallback Content: Use else to handle undefined cases:

    {{#with user}}
      {{name}}
    {{else}}
      User not found
    {{/with}}
  3. Context Clarity: Comment blocks when using multiple nested with statements

  4. Performance: Use with when accessing multiple properties of the same object

Common Pitfalls

  1. Accessing Parent Context: Use ../ to access parent context:

    {{#with user}}
      {{name}} works at {{../company.name}}
    {{/with}}
  2. Undefined Objects: The block is skipped if the object is undefined:

    {{#with undefinedObject}}
      This won't be rendered
    {{else}}
      Fallback content
    {{/with}}
  3. This Reference: Inside with, this refers to the new context:

    {{#with user}}
      {{this.name}} {{! same as just {{name}} }}
    {{/with}}

�� Configuration

Project Structure

contracts-wizard/
ā”œā”€ā”€ bin/              # CLI executable
ā”œā”€ā”€ src/              # Source code
│   ā”œā”€ā”€ cli/          # CLI implementation
│   ā”œā”€ā”€ config/       # Configuration files
│   ā”œā”€ā”€ core/         # Core processing logic
│   └── utils/        # Utility functions
ā”œā”€ā”€ templates/        # Working template files
│   ā”œā”€ā”€ markdown/     # Markdown templates
│   └── css/          # CSS styles
ā”œā”€ā”€ examples/         # Example files (reference only)
│   ā”œā”€ā”€ markdown/     # Example templates
│   ā”œā”€ā”€ css/          # Example styles
│   └── csv/          # Example data files
ā”œā”€ā”€ data-csv/         # Working CSV files
ā”œā”€ā”€ output_files/     # Generated contracts
ā”œā”€ā”€ logs/             # Application logs
ā”œā”€ā”€ scripts/          # Helper scripts
ā”œā”€ā”€ tests/            # Test files
ā”œā”€ā”€ docs/             # Documentation
└── package.json

Environment Variables

The application uses environment variables for configuration. Create a .env file based on .env.example.

VariableDescriptionDefault ValueOptions
NODE_ENVApplication environmentdevelopmentdevelopment/production/test
DEBUGEnable console outputfalsetrue/false
LOG_LEVELFile logging verbosity levelinfoerror/warn/info/debug
LOG_DIRDirectory for log fileslogs
LOG_MAX_SIZEMaximum size before log rotation10MB
LOG_MAX_FILESNumber of log files to keep7
TIMEZONEDefault timezoneUTC
LANGUAGEDefault languageen-US
DIR_OUTPUTOutput directory for filesoutput_files
DIR_TEMPLATESTemplates directorytemplates/markdown
DIR_CSSCSS styles directorytemplates/css
DIR_IMAGESImages directorytemplates/images
DIR_CSVCSV data directorydata-csv
DIR_REPORTSReports directoryreports
DIR_COVERAGETest coverage directorycoverage
DIR_TEST_LOGSTest logs directorytests-logs
DIR_TEST_OUTPUTTest output directorytests-output
CACHE_ENABLEDEnable/disable cachingtrue
CACHE_TTLCache time-to-live (seconds)1800
MAX_CONCURRENT_PROCESSESMax concurrent processes2
RATE_LIMIT_WINDOWRate limiting window (minutes)15
RATE_LIMIT_MAX_REQUESTSMax requests per window50
SESSION_TIMEOUTSession timeout (minutes)15

Configuration Files

All configuration files are located in src/config/. Here are the key files you can edit to customize the behavior:

FileDescriptionKey Settings
aliases.jsModule path aliasesImport path shortcuts
appMetadata.jsApplication informationVersion, author, repository
assets.jsStatic assets configurationImages, fonts, resource paths
cheerioRules.jsHTML transformation rulesList formatting, table responsiveness
encoding.jsCharacter encoding settingsInput/output file encodings
fileExtensions.jsAllowed file extensionsTemplate, data, and style extensions
htmlOptions.jsHTML output configurationDocument structure, meta tags
locale.jsLocalization settingsDate formats, timezone, language
paths.jsDirectory structure and file pathsOutput, templates, and data paths
pdfOptions.jsPDF generation settingsPage format, margins, headers
version.jsVersion informationApplication version number

Example configurations:

Locale Settings (locale.js)

module.exports = {
  defaultLocale: 'es-ES',
  defaultTimezone: 'Europe/Madrid',
  dateFormat: 'DD/MM/YYYY',
  currencyFormat: '0,0.00'
};

PDF Options (pdfOptions.js)

module.exports = {
  format: 'A4',
  margin: { 
    top: '1cm', 
    right: '1cm', 
    bottom: '1cm', 
    left: '1cm' 
  },
  displayHeaderFooter: true,
  headerTemplate: customHeader,
  footerTemplate: customFooter,
  printBackground: true,
  preferCSSPageSize: true, // Respect CSS page size and margins
  tagged: true,            // Enable PDF tagging for better accessibility
  outline: true           // Generate document outline with internal links
};

The PDF generation includes several features for internal navigation:

  • Table of contents entries are automatically converted to clickable links
  • Links navigate directly to their corresponding sections in the PDF
  • Document outline is generated for easy navigation
  • PDF tagging improves accessibility and document structure

HTML Options (htmlOptions.js)

module.exports = {
  doctype: 'html',
  language: 'en',
  meta: {
    charset: 'UTF-8',
    viewport: 'width=device-width, initial-scale=1.0'
  },
  minify: process.env.NODE_ENV === 'production'
};

File Extensions (fileExtensions.js)

module.exports = {
  types: {
    markdown: 'markdown',
    csv: 'csv',
    css: 'css'
  },
  markdown: ['.md', '.markdown'],
  csv: ['.csv'],
  css: ['.css']
};

For more detailed configuration options, check the corresponding files in src/config/.

šŸ¤ Contributing

We love your input! We want to make contributing to Contracts Wizard as easy and transparent as possible. Please see our Development and Contributing Guide for details on:

  • Development setup
  • Coding standards
  • Testing guidelines
  • Pull request process
  • Release process

šŸ“œ License

This project is licensed under the MIT License - see the LICENSE file for details.

šŸ™ Acknowledgments


Made with ā¤ļø by the Contracts Wizard team

šŸ” Troubleshooting

Common Issues

  1. Installation Fails

    # Clear npm cache
    npm cache clean --force
    # Retry installation
    npm install -g @petalo/contracts-wizard
  2. PDF Generation Fails

    • Check Chrome/Chromium installation
    • Verify sufficient memory available
    • Check file permissions in output directory
  3. Missing Data Handling

    • Verify CSV format matches template fields
    • Check for proper UTF-8 encoding
    • Validate date formats match locale settings
  4. Template Processing Issues

    • Validate Handlebars syntax
    • Check for proper closing tags
    • Verify helper function usage

Debug Mode

Enable debug mode for detailed logging:

DEBUG=true contracts-wizard generate -t template.md

Check logs at logs/logging-latest.log for detailed error information.