From 1136c68346901f9da28f14c823f032f82b600dc4 Mon Sep 17 00:00:00 2001 From: Vaibhav Rajput Date: Fri, 27 Mar 2026 19:43:55 +0530 Subject: [PATCH] docs: rewrite README, add API.md, gitignore PROJECT_PLAN.md - README: hero section, comparison table, quick start, features, usage examples, charset table, phased roadmap, contributing, about - API.md: full reference for all exports with types and examples - .gitignore: exclude PROJECT_PLAN.md (internal strategy doc) --- .gitignore | 1 + API.md | 561 +++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 250 ++++++++++++++---------- 3 files changed, 711 insertions(+), 101 deletions(-) create mode 100644 API.md diff --git a/.gitignore b/.gitignore index 89bb38d..bd4fdb0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ dist/ .DS_Store coverage/ .env +PROJECT_PLAN.md diff --git a/API.md b/API.md new file mode 100644 index 0000000..8e75165 --- /dev/null +++ b/API.md @@ -0,0 +1,561 @@ +# API Reference + +Full documentation for `@morsecodeapp/morse` v0.1.0. + +All exports are available from both `@morsecodeapp/morse` and `@morsecodeapp/morse/core`. + +--- + +## Table of Contents + +- [encode()](#encode) +- [encodeDetailed()](#encodedetailed) +- [decode()](#decode) +- [decodeDetailed()](#decodedetailed) +- [Charsets](#charsets) +- [Prosigns](#prosigns) +- [Timing](#timing) +- [Stats](#stats) +- [Validation](#validation) +- [Types](#types) + +--- + +## encode() + +Converts text to Morse code. + +```ts +function encode(text: string, options?: EncodeOptions): string +``` + +**Examples:** + +```ts +import { encode } from '@morsecodeapp/morse'; + +encode('SOS'); // '... --- ...' +encode('Hello World'); // '.... . .-.. .-.. --- / .-- --- .-. .-.. -..' +encode('ПРИВЕТ', { charset: 'cyrillic' }); // '.--. .-. .. .-- . -' +encode('SOS', { dot: '•', dash: '—' }); // '••• ——— •••' +encode('SOS', { separator: '|', wordSeparator: ' // ' }); +``` + +### EncodeOptions + +| Option | Type | Default | Description | +|--------|------|---------|-------------| +| `charset` | `CharsetId` | `'itu'` | Character set to use | +| `fallbackCharsets` | `CharsetId[]` | `[]` | Additional charsets to try for unmatched characters | +| `dot` | `string` | `'.'` | Dot symbol in output | +| `dash` | `string` | `'-'` | Dash symbol in output | +| `separator` | `string` | `' '` | Separator between letters | +| `wordSeparator` | `string` | `' / '` | Separator between words | +| `invalid` | `string` | `'?'` | Replacement for characters with no mapping | + +--- + +## encodeDetailed() + +Like `encode()` but returns an `EncodeResult` with validity info. + +```ts +function encodeDetailed(text: string, options?: EncodeOptions): EncodeResult +``` + +**Example:** + +```ts +import { encodeDetailed } from '@morsecodeapp/morse'; + +encodeDetailed('A§B'); +// { morse: '.- ? -...', valid: false, errors: ['§'] } + +encodeDetailed('SOS'); +// { morse: '... --- ...', valid: true, errors: [] } +``` + +### EncodeResult + +| Field | Type | Description | +|-------|------|-------------| +| `morse` | `string` | The Morse code output | +| `valid` | `boolean` | `true` if all characters were mapped | +| `errors` | `string[]` | Characters that could not be encoded | + +--- + +## decode() + +Converts Morse code back to text. + +```ts +function decode(morse: string, options?: DecodeOptions): string +``` + +**Examples:** + +```ts +import { decode } from '@morsecodeapp/morse'; + +decode('... --- ...'); // 'SOS' +decode('.... . .-.. .-.. --- / .-- --- .-. .-.. -..'); // 'HELLO WORLD' +decode('.-', { charset: 'cyrillic' }); // 'А' +decode('••• ——— •••', { dot: '•', dash: '—' }); // 'SOS' +``` + +### DecodeOptions + +| Option | Type | Default | Description | +|--------|------|---------|-------------| +| `charset` | `CharsetId` | `'itu'` | Character set to use | +| `fallbackCharsets` | `CharsetId[]` | `[]` | Additional charsets to try for unmatched patterns | +| `dot` | `string` | `'.'` | Dot symbol in input | +| `dash` | `string` | `'-'` | Dash symbol in input | +| `separator` | `string` | `' '` | Separator between letters | +| `wordSeparator` | `string` | `' / '` | Separator between words | +| `invalid` | `string` | `'?'` | Replacement for unrecognized patterns | + +--- + +## decodeDetailed() + +Like `decode()` but returns a `DecodeResult` with validity info. + +```ts +function decodeDetailed(morse: string, options?: DecodeOptions): DecodeResult +``` + +**Example:** + +```ts +import { decodeDetailed } from '@morsecodeapp/morse'; + +decodeDetailed('... --- ... .-.-.-'); +// { text: 'SOS.', valid: true, errors: [] } + +decodeDetailed('... @@@ ...'); +// { text: 'S?S', valid: false, errors: ['@@@'] } +``` + +### DecodeResult + +| Field | Type | Description | +|-------|------|-------------| +| `text` | `string` | The decoded text | +| `valid` | `boolean` | `true` if all patterns were mapped | +| `errors` | `string[]` | Morse patterns that could not be decoded | + +--- + +## Charsets + +### getCharset() + +Returns a `Charset` object by ID. + +```ts +function getCharset(id?: CharsetId): Charset +``` + +```ts +import { getCharset } from '@morsecodeapp/morse'; + +const itu = getCharset('itu'); +itu.charToMorse['A']; // '.-' +itu.morseToChar['.-']; // 'A' +itu.name; // 'International (ITU)' +``` + +Throws an `Error` if the charset ID is unknown. + +### listCharsets() + +Returns an array of all available charset IDs. + +```ts +function listCharsets(): CharsetId[] +``` + +```ts +listCharsets(); +// ['itu', 'american', 'latin-ext', 'cyrillic', 'greek', 'hebrew', +// 'arabic', 'persian', 'japanese', 'korean', 'thai'] +``` + +### listCharsetsDetailed() + +Returns charset metadata including character count. + +```ts +function listCharsetsDetailed(): Array<{ id: CharsetId; name: string; size: number }> +``` + +```ts +listCharsetsDetailed(); +// [{ id: 'itu', name: 'International (ITU)', size: 54 }, ...] +``` + +### detectCharset() + +Auto-detects the best charset for the given text by coverage score. + +```ts +function detectCharset(text: string): CharsetId +``` + +```ts +detectCharset('ПРИВЕТ'); // 'cyrillic' +detectCharset('HELLO'); // 'itu' +detectCharset('こんにちは'); // 'japanese' +``` + +### Direct charset imports + +Individual charsets are also exported directly: + +```ts +import { itu, cyrillic, greek, arabic } from '@morsecodeapp/morse'; + +itu.charToMorse['S']; // '...' +cyrillic.charToMorse['Ж']; // '...-' +``` + +Available: `itu`, `american`, `latinExt`, `cyrillic`, `greek`, `hebrew`, `arabic`, `persian`, `japanese`, `korean`, `thai` + +### Charset interface + +```ts +interface Charset { + readonly id: CharsetId; + readonly name: string; + readonly charToMorse: Readonly>; + readonly morseToChar: Readonly>; +} +``` + +### CharsetId + +```ts +type CharsetId = + | 'itu' | 'american' | 'latin-ext' | 'cyrillic' | 'greek' + | 'hebrew' | 'arabic' | 'persian' | 'japanese' | 'korean' | 'thai'; +``` + +--- + +## Prosigns + +Procedural signals — sent as single unbroken characters with no inter-character gaps. + +### PROSIGNS + +A `readonly Prosign[]` array of all 10 standard prosigns. + +```ts +import { PROSIGNS } from '@morsecodeapp/morse'; + +PROSIGNS[0]; // { label: 'SOS', morse: '...---...', meaning: 'International distress signal' } +``` + +| Label | Morse | Meaning | +|-------|-------|---------| +| SOS | `...---...` | International distress signal | +| AR | `.-.-.` | End of message | +| SK | `...-.-` | End of contact / Silent Key | +| BT | `-...-` | Break / New paragraph | +| KN | `-.--. ` | Go ahead, named station only | +| AS | `.-...` | Wait / Stand by | +| CL | `-.-..-.." ` | Closing station | +| CT | `-.-.-` | Commence transmission | +| SN | `...-.` | Understood / Verified | +| HH | `........` | Error / Correction | + +### encodeProsign() + +Returns the morse pattern for a prosign label, or `undefined`. + +```ts +function encodeProsign(label: string): string | undefined +``` + +```ts +encodeProsign('SOS'); // '...---...' +encodeProsign('AR'); // '.-.-.' +encodeProsign('XYZ'); // undefined +``` + +### decodeProsign() + +Returns the prosign label for a morse pattern, or `undefined`. + +```ts +function decodeProsign(morse: string): string | undefined +``` + +```ts +decodeProsign('...---...'); // 'SOS' +decodeProsign('.-.-.'); // 'AR' +``` + +### getProsign() + +Returns the full `Prosign` object by label, or `undefined`. + +```ts +function getProsign(label: string): Prosign | undefined +``` + +```ts +getProsign('SOS'); +// { label: 'SOS', morse: '...---...', meaning: 'International distress signal' } +``` + +### listProsigns() + +Returns an array of all prosign labels. + +```ts +function listProsigns(): string[] +``` + +```ts +listProsigns(); // ['SOS', 'AR', 'SK', 'BT', 'KN', 'AS', 'CL', 'CT', 'SN', 'HH'] +``` + +--- + +## Timing + +Based on the PARIS standard — the word PARIS is 50 dot-units, so at W WPM: `unit = 1200 / W` ms. + +### timing() + +Calculate standard PARIS timing values. + +```ts +function timing(wpm?: number): TimingValues +``` + +Default WPM is 20. Clamped to 1–60. + +```ts +import { timing } from '@morsecodeapp/morse'; + +timing(20); +// { unit: 60, dot: 60, dash: 180, intraChar: 60, interChar: 180, interWord: 420 } + +timing(5); +// { unit: 240, dot: 240, dash: 720, intraChar: 240, interChar: 720, interWord: 1680 } +``` + +### farnsworthTiming() + +Characters sent at `charWpm`, with extra gaps to achieve `overallWpm`. + +```ts +function farnsworthTiming(overallWpm?: number, charWpm?: number): TimingValues +``` + +Defaults: `overallWpm = 15`, `charWpm = 20`. + +```ts +import { farnsworthTiming } from '@morsecodeapp/morse'; + +farnsworthTiming(10, 20); +// Characters at 20 WPM speed, but overall pace is 10 WPM +// Extra delay added to interChar and interWord gaps +``` + +### duration() + +Calculate total playback duration of a morse string in milliseconds. + +```ts +function duration(morse: string, wpm?: number): number +``` + +```ts +import { duration } from '@morsecodeapp/morse'; + +duration('... --- ...'); // 1620 (ms at 20 WPM) +duration('... --- ...', 10); // 3240 (ms at 10 WPM) +``` + +### formatDuration() + +Format milliseconds to a human-readable string. + +```ts +function formatDuration(ms: number): string +``` + +```ts +import { formatDuration } from '@morsecodeapp/morse'; + +formatDuration(500); // '500ms' +formatDuration(3500); // '3.5s' +formatDuration(65000); // '1m 5.0s' +``` + +### Constants + +```ts +import { DEFAULT_WPM, MIN_WPM, MAX_WPM } from '@morsecodeapp/morse'; + +DEFAULT_WPM; // 20 +MIN_WPM; // 1 +MAX_WPM; // 60 +``` + +### TimingValues + +```ts +interface TimingValues { + unit: number; // Base unit in ms + dot: number; // 1 unit + dash: number; // 3 units + intraChar: number; // Gap between signals within a character (1 unit) + interChar: number; // Gap between characters (3 units, extended for Farnsworth) + interWord: number; // Gap between words (7 units, extended for Farnsworth) +} +``` + +--- + +## Stats + +### stats() + +Compute statistics for a morse code string. + +```ts +function stats(morse: string, wpm?: number): MorseStats +``` + +```ts +import { stats } from '@morsecodeapp/morse'; + +stats('... --- ...'); +// { +// dots: 6, +// dashes: 3, +// signals: 9, +// characters: 3, +// words: 1, +// durationMs: 1620, +// durationSec: '1.6', +// durationFormatted: '1.6s' +// } + +stats('.... . .-.. .-.. --- / .-- --- .-. .-.. -..', 15); +// Statistics at 15 WPM +``` + +### MorseStats + +```ts +interface MorseStats { + dots: number; // Count of dots + dashes: number; // Count of dashes + signals: number; // dots + dashes + characters: number; // Number of letters/numbers + words: number; // Number of words + durationMs: number; // Estimated duration in milliseconds + durationSec: string; // Duration in seconds (1 decimal, e.g., '1.6') + durationFormatted: string; // Human-readable (e.g., '1.6s', '1m 5.0s') +} +``` + +--- + +## Validation + +### isValidMorse() + +Check if a string contains only valid Morse characters (dots, dashes, spaces, slashes). + +```ts +function isValidMorse(morse: string): boolean +``` + +```ts +isValidMorse('... --- ...'); // true +isValidMorse('HELLO'); // false +isValidMorse('... @@@ ...'); // false +``` + +### isEncodable() + +Check if all characters in text have a mapping in the given charset. + +```ts +function isEncodable(text: string, charset?: CharsetId): boolean +``` + +```ts +isEncodable('HELLO'); // true (defaults to 'itu') +isEncodable('HELLO', 'itu'); // true +isEncodable('Ж', 'itu'); // false +isEncodable('Ж', 'cyrillic'); // true +``` + +### isDecodable() + +Check if all morse patterns can be decoded with the given charset. + +```ts +function isDecodable(morse: string, charset?: CharsetId): boolean +``` + +```ts +isDecodable('... --- ...'); // true +isDecodable('... --- ...', 'itu'); // true +isDecodable('HELLO'); // false (not valid morse) +``` + +### findInvalidChars() + +Find characters in text that cannot be encoded with the given charset. + +```ts +function findInvalidChars(text: string, charset?: CharsetId): string[] +``` + +```ts +findInvalidChars('Hello!§'); // ['§'] +findInvalidChars('ABC'); // [] +``` + +### findInvalidPatterns() + +Find morse patterns that cannot be decoded with the given charset. + +```ts +function findInvalidPatterns(morse: string, charset?: CharsetId): string[] +``` + +```ts +findInvalidPatterns('... --- .---.--.'); // ['.---.--.' ] (not a real pattern) +findInvalidPatterns('... --- ...'); // [] +``` + +--- + +## Types + +All types are exported and available for import: + +```ts +import type { + CharsetId, + Charset, + EncodeOptions, + DecodeOptions, + EncodeResult, + DecodeResult, + TimingValues, + Prosign, + MorseStats, +} from '@morsecodeapp/morse'; +``` diff --git a/README.md b/README.md index 0c437bc..b0f0510 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,38 @@ +
+ # @morsecodeapp/morse -> A comprehensive, tree-shakeable Morse code library for JavaScript & TypeScript. +**The most complete Morse code library for JavaScript and TypeScript.** + +Encode, decode, validate, and analyze — with 11 character sets, prosigns, PARIS timing, and Farnsworth spacing. Zero dependencies. [![npm version](https://img.shields.io/npm/v/@morsecodeapp/morse.svg)](https://www.npmjs.com/package/@morsecodeapp/morse) [![bundle size](https://img.shields.io/bundlephobia/minzip/@morsecodeapp/morse)](https://bundlephobia.com/package/@morsecodeapp/morse) -[![license](https://img.shields.io/npm/l/@morsecodeapp/morse.svg)](./LICENSE) [![tests](https://img.shields.io/github/actions/workflow/status/AppsYogi-com/morsecodeapp/ci.yml?label=tests)](https://github.com/AppsYogi-com/morsecodeapp/actions) +[![license](https://img.shields.io/npm/l/@morsecodeapp/morse.svg)](./LICENSE) -**Built by the team behind [morsecodeapp.com](https://morsecodeapp.com)** — the most feature-rich Morse code translator on the web. +[Install](#install) · [Quick Start](#quick-start) · [API Reference](API.md) · [Report Bug](https://github.com/AppsYogi-com/morsecodeapp/issues) -## Features +
-- **11 character sets** — ITU, American, Latin Extended, Cyrillic, Greek, Hebrew, Arabic, Persian, Japanese (Wabun), Korean (SKATS), Thai -- **10 prosigns** — SOS, AR, SK, BT, KN, AS, CL, CT, SN, HH -- **PARIS timing** — standard and Farnsworth spacing calculations -- **Zero dependencies** — nothing but your code -- **Tree-shakeable** — import only what you need via `@morsecodeapp/morse/core` -- **TypeScript-first** — strict types, full `.d.ts` declarations -- **ESM + CJS** — works everywhere: Node.js, Bun, Deno, browsers (via bundler) -- **Roundtrip safe** — `decode(encode(text)) === text` for all supported characters +--- + +## Why this library? + +| | @morsecodeapp/morse | morse-code-translator | morsify | +|--|:---:|:---:|:---:| +| Character sets | **11** | 12 | 1 | +| Prosigns (SOS, AR, SK…) | **10** | — | — | +| Farnsworth timing | **Yes** | — | — | +| PARIS timing calculator | **Yes** | — | — | +| Statistics & duration | **Yes** | — | — | +| Validation utilities | **Yes** | — | — | +| Tree-shakeable sub-paths | **Yes** | — | — | +| TypeScript-first | **Yes** | Partial | — | +| Zero dependencies | **Yes** | 1 dep | — | +| Roundtrip safe | **Yes** | — | — | + +--- ## Install @@ -26,62 +40,52 @@ npm install @morsecodeapp/morse ``` +Works with npm, yarn, pnpm, and bun. + +--- + ## Quick Start ```ts import { encode, decode } from '@morsecodeapp/morse'; -encode('SOS'); // '... --- ...' -decode('... --- ...'); // 'SOS' +encode('SOS'); // '... --- ...' +decode('... --- ...'); // 'SOS' -encode('Hello World'); // '.... . .-.. .-.. --- / .-- --- .-. .-.. -..' +encode('Hello World'); // '.... . .-.. .-.. --- / .-- --- .-. .-.. -..' ``` -## API - -### `encode(text, options?): string` - -Converts text to Morse code. - -```ts -import { encode } from '@morsecodeapp/morse'; - -// Basic -encode('SOS'); // '... --- ...' +Three lines. That's it. -// Cyrillic -encode('ПРИВЕТ', { charset: 'cyrillic' }); // '.--. .-. .. .-- . -' +--- -// Custom symbols -encode('SOS', { dot: '•', dash: '—' }); // '••• ——— •••' -``` +## Features -**Options:** +- **11 character sets** — ITU, American, Latin Extended, Cyrillic, Greek, Hebrew, Arabic, Persian, Japanese (Wabun), Korean (SKATS), Thai +- **10 prosigns** — SOS, AR, SK, BT, KN, AS, CL, CT, SN, HH +- **PARIS timing** — standard and Farnsworth spacing, duration estimates +- **Validation** — check morse syntax, encodability, find unsupported characters +- **Statistics** — dots, dashes, signal count, duration in ms/sec +- **Zero dependencies** — nothing but your code +- **Tree-shakeable** — import from `@morsecodeapp/morse/core` for minimal bundle +- **TypeScript-first** — strict types, full `.d.ts`, zero `any` +- **ESM + CJS** — works in Node.js, Bun, Deno, and browsers (via bundler) +- **Roundtrip safe** — `decode(encode(text)) === text` for all supported characters -| Option | Type | Default | Description | -|--------|------|---------|-------------| -| `charset` | `CharsetId` | `'itu'` | Character set to use | -| `fallbackCharsets` | `CharsetId[]` | `[]` | Additional charsets for mixed-script text | -| `dot` | `string` | `'.'` | Dot symbol in output | -| `dash` | `string` | `'-'` | Dash symbol in output | -| `separator` | `string` | `' '` | Letter separator | -| `wordSeparator` | `string` | `' / '` | Word separator | -| `invalid` | `string` | `'?'` | Replacement for unknown characters | +--- -### `decode(morse, options?): string` +## Usage Examples -Converts Morse code back to text. +### Encode with different charsets ```ts -import { decode } from '@morsecodeapp/morse'; +import { encode } from '@morsecodeapp/morse'; -decode('... --- ...'); // 'SOS' -decode('.-', { charset: 'cyrillic' }); // 'А' +encode('ПРИВЕТ', { charset: 'cyrillic' }); // '.--. .-. .. .-- . -' +encode('SOS', { dot: '•', dash: '—' }); // '••• ——— •••' ``` -### `encodeDetailed(text, options?): EncodeResult` - -Like `encode()` but returns detailed validation info: +### Detailed results with error info ```ts import { encodeDetailed } from '@morsecodeapp/morse'; @@ -90,69 +94,60 @@ const result = encodeDetailed('A§B'); // { morse: '.- ? -...', valid: false, errors: ['§'] } ``` -### `timing(wpm?): TimingValues` - -Calculate PARIS standard timing in milliseconds. +### Prosigns ```ts -import { timing } from '@morsecodeapp/morse'; +import { encodeProsign, decodeProsign, PROSIGNS } from '@morsecodeapp/morse'; -const t = timing(20); -// { unit: 60, dot: 60, dash: 180, intraChar: 60, interChar: 180, interWord: 420 } +encodeProsign('SOS'); // '...---...' +decodeProsign('...---...'); // 'SOS' +PROSIGNS.length; // 10 ``` -### `farnsworthTiming(overallWpm?, charWpm?): TimingValues` - -Farnsworth timing — characters sent fast, extra gap between them. +### Timing calculations ```ts -import { farnsworthTiming } from '@morsecodeapp/morse'; +import { timing, farnsworthTiming } from '@morsecodeapp/morse'; + +const t = timing(20); +// { unit: 60, dot: 60, dash: 180, intraChar: 60, interChar: 180, interWord: 420 } const ft = farnsworthTiming(10, 20); -// Characters at 20 WPM, overall pace at 10 WPM +// Characters at 20 WPM, overall pace slowed to 10 WPM ``` -### `stats(morse, wpm?): MorseStats` - -Get statistics about a Morse code string. +### Statistics ```ts import { stats } from '@morsecodeapp/morse'; -const s = stats('... --- ...'); -// { dots: 6, dashes: 3, signals: 9, characters: 3, words: 1, durationMs: 1620, ... } +stats('... --- ...'); +// { dots: 6, dashes: 3, signals: 9, characters: 3, words: 1, +// durationMs: 1620, durationSec: '1.6', durationFormatted: '1.6s' } ``` -### Character Sets +### Validation ```ts -import { listCharsets, getCharset, detectCharset } from '@morsecodeapp/morse'; +import { isValidMorse, isEncodable, findInvalidChars } from '@morsecodeapp/morse'; -listCharsets(); // ['itu', 'american', 'latin-ext', 'cyrillic', ...] -getCharset('cyrillic'); // { id, name, charToMorse, morseToChar } -detectCharset('ПРИВЕТ'); // 'cyrillic' +isValidMorse('... --- ...'); // true +isEncodable('HELLO', 'itu'); // true +findInvalidChars('A§B'); // ['§'] ``` -### Prosigns +### Charset detection ```ts -import { encodeProsign, decodeProsign, PROSIGNS } from '@morsecodeapp/morse'; +import { detectCharset, listCharsets } from '@morsecodeapp/morse'; -encodeProsign('SOS'); // '...---...' -decodeProsign('...---...'); // 'SOS' -PROSIGNS; // [{ label: 'SOS', morse: '...---...', meaning: 'International distress signal' }, ...] +detectCharset('ПРИВЕТ'); // 'cyrillic' +listCharsets(); // ['itu', 'american', 'latin-ext', 'cyrillic', ...] ``` -### Validation +> Full API documentation with all options and return types → **[API.md](API.md)** -```ts -import { isValidMorse, isEncodable, findInvalidChars } from '@morsecodeapp/morse'; - -isValidMorse('... --- ...'); // true -isValidMorse('HELLO'); // false -isEncodable('HELLO', 'itu'); // true -findInvalidChars('A§B'); // ['§'] -``` +--- ## Tree Shaking @@ -162,37 +157,90 @@ For minimal bundle size, import from the `/core` sub-path: import { encode, decode } from '@morsecodeapp/morse/core'; ``` -This gives you encode/decode, charsets, timing, stats, and validation — no DOM or Web Audio dependencies. +Both paths export the same API. The `/core` entry point is optimized for bundlers that benefit from explicit sub-path imports. + +--- ## Supported Character Sets -| ID | Name | Characters | -|----|------|-----------| -| `itu` | International (ITU) | A–Z, 0–9, 18 punctuation marks | +| ID | Name | Script | +|----|------|--------| +| `itu` | International (ITU-R M.1677-1) | Latin A–Z, 0–9, punctuation | | `american` | American Morse | Historical telegraph variant | -| `latin-ext` | Latin Extended | ITU + accented European characters | -| `cyrillic` | Russian/Cyrillic | А–Я, 0–9 | -| `greek` | Greek | Α–Ω, 0–9 | -| `hebrew` | Hebrew | א–ת, 0–9 | -| `arabic` | Arabic | Arabic alphabet, 0–9 | +| `latin-ext` | Latin Extended | Accented European characters | +| `cyrillic` | Russian / Cyrillic | А–Я | +| `greek` | Greek | Α–Ω | +| `hebrew` | Hebrew | א–ת | +| `arabic` | Arabic | Arabic alphabet | | `persian` | Persian (Farsi) | Extended Arabic for Farsi | | `japanese` | Japanese (Wabun) | Katakana syllabary | | `korean` | Korean (SKATS) | Jamo consonants & vowels | | `thai` | Thai | Thai consonants, vowels, tone marks | +--- + ## Roadmap -- [ ] 🔊 **Audio** — Web Audio playback, WAV export, gain envelope -- [ ] 📱 **Visual** — Flash, vibrate, visual output -- [ ] 👆 **Tap** — Decode morse from tap/click timing -- [ ] ⚛️ **React** — `useMorse()` hook, `` component -- [ ] 🧠 **Decoder** — Real-time audio decoding via Web Audio +### Phase 1 — Core ✅ `v0.1.0` +> Encode, decode, validate — the foundation. -## About +- [x] 11 character sets (ITU, American, Cyrillic, Greek, Hebrew, Arabic, Persian, Japanese, Korean, Thai, Latin Extended) +- [x] 10 prosigns (SOS, AR, SK, BT, KN, AS, CL, CT, SN, HH) +- [x] PARIS standard + Farnsworth timing +- [x] Statistics, validation, charset detection +- [x] ESM + CJS, TypeScript-first, zero dependencies +- [x] 99%+ test coverage + +### Phase 2 — Audio 🔊 `v0.2.0` ← up next +> Hear your Morse code. + +- [ ] `MorsePlayer` class — Web Audio API playback with play/pause/stop +- [ ] WAV export (44.1kHz, 16-bit PCM) +- [ ] Sound presets — telegraph, radio, military, crystal +- [ ] Gain envelope — clean start/stop, no audio clicks +- [ ] Configurable frequency, WPM, and volume + +### Phase 3 — Visual + Tap 📱 `v0.3.0` +> See it. Tap it. + +- [ ] Screen flash / LED controller +- [ ] Vibration API output +- [ ] Tap-to-morse decoder (touch/click timing → text) + +### Phase 4 — React ⚛️ `v0.4.0` +> Drop-in components for React apps. + +- [ ] `useMorse()` hook +- [ ] `` audio component +- [ ] `` waveform component + +### Phase 5 — Decoder 🧠 `v0.5.0` +> Decode Morse from real audio. -This library is built and maintained by the team behind **[morsecodeapp.com](https://morsecodeapp.com)** — a comprehensive suite of Morse code tools including a translator, audio player, learning resources, and more. +- [ ] Real-time audio decoding (Goertzel algorithm) +- [ ] Microphone input +- [ ] Audio file decoding + +--- + +## Contributing + +Contributions are welcome. Please read the [Contributing Guide](CONTRIBUTING.md) before opening a Pull Request. + +```bash +git clone https://github.com/AppsYogi-com/morsecodeapp.git +cd morsecodeapp +npm install +npm test # Run tests +npm run build # ESM + CJS + DTS +npm run lint # Type check +``` + +--- + +## About -We created this library to share the expertise we've built powering tens of thousands of Morse code translations every month. +Built and maintained by the team behind **[MorseCodeApp.com](https://morsecodeapp.com)** — a comprehensive suite of Morse code tools used by thousands of people every month. ## License