diff --git a/.changeset/curvy-chicken-laugh.md b/.changeset/curvy-chicken-laugh.md deleted file mode 100644 index f6883a4..0000000 --- a/.changeset/curvy-chicken-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@fake-scope/fake-pkg": patch ---- - -fix: export issues in `3.0.0` diff --git a/.changeset/purple-zebras-kiss.md b/.changeset/purple-zebras-kiss.md new file mode 100644 index 0000000..44398ca --- /dev/null +++ b/.changeset/purple-zebras-kiss.md @@ -0,0 +1,5 @@ +--- +"esbuild-coffeescript": patch +--- + +docs: update README with enhanced installation instructions diff --git a/README.md b/README.md index e3ae210..1b47cce 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,419 @@ # esbuild-coffeescript [![esbuild-coffeescript](https://github.com/johnie/esbuild-coffeescript/actions/workflows/master.yml/badge.svg?branch=master)](https://github.com/johnie/esbuild-coffeescript/actions/workflows/master.yml) +[![npm version](https://badge.fury.io/js/esbuild-coffeescript.svg)](https://www.npmjs.com/package/esbuild-coffeescript) +[![Downloads](https://img.shields.io/npm/dm/esbuild-coffeescript.svg)](https://www.npmjs.com/package/esbuild-coffeescript) > This plugin lets you import [CoffeeScript](https://coffeescript.org/) files when bundling with [Esbuild](https://esbuild.github.io/) +Transform and bundle `.coffee` and `.litcoffee` files seamlessly with esbuild's lightning-fast build system. + +## Table of Contents + +- [Installation](#installation) +- [Quick Start](#quick-start) +- [Usage Examples](#usage-examples) +- [Configuration Options](#configuration-options) +- [Advanced Usage](#advanced-usage) +- [Error Handling](#error-handling) +- [Migration Guide](#migration-guide) +- [Troubleshooting](#troubleshooting) +- [Contributing](#contributing) +- [License](#license) + ## Installation -``` -$ npm install --save-dev esbuild-coffeescript +```bash +# npm +npm install --save-dev esbuild-coffeescript esbuild + +# pnpm +pnpm add --dev esbuild-coffeescript esbuild ``` ## Compatibility -This plugin is tested against Node.js versions 20.x, 22.x, and 24.x. +This plugin is tested against Node.js versions **20.x**, **22.x**, and **24.x**. + +## Quick Start -## Getting Started +### Basic CoffeeScript File -`main.coffee` +Create a CoffeeScript file: + +**main.coffee** ```coffee answer = 42 console.log("the answer is #{answer}") ``` -`build.js` +### Build Configuration + +**build.js** + +```js +import coffeeScriptPlugin from "esbuild-coffeescript"; +import esbuild from "esbuild"; + +esbuild + .build({ + entryPoints: ["main.coffee"], + bundle: true, + outfile: "out.js", + plugins: [coffeeScriptPlugin()], + }) + .catch(() => process.exit(1)); +``` + +### Generated Output + +The above CoffeeScript compiles to: ```js -import coffeeScriptPlugin from 'esbuild-coffeescript'; -import esbuild from 'esbuild'; +(function () { + var answer; + answer = 42; + return console.log("the answer is " + answer); +}).call(this); +``` + +## Usage Examples + +### Literate CoffeeScript + +The plugin automatically detects and processes `.litcoffee` files: + +**docs.litcoffee** + +```markdown +# My Application + +This is documentation written in Markdown with embedded CoffeeScript: + + class Calculator + add: (a, b) -> a + b + multiply: (a, b) -> a * b + calc = new Calculator() + console.log calc.add(5, 3) +``` + +**build.js** + +```js esbuild.build({ - entryPoints: ['main.coffee'], + entryPoints: ["docs.litcoffee"], bundle: true, - outfile: 'out.js', + plugins: [coffeeScriptPlugin({ literate: true })], + outfile: "calculator.js", +}); +``` + +### Multiple File Project + +**models/User.coffee** + +```coffee +class User + constructor: (@name, @email) -> + + greet: -> "Hello, I'm #{@name}" + +module.exports = { User } +``` + +**main.coffee** + +```coffee +{User} = require('./models/User.coffee') + +user = new User('John', 'john@example.com') +console.log user.greet() +``` + +**build.js** + +```js +esbuild.build({ + entryPoints: ["main.coffee"], + bundle: true, + plugins: [coffeeScriptPlugin({ bare: true })], + outfile: "app.js", + format: "esm", +}); +``` + +### Web Application Bundle + +```js +import coffeeScriptPlugin from "esbuild-coffeescript"; + +esbuild.build({ + entryPoints: ["src/app.coffee"], + bundle: true, + outdir: "dist", plugins: [coffeeScriptPlugin()], -}).catch(() => process.exit(1)); + format: "esm", + target: "es2020", + minify: true, + sourcemap: true, +}); +``` + +## Configuration Options + +Pass configuration options to the plugin constructor: + +```js +coffeeScriptPlugin({ + bare: true, + inlineMap: true, + // ... other options +}); +``` + +### Available Options + +| Option | Type | Default | Description | +| ----------- | --------- | ------------- | ---------------------------------------------------------------------------------------------- | +| `inlineMap` | `boolean` | `false` | Output source map as base64-encoded string in comment | +| `filename` | `string` | auto-detected | Filename for source map (can include path) | +| `bare` | `boolean` | `false` | Output without top-level function safety wrapper | +| `header` | `boolean` | `false` | Output "Generated by CoffeeScript" header | +| `transpile` | `object` | `undefined` | Babel transpilation options (see [CoffeeScript docs](https://coffeescript.org/#transpilation)) | +| `ast` | `boolean` | `false` | Return abstract syntax tree instead of compiled code | +| `literate` | `boolean` | auto-detected | Parse as Literate CoffeeScript | + +### Configuration Examples + +#### Development Build with Source Maps + +```js +coffeeScriptPlugin({ + inlineMap: true, + bare: true, + header: true, +}); ``` -## Configuration +#### Production Build (Bare Output) -An object containing configuration options may be passed into the plugin constructor `coffeeScriptPlugin`. +```js +coffeeScriptPlugin({ + bare: true, + header: false, +}); +``` + +#### Modern JavaScript Transpilation ```js coffeeScriptPlugin({ bare: true, + transpile: { + presets: ["@babel/preset-env"], + targets: { node: "18" }, + }, }); ``` -The following options are available: +## Advanced Usage + +### TypeScript Integration + +Use alongside esbuild's built-in TypeScript support: + +```js +esbuild.build({ + entryPoints: ["src/main.ts", "src/utils.coffee"], + bundle: true, + plugins: [coffeeScriptPlugin({ bare: true })], + outdir: "dist", + format: "esm", +}); +``` + +### Watch Mode + +```js +const context = await esbuild.context({ + entryPoints: ["src/app.coffee"], + bundle: true, + plugins: [coffeeScriptPlugin()], + outdir: "dist", +}); + +await context.watch(); +console.log("Watching for changes..."); +``` + +### Custom File Extensions + +While not directly configurable, you can pre-process files with custom extensions: + +```js +// For .cjsx or other extensions, rename or copy files first +import { copyFile } from "fs/promises"; + +await copyFile("src/component.cjsx", "src/component.coffee"); + +esbuild.build({ + entryPoints: ["src/component.coffee"], + plugins: [coffeeScriptPlugin()], + // ... +}); +``` + +## Error Handling + +The plugin provides detailed error reporting with location information: + +**invalid.coffee** + +```coffee +hello . 8 # Syntax error +``` + +**Error Output:** + +``` +✘ [ERROR] unexpected . + + invalid.coffee:1:6: + 1 │ hello . 8 + ╵ ^ +``` + +### Handling Build Errors in Code + +```js +try { + await esbuild.build({ + entryPoints: ["main.coffee"], + plugins: [coffeeScriptPlugin()], + logLevel: "silent", // Suppress esbuild's error output + }); +} catch (error) { + console.error("Build failed:", error.message); + // Custom error handling logic +} +``` + +## Migration Guide + +### From v2.x to v3.x + +- **Breaking Change**: Now requires Node.js 20+ +- **New**: ESM-first approach +- **Updated**: Latest CoffeeScript compiler (2.7.0) +- **Updated**: esbuild peer dependency to ^0.25.9 + +**Before (v2.x):** + +```js +const coffeeScriptPlugin = require("esbuild-coffeescript"); +``` + +**After (v3.x):** + +```js +import coffeeScriptPlugin from "esbuild-coffeescript"; +``` + +## Troubleshooting + +### Common Issues + +#### "Cannot resolve CoffeeScript file" + +``` +✘ [ERROR] Could not resolve "./utils.coffee" +``` + +**Solution:** Ensure the file exists and the path is correct. esbuild resolves paths relative to the importing file. + +#### "Unexpected token" in generated code + +This usually indicates a CoffeeScript compilation error. + +**Solution:** Check your CoffeeScript syntax. Use `bare: true` to remove the function wrapper if needed. + +#### Source maps not working + +**Solution:** Use `inlineMap: true` option or configure esbuild's `sourcemap` option: + +```js +esbuild.build({ + sourcemap: true, // or 'inline' + plugins: [coffeeScriptPlugin({ inlineMap: true })], + // ... +}); +``` + +### Performance Tips + +1. **Use `bare: true`** for smaller output when the function wrapper isn't needed +2. **Enable minification** in production builds +3. **Use `bundle: true`** to reduce the number of HTTP requests +4. **Consider code splitting** for large applications + +### Getting Help + +- Check the [esbuild documentation](https://esbuild.github.io/) +- Review [CoffeeScript language guide](https://coffeescript.org/) +- Search existing [GitHub issues](https://github.com/johnie/esbuild-coffeescript/issues) +- Create a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) when reporting bugs + +## Why CoffeeScript? + +While some consider CoffeeScript a thing of the past, it remains actively maintained and widely used: + +- **1.6+ million weekly downloads** on npm +- **Concise, readable syntax** that compiles to clean JavaScript +- **Excellent for rapid prototyping** and functional programming patterns +- **Mature ecosystem** with extensive tooling support + +This plugin provides an excellent migration path for CoffeeScript projects wanting to leverage esbuild's speed and modern bundling features. + +## Contributing + +We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details. + +### Development Setup + +```bash +# Clone the repository +git clone https://github.com/johnie/esbuild-coffeescript.git +cd esbuild-coffeescript + +# Install dependencies +pnpm install + +# Run tests +pnpm test + +# Build the project +pnpm build +``` + +### Running Tests + +```bash +# Run all tests +pnpm test + +# Watch mode +pnpm test:watch + +# Coverage report +pnpm test:coverage +``` + +## License - * `options.inlineMap`, `boolean`: if true, output the source map as a base64-encoded string in a comment at the bottom. - * `options.filename`, `string`: the filename to use for the source map. It can include a path (relative or absolute). - * `options.bare`, `boolean`: if true, output without the top-level function safety wrapper. - * `options.header`, `boolean`: if true, output the Generated by CoffeeScript header. - * `options.transpile`, `object`: if set, this must be an object with the options to pass to Babel. See [Transpilation](https://coffeescript.org/#transpilation). - * `options.ast`, `boolean`: if true, return an abstract syntax tree of the input CoffeeScript source code. - * `options.literate`, `boolean`: if true, parses the code as Literate CoffeeScript. This allows you to write CoffeeScript embedded in Markdown, where indented blocks are treated as executable code. +MIT © [Johnie Hjelm](https://github.com/johnie) -### But CoffeeScript is dead? +--- -While it might seem like it, coffeescript is still downloaded over 1.6 million times every week. Coffeescript is still actively used and widespread, and this plugin provides a great way for these projects to leverage the great esbuild tooling. +**Tip:** ⭐ Star this repo if you find it helpful!