# morse-coder

Lightweight Morse code encoding, decoding, and audio tooling for Node.js and modern bundlers. Convert plain text to Morse, parse Morse back to text, and generate WAV audio for playback or distribution.

Project homepage: https://morse-coder.com  
Source repository: https://github.com/cabbagehao/cabbagehao

## Features

- Complete Morse code maps for letters, digits, and common punctuation marks
- Bidirectional text ↔ Morse translation with customizable separators
- High-quality PCM/WAV synthesis with playback and filesystem export helpers
- Type definitions included for seamless TypeScript integration
- Zero dependencies beyond the lightweight [`play-sound`](https://www.npmjs.com/package/play-sound) helper

## Requirements

- Node.js 18 or newer (ESM module support)
- Optional: a system audio player supported by `play-sound` (afplay, mpg123, mplayer, etc.) if you intend to call `play()`

## Installation

```bash
npm install morse-coder
```

or with pnpm / yarn:

```bash
pnpm add morse-coder
yarn add morse-coder
```

## Basic Usage

```ts
import { encode, decode, audio } from 'morse-coder';

const encoded = encode('SOS'); // ... --- ...
const decoded = decode('... --- ...'); // SOS

const player = audio('HELLO WORLD');
await player.play();            // start playback (requires external player)
await player.save('hello.wav'); // export to WAV
```

## Encoding Options

```ts
import { encode } from 'morse-coder';

const morse = encode('Hello, world!', {
  letterSeparator: ' ',        // default: single space
  wordSeparator: '   ',        // default: ' / '
  unknownFallback: '?'         // default: throws on unknown characters
});
```

- `letterSeparator`: inserted between encoded letters.
- `wordSeparator`: inserted between encoded words.
- `unknownFallback`: string used when an input character is not in the Morse table. If omitted, `encode` will throw an error.

## Decoding Options

```ts
import { decode } from 'morse-coder';

const text = decode('.... . .-.. .-.. --- / .-- --- .-. .-.. -..', {
  letterSeparator: /\s+/,      // supports string, RegExp, or string[]
  wordSeparator: ['/', '   '], // handle both slash and triple spaces
  unknownFallback: '�'         // fallback character on unknown codes
});
```

- `letterSeparator`: splitter used to group Morse tokens into letters.
- `wordSeparator`: splitter used to group tokens into words.
- `unknownFallback`: returned when a code has no matching character; omitted to throw an error instead.

## Inspecting the Character Map

```ts
import { characters } from 'morse-coder';

const { letters, digits, punctuation } = characters();
console.log(letters.A); // .-
```

`characters()` returns shallow copies so you can inspect or extend them without mutating internal state.

## Working with Audio

```ts
import { audio } from 'morse-coder';

const morseAudio = audio('CQ CQ', {
  inputType: 'text', // 'text' | 'morse' | 'auto' (default)
  wpm: 18,
  frequency: 700,
  sampleRate: 44100,
  volume: 0.6
});

await morseAudio.save('cq.wav');   // write to disk
await morseAudio.play();           // play through system default player
morseAudio.stop();                 // stop playback early (no resume)

const buffer = morseAudio.toBuffer(); // obtain the WAV buffer for custom handling
```

When `inputType` is set to `auto`, the helper will detect whether the input looks like raw Morse (containing `.-/`) and choose the appropriate translation path automatically.

> `play()` relies on `play-sound`, which shells out to an installed player such as `afplay` (macOS) or `mplayer` (Linux/Windows). Install one of the supported players if playback fails.

## TypeScript Support

The package ships with TypeScript declarations. If you need to reference the types directly:

```ts
import type { EncodeOptions, DecodeOptions, MorseAudioOptions } from 'morse-coder';
```

No additional configuration is required in a standard TS + ES2020 project.

## Building from Source

```bash
npm run build
```

Outputs compiled ESM modules and `.d.ts` files into the `dist` directory. Bundlers such as Vite, webpack, and esbuild can consume the published package without additional steps.

## License

[MIT](./LICENSE)
