Helper functions and utilities used throughout the CoffeeScript compiler and available for external use, including debugging support, file operations, and language utilities.
Access to CoffeeScript version and metadata.
/**
* CoffeeScript package version string
*/
const VERSION: string; // e.g., "2.7.0"Usage Examples:
const CoffeeScript = require('coffeescript');
console.log('CoffeeScript version:', CoffeeScript.VERSION);
// Output: CoffeeScript version: 2.7.0
// Version checking
function requiresCoffeeScriptVersion(minVersion) {
const current = CoffeeScript.VERSION.split('.').map(Number);
const required = minVersion.split('.').map(Number);
for (let i = 0; i < 3; i++) {
if (current[i] > required[i]) return true;
if (current[i] < required[i]) return false;
}
return true;
}
if (requiresCoffeeScriptVersion('2.5.0')) {
console.log('CoffeeScript version is compatible');
}Enable enhanced stack traces that show CoffeeScript source locations instead of compiled JavaScript.
/**
* Enable stack trace patching for CoffeeScript files
* Modifies Error.prepareStackTrace to show CoffeeScript locations
*/
function patchStackTrace(): void;
/**
* Register compiled source map for stack trace patching
* @param filename - Source filename
* @param source - Original CoffeeScript source
* @param sourcemap - Generated source map
*/
function registerCompiled(filename: string, source: string, sourcemap: SourceMap): void;Usage Examples:
const CoffeeScript = require('coffeescript');
// Enable stack trace patching
CoffeeScript.patchStackTrace();
// Now errors in CoffeeScript files show original locations
try {
CoffeeScript.run(`
divide = (a, b) ->
throw new Error "Division by zero" if b is 0
a / b
result = divide 10, 0
`);
} catch (error) {
console.log(error.stack);
// Stack trace shows CoffeeScript line numbers, not JavaScript
}
// Manual source map registration
const source = 'square = (x) -> x * x';
const compiled = CoffeeScript.compile(source, {
sourceMap: true,
filename: 'math.coffee'
});
CoffeeScript.registerCompiled('math.coffee', source, compiled.sourceMap);Babel integration for transpiling compiled JavaScript to target specific environments.
/**
* Transpile JavaScript using Babel (requires @babel/core)
* @param js - JavaScript code to transpile
* @param options - Babel configuration options
* @returns Transpilation result with code and optional source map
*/
function transpile(js: string, options?: BabelOptions): BabelResult;
interface BabelOptions {
/** Babel presets to apply */
presets?: any[];
/** Babel plugins to apply */
plugins?: any[];
/** Source map options */
sourceMaps?: boolean | 'inline' | 'both';
/** Input filename for source maps */
filename?: string;
}
interface BabelResult {
/** Transpiled JavaScript code */
code: string;
/** Source map object (if enabled) */
map?: any;
/** Abstract Syntax Tree (if requested) */
ast?: any;
}Usage Examples:
const CoffeeScript = require('coffeescript');
// Compile CoffeeScript with transpilation
const coffeeCode = `
class Calculator
add: (a, b) => a + b
multiply: (a, b) => a * b
`;
const jsCode = CoffeeScript.compile(coffeeCode);
// Transpile for older browsers
try {
const transpiled = CoffeeScript.transpile(jsCode, {
presets: [
['@babel/preset-env', {
targets: 'ie 11'
}]
]
});
console.log('Transpiled code:', transpiled.code);
} catch (error) {
if (error.message.includes('@babel/core')) {
console.error('Babel is required for transpilation. Install with: npm install @babel/core');
}
}
// Transpile with source maps
const transpiled = CoffeeScript.transpile(jsCode, {
presets: ['@babel/preset-env'],
sourceMaps: true,
filename: 'calculator.js'
});
console.log('Code:', transpiled.code);
console.log('Source map:', transpiled.map);The helpers object contains utility functions used throughout the CoffeeScript compiler.
/**
* Collection of utility helper functions
*/
const helpers: HelperFunctions;
interface HelperFunctions {
// String utilities
starts(string: string, literal: string, start?: number): boolean;
ends(string: string, literal: string, back?: number): boolean;
repeat(str: string, n: number): string;
count(string: string, substr: string): number;
// Array utilities
compact(array: any[]): any[];
flatten(array: any[]): any[];
// Object utilities
merge(options: any, overrides: any): any;
extend(object: any, properties: any): any;
del(obj: any, key: string): any;
// File utilities
isCoffee(file: string): boolean;
isLiterate(file: string): boolean;
baseFileName(file: string, stripExt?: boolean, useWinPathSep?: boolean): string;
anonymousFileName(): string;
// Type checking
isFunction(obj: any): boolean;
isNumber(obj: any): boolean;
isString(obj: any): boolean;
isBoolean(obj: any): boolean;
isPlainObject(obj: any): boolean;
// Error handling
throwSyntaxError(message: string, location: LocationData): void;
updateSyntaxError(error: Error, code: string, filename?: string): Error;
// Other utilities
parseNumber(string: string): number;
locationDataToString(obj: LocationData): string;
nameWhitespaceCharacter(string: string): string;
}const { helpers } = require('coffeescript');
// String testing
console.log(helpers.starts('hello world', 'hello')); // true
console.log(helpers.ends('hello world', 'world')); // true
console.log(helpers.starts('hello world', 'world', 6)); // true (start at index 6)
// String repetition
console.log(helpers.repeat('*', 5)); // '*****'
console.log(helpers.repeat('abc', 3)); // 'abcabcabc'
// Substring counting
console.log(helpers.count('hello world', 'l')); // 3
console.log(helpers.count('aaaaaa', 'aa')); // 5 (overlapping matches)const { helpers } = require('coffeescript');
// Remove falsy values
const messy = [1, null, 2, undefined, 3, false, 4, '', 5];
console.log(helpers.compact(messy)); // [1, 2, 3, 4, 5]
// Flatten nested arrays
const nested = [1, [2, 3], [4, [5, 6]], 7];
console.log(helpers.flatten(nested)); // [1, 2, 3, 4, 5, 6, 7]const { helpers } = require('coffeescript');
// Merge objects (creates new object)
const options = { a: 1, b: 2 };
const overrides = { b: 3, c: 4 };
const merged = helpers.merge(options, overrides);
console.log(merged); // { a: 1, b: 3, c: 4 }
console.log(options); // { a: 1, b: 2 } (unchanged)
// Extend object (modifies original)
const obj = { x: 1 };
helpers.extend(obj, { y: 2, z: 3 });
console.log(obj); // { x: 1, y: 2, z: 3 }
// Delete and return value
const data = { name: 'Alice', age: 30, city: 'NYC' };
const age = helpers.del(data, 'age');
console.log(age); // 30
console.log(data); // { name: 'Alice', city: 'NYC' }const { helpers } = require('coffeescript');
// File type detection
console.log(helpers.isCoffee('script.coffee')); // true
console.log(helpers.isCoffee('script.js')); // false
console.log(helpers.isLiterate('readme.litcoffee')); // true
console.log(helpers.isLiterate('docs.coffee.md')); // true
// Filename manipulation
console.log(helpers.baseFileName('/path/to/script.coffee')); // 'script.coffee'
console.log(helpers.baseFileName('/path/to/script.coffee', true)); // 'script'
console.log(helpers.baseFileName('C:\\path\\to\\script.coffee', false, true)); // 'script.coffee'
// Anonymous filename generation
console.log(helpers.anonymousFileName()); // '<anonymous>'const { helpers } = require('coffeescript');
// Type checking utilities
console.log(helpers.isFunction(() => {})); // true
console.log(helpers.isNumber(42)); // true
console.log(helpers.isString('hello')); // true
console.log(helpers.isBoolean(true)); // true
console.log(helpers.isPlainObject({})); // true
console.log(helpers.isPlainObject(new Date())); // false
// Number parsing with validation
console.log(helpers.parseNumber('42')); // 42
console.log(helpers.parseNumber('3.14')); // 3.14
console.log(helpers.parseNumber('0x10')); // 16
console.log(helpers.parseNumber('0b1010')); // 10
try {
helpers.parseNumber('invalid');
} catch (error) {
console.log('Invalid number format');
}const { helpers } = require('coffeescript');
// Create syntax errors with location
try {
helpers.throwSyntaxError('Unexpected token', {
first_line: 1,
last_line: 1,
first_column: 10,
last_column: 15
});
} catch (error) {
console.log(error.name); // 'SyntaxError'
console.log(error.message); // 'Unexpected token'
console.log(error.location); // Location data
}
// Update existing errors with context
const originalError = new Error('Something went wrong');
const enhanced = helpers.updateSyntaxError(
originalError,
'square = (x) -> x *', // Source code
'math.coffee' // Filename
);
console.log(enhanced.filename); // 'math.coffee'
console.log(enhanced.location); // Calculated locationconst { helpers } = require('coffeescript');
// Format location data for display
const location = {
first_line: 3,
last_line: 3,
first_column: 8,
last_column: 15
};
console.log(helpers.locationDataToString(location));
// Output: "3:8-15" or similar format
// Describe whitespace characters
console.log(helpers.nameWhitespaceCharacter(' ')); // 'space'
console.log(helpers.nameWhitespaceCharacter('\t')); // 'tab'
console.log(helpers.nameWhitespaceCharacter('\n')); // 'newline'
console.log(helpers.nameWhitespaceCharacter('\r')); // 'carriage return'const CoffeeScript = require('coffeescript');
// Get cached source map for a file
const sourceMap = CoffeeScript.getSourceMap?.('math.coffee');
if (sourceMap) {
console.log('Source map found for math.coffee');
// Use source map for debugging
const mappedLocation = sourceMap.originalPositionFor({
line: 5,
column: 10
});
console.log('Original location:', mappedLocation);
}You can extend the helper functionality for your specific needs:
const { helpers } = require('coffeescript');
// Custom string utilities
function customHelpers(helpers) {
return Object.assign({}, helpers, {
// Title case conversion
titleCase: (str) => str.replace(/\w\S*/g, (txt) =>
txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
),
// Camel case conversion
camelCase: (str) => str.replace(/[-_\s]+(.)?/g, (_, c) =>
c ? c.toUpperCase() : ''
),
// Deep object merging
deepMerge: (target, source) => {
const result = helpers.extend({}, target);
for (const key in source) {
if (helpers.isPlainObject(source[key]) && helpers.isPlainObject(result[key])) {
result[key] = customHelpers(helpers).deepMerge(result[key], source[key]);
} else {
result[key] = source[key];
}
}
return result;
}
});
}
// Usage
const enhanced = customHelpers(helpers);
console.log(enhanced.titleCase('hello world')); // 'Hello World'
console.log(enhanced.camelCase('my-var-name')); // 'myVarName'
const deep1 = { a: { b: 1, c: 2 }, d: 3 };
const deep2 = { a: { c: 4, e: 5 }, f: 6 };
console.log(enhanced.deepMerge(deep1, deep2));
// { a: { b: 1, c: 4, e: 5 }, d: 3, f: 6 }Helpful utilities for development and debugging:
const CoffeeScript = require('coffeescript');
// Debug compilation pipeline
function debugCompile(source, options = {}) {
console.log('=== CoffeeScript Debug Compilation ===');
console.log('Source:', source);
try {
// Tokenize
const tokens = CoffeeScript.tokens(source, options);
console.log('Tokens:', tokens.length);
// Parse
const ast = CoffeeScript.nodes(source, options);
console.log('AST nodes:', ast.expressions.length);
// Compile
const result = CoffeeScript.compile(source, {
...options,
sourceMap: true
});
console.log('Compiled successfully');
console.log('JavaScript length:', result.js.length);
console.log('Has source map:', !!result.sourceMap);
return result;
} catch (error) {
console.error('Compilation failed:', error.message);
if (error.location) {
console.error('Location:', error.location);
}
throw error;
}
}
// Usage
debugCompile(`
class MathUtils
@square: (x) -> x * x
@cube: (x) -> x * x * x
`);