diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3a90add..43a4915 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -57,13 +57,14 @@ P4RS3LT0NGV3/ │ └── transformers/ # Transformer sources → bundled to dist/js/bundles/ │ ├── BaseTransformer.js │ ├── index.js # Generated by npm run build:index (gitignored) -│ ├── ancient/ │ ├── case/ │ ├── cipher/ +│ ├── concealment/ │ ├── encoding/ -│ ├── fantasy/ │ ├── format/ +│ ├── signwriting/ │ ├── special/ +│ ├── symbol/ │ ├── technical/ │ ├── unicode/ │ └── visual/ @@ -89,7 +90,8 @@ P4RS3LT0NGV3/ │ ├── fetch-glitch-data.js │ ├── inject-tool-scripts.js # Discovers tools; updates index.template.html + toolRegistry │ ├── inject-tool-templates.js # Builds dist/index.html from index.template.html + templates/ -│ └── readme-transform-section.js # Maintainer helper for README transform list +│ ├── build-code-vendor.js # Bundles QR/barcode libs → js/vendor/ +│ └── build-alphabet-transforms.js # Regenerates symbol/*.js from data/alphabets/ ├── tests/ │ ├── test_universal.js │ └── test_steganography_options.js @@ -172,7 +174,6 @@ Transformers are the core text transformation logic. See `src/transformers/READM export default new BaseTransformer({ name: 'My Cipher', priority: 60, // See priority guide in transformers/README.md - category: 'ciphers', func: function(text) { // Encoding logic return encoded; @@ -203,7 +204,10 @@ Transformers are the core text transformation logic. See `src/transformers/READM - Add test cases to `tests/test_universal.js` - Run `npm test` to verify -**Important:** Transformers are automatically discovered and bundled. No manual registration needed! +6. Update documentation: + - Add a bullet to the matching category under **Text Transformations** in the root `README.md` + +**Important:** Transformers are automatically discovered and bundled. Category is set from the parent folder at build time — no manual registration needed. ### 2. Adding a New Tool (New Tab/Feature) diff --git a/README.md b/README.md index 0c0ae47..e917c0f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🐍 P4RS3LT0NGV3 - Universal Text Translator -A powerful web-based text transformation and steganography tool with **159** built-in text transforms spanning encodings, classical and modern ciphers, Unicode styles, formatting, and niche alphabets. Think of it as a universal translator for ALL alphabets and writing systems! +A powerful web-based text transformation and steganography tool with **223** built-in text transforms spanning encodings, classical and modern ciphers, Unicode styles, formatting, and niche alphabets. Think of it as a universal translator for ALL alphabets and writing systems! The app is a **static site**: run **`npm run build`** (after `npm install`), then open **`dist/index.html`** in your browser—no local server required. **Alternatively**, you can run it as a local app over HTTP with **`npm start`** or **`npx serve dist -l 8080`** (see [Getting Started](#getting-started) below). Core transforms, decoder, and steganography work **without** calling the cloud; features that use [OpenRouter](https://openrouter.ai/) need **network access** and an API key (see below). @@ -15,22 +15,22 @@ The app is a **static site**: run **`npm run build`** (after `npm install`), the Categories match the Transform tab and the folders under `src/transformers/` (each transformer’s `name` as shown in the UI). Short descriptions explain what each transform does. -#### **Ancient** -- **Elder Futhark** - Germanic Elder Futhark runes -- **Hieroglyphics** - Egyptian hieroglyph-style mapping -- **Ogham (Celtic)** - Celtic Ogham tree alphabet -- **Roman Numerals** - Arabic numerals ↔ Roman numerals - #### **Case** - **Alternating Case** - Alternate uppercase and lowercase per letter (first letter upper or lower) - **camelCase** - lowerCamelCase for identifiers +- **Capitalize Words** - Capitalize the first letter of each word - **kebab-case** - kebab-case for slugs and identifiers +- **Lowercase All** - Lowercase entire text - **Random Case** - Random casing per character - **Sentence Case** - Capitalize the first letter of each sentence - **snake_case** - snake_case for identifiers - **Title Case** - Capitalize each word +- **Toggle Case** - Swap case of each letter +- **Uppercase All** - Uppercase entire text #### **Cipher** +- **A1Z26** - A=1 … Z=26 letter numbering +- **Acéré Cipher** - Solfege / duration encoding for musical steganography - **ADFGX Cipher** - WWI ADFGVX-style polybius + column transposition - **N7AX Cipher** - ADFGX-style polybius with N7AX coordinates + column transposition - **Affine Cipher** - Affine substitution (ax + b mod 26) @@ -40,16 +40,21 @@ Categories match the Transform tab and the folders under `src/transformers/` (ea - **Beaufort Cipher** - Beaufort key-table polyalphabetic cipher - **Bifid Cipher** - Polybius square + row/column interleaving - **Caesar Cipher** - Classic alphabet shift (configurable) +- **Codons (Genetic Code)** - Letters A–Z as DNA triplets - **Columnar Transposition** - Columnar transposition with a keyword +- **Double Transposition** - Two keyed columnar transpositions - **Four-Square Cipher** - Four 5×5 squares; digraph substitution +- **Fractionated Morse** - Morse with fractionation pattern - **Gronsfeld Cipher** - Vigenère family with numeric key - **Hill Cipher** - Matrix-based multi-letter substitution - **Homophonic Cipher** - Multiple ciphertext symbols per plaintext letter +- **Multiplicative Cipher** - Multiply by key mod 26 - **Nihilist Cipher** - Keyed Polybius + additive encryption -- **Pigpen Cipher** - Masonic / pigpen grid symbols - **Playfair Cipher** - Digraph cipher on a 5×5 square - **Polybius Square** - Letter ↔ grid coordinates - **Porta Cipher** - Porta table polyalphabetic cipher +- **QWERTY Right Shift** - Map keys to the key to the right on QWERTY +- **Route Cipher** - Read ciphertext along a grid route - **Rail Fence** - Zig-zag rail-fence transposition - **ROT128** - UTF-16 code unit rotation by 128 - **ROT13** - Rotate Latin letters by 13 places @@ -58,11 +63,24 @@ Categories match the Transform tab and the folders under `src/transformers/` (ea - **ROT5** - Rotate digits 0–9 by 5 - **ROT8000** - Plane-0 Unicode BMP rotation cipher - **Scytale Cipher** - Wrap-around strip (scytale) transposition +- **Tap Code** - Polybius / tap / prison code - **Trifid Cipher** - Three Polybius cubes + trifid grouping +- **Trithemius Cipher** - Progressive Caesar (tabula recta) - **Two-Square Cipher** - Digraph cipher with two Playfair squares +- **Vernam Cipher** - One-time pad XOR (mod 26) - **Vigenère Cipher** - Polyalphabetic cipher with repeating keyword - **XOR Cipher** - XOR with a repeating key +#### **Concealment** +- **Acrostic** - First letter of each line or word spells a message +- **Cardan Grille** - Hide text through a rotating grille +- **Homoglyph Generator** - Latin letters to Cyrillic homoglyphs +- **Invisible Text** - Unicode Tags / invisible carrier encoding +- **Null Cipher** - Fixed letter position in each cover word +- **Trevanion Cipher** - Letters N positions after punctuation marks +- **Whitespace Steganography** - Hide bits in whitespace patterns +- **Zero-Width Steganography** - Hide data with zero-width characters + #### **Encoding** - **ASCII85** - Ascii85 / Adobe-style base-85 encoding - **Base122** - Binary → 122 printable ASCII characters @@ -74,46 +92,39 @@ Categories match the Transform tab and the folders under `src/transformers/` (ea - **Base64** - Standard Base64 - **Base64 URL** - Base64url (URL-safe alphabet) - **Base91** - basE91 / Ascii91 encoding +- **Bibi-binary Code** - UTF-8 bytes via Bibi-binary syllables - **Baudot Code (ITA2)** - Five-bit telegraph / ITA2 - **Binary Coded Decimal** - Decimal digits as BCD nibbles - **Binary** - Text bytes ↔ binary strings +- **Bitwise NOT** - UTF-8 bytes NOT'd per byte; encode output is hex (decode pastes hex back to text) +- **Brainfuck** - Text ↔ Brainfuck program +- **Decabit Code** - Ten-bit patterns for decimal digits - **EBCDIC** - EBCDIC byte encoding -- **Emoji Encoding** - Payload encoded with emoji +- **Base256Emoji** - Multiformats multibase encoding (1 byte → 1 emoji) - **Gray Code** - Binary Gray code - **Hexadecimal** - Hex encode/decode bytes - **HTML Entities** - HTML entity escape / unescape -- **Invisible Text** - Unicode Tags / invisible carrier encoding +- **Manchester Code** - Manchester line coding +- **Metaphone** - Metaphone phonetic encoding - **Quoted-Printable** - MIME quoted-printable +- **Shadoks Numeral System** - UTF-8 bytes as Shadoks base-4 words - **Unicode Code Points** - Characters ↔ U+XXXX code points - **URL Encode** - application/x-www-form-urlencoded - **Uuencoding** - Classic uuencode / uudecode - **YEnc** - yEnc line-oriented binary encoding - **Z85** - ZeroMQ Z85 encoding -#### **Fantasy** -- **Aurebesh (Star Wars)** - Galactic Basic Aurebesh alphabet -- **Dovahzul (Dragon)** - Skyrim Dovahzul transliteration -- **Klingon** - Klingon transliteration -- **Quenya (Tolkien Elvish)** - Tolkien Quenya mapping -- **Tengwar Script** - Elvish Tengwar script - #### **Format** -- **Bitwise NOT** - UTF-8 bytes NOT'd per byte; encode output is hex (decode pastes hex back to text) - **Boustrophedon** - Serpentine / alternating line direction -- **Capitalize Words** - Capitalize the first letter of each word +- **Group Letters** - Insert separators between letters - **Indent** - Add leading spaces to each line (configurable width) -- **Javanais** - French “javanais” vowel-insertion game -- **Latin Gibberish** - Latin-flavored pseudo-text -- **Leetspeak** - 1337-style character substitutions - **Letters Only** - Keep letters; strip other characters - **Letters & Numbers Only** - Alphanumeric only - **Line Numbers** - Prefix lines with numbers (start and column width configurable) -- **Louchebem** - French argot (loucherbem-style) -- **Lowercase All** - Lowercase entire text +- **Leading Zeros** - Pad numbers with leading zeros +- **List Deduplicate** - Remove duplicate lines from a list - **Mirror Digits** - Mirror digits 0–9 visually - **Numbers Only** - Digits only -- **Pig Latin** - English Pig Latin -- **QWERTY Right Shift** - Map keys to the key to the right on QWERTY - **Remove Accents** - Strip diacritics / combining marks - **Remove Consonants** - Remove consonant letters - **Remove Duplicates** - Remove duplicate lines @@ -128,35 +139,83 @@ Categories match the Transform tab and the folders under `src/transformers/` (ea - **Reverse Text** - Reverse character order - **Shuffle Characters** - Shuffle characters (random order) - **Shuffle Words** - Shuffle word order +- **Shuffled Letters** - Randomize letter order within each word - **Spaces Remover** - Remove space characters - **Text Justify** - Pad each line to a fixed width (left, right, or center); not word-spacing justify -- **Uppercase All** - Uppercase entire text -- **Toggle Case** - Swap case of each letter -- **Whitespace Steganography** - Hide bits in whitespace patterns +- **Typoglycemia** - Scrambled middle letters (readable chaos) +- **Word Letter Add** - Insert a letter at a fixed position in each word +- **Word Letter Change** - Replace a letter at a fixed position in each word +- **Word Letter Remove** - Remove a letter at a fixed position in each word - **Word Wrap** - Break long lines at spaces so each line fits a maximum width -- **Zero-Width Steganography** - Hide data with zero-width characters + +#### **SignWriting** +- **ASL SignWriting** - American Sign Language fingerspelling (ISWA) +- **LIBRAS SignWriting** - Brazilian Sign Language fingerspelling +- **JSL SignWriting** - Japanese Sign Language (hiragana input) +- **IPA Lip-reading** - IPA symbols in SignWriting +- **Morse Blink** - Morse as SignWriting blink marks +- **Tactile SignWriting** - Tactile SignWriting notation #### **Special** - **Random Mix** - Pick random transforms and chain them #### **Technical** -- **A1Z26** - A=1 … Z=26 letter numbering -- **Braille** - Unicode Braille patterns -- **Brainfuck** - Text ↔ Brainfuck program - **ICAO Spelling Alphabet** - ICAO radiotelephony spelling - **ITU Spelling Alphabet** - ITU phonetic / spelling alphabet +- **DTMF Tones** - Dual-tone multi-frequency telephone codes - **Maritime Signal Flags** - International maritime signal flags - **Morse Code** - International Morse code +- **Navajo Code** - WWII Navajo word code for A–Z - **NATO Phonetic** - NATO phonetic alphabet - **Semaphore Flags** - Flag semaphore arm positions -- **Tap Code** - Polybius / tap / prison code +- **T9 (Predictive Text)** - Phone T9 multi-tap encoding +- **Phone Keypad** - Digits from phone keypad groups + +#### **Symbol** +- **Alchemical Symbols** - Alchemical symbol alphabet +- **Aurebesh (Star Wars)** - Galactic Basic Aurebesh alphabet +- **Babylonian Numerals** - A1Z26 as cuneiform numerals +- **Braille** - Unicode Braille patterns +- **Celestial Alphabet** - Celestial / angelic script +- **Chemical Symbols** - Chemical element symbols +- **Daedric (Elder Scrolls)** - Daedric alphabet +- **Dancing Men (Sherlock Holmes)** - Dancing figure cipher +- **Dominos in Digits** - Digits as domino tile notation +- **Dovahzul (Dragon)** - Skyrim Dovahzul transliteration +- **Egyptian Numerals** - A1Z26 as hieroglyph numerals +- **Elder Futhark** - Germanic Elder Futhark runes +- **Enochian** - Enochian angelic alphabet +- **Eye of Horus (Wedjat)** - Wedjat fraction hieroglyphs +- **Friderici Cipher (Windows)** - 1685 window-pane cipher +- **Greek Letters** - Greek letter replacements +- **Hieroglyphics** - Egyptian hieroglyph-style mapping +- **Hiragana** - Rough Romaji → Hiragana +- **Klingon** - Klingon transliteration +- **Katakana** - Rough Romaji → Katakana +- **Malachim** - Malachim angelic alphabet +- **Mary Stuart Cipher** - Mary Queen of Scots cipher +- **Mayan Numerals** - A1Z26 as Mayan numeral glyphs +- **Moon Alphabet** - Moon type for blind readers +- **Ogham (Celtic)** - Celtic Ogham tree alphabet +- **Passing the River** - Golden Dawn Passing the River script +- **Periodic Table Cipher** - Letters A–Z as element symbols +- **Pigpen Cipher** - Masonic / pigpen grid symbols +- **Quenya (Tolkien Elvish)** - Tolkien Quenya mapping +- **Roman Numerals** - Arabic numerals ↔ Roman numerals +- **Rosicrucian** - Rosicrucian cipher alphabet +- **Seven-Segment Display** - Digits as 7-segment ASCII art +- **Standard Galactic (Minecraft)** - Enchanting Table / SGA alphabet +- **Templars Cipher** - Templar pigpen variant +- **Tengwar Script** - Elvish Tengwar script +- **Theban Alphabet** - Witches' Theban script +- **Wingdings** - Wingdings-style symbol mapping +- **Younger Futhark** - Medieval Younger Futhark runes #### **Unicode** - **Bold Italic** - Mathematical sans-serif bold italic - **Bold** - Mathematical bold -- **Bubble** - Circled / “bubble” letters -- **Chemical Symbols** - Chemical element symbols -- **Circled** - Circled Unicode letters +- **Bubble** - Circled letters (upper and lower case) and circled digits 0–9 +- **Circled** - Circled uppercase letters and digits (no lowercase) - **Cursive** - Mathematical script / cursive - **Cyrillic Stylized** - Latin → Cyrillic lookalike letters - **Dashed Underline** - Combining dashed underline @@ -164,10 +223,7 @@ Categories match the Transform tab and the folders under `src/transformers/` (ea - **Double-Struck** - Mathematical double-struck - **Fraktur** - Mathematical Fraktur / Gothic - **Full Width** - Fullwidth Latin (and related) forms -- **Greek Letters** - Greek letter replacements -- **Hiragana** - Rough Romaji → Hiragana - **Italic** - Mathematical italic -- **Katakana** - Rough Romaji → Katakana - **Mathematical Notation** - Mathematical alphanumeric symbols - **Medieval** - Medieval Unicode letterforms - **Mirror Text** - Left–right mirrored characters @@ -186,12 +242,16 @@ Categories match the Transform tab and the folders under `src/transformers/` (ea - **Vaporwave** - Fullwidth + aesthetic spacing - **Wavy Underline** - Wavy underline combining marks - **Wide Spacing** - Insert wide spaces between characters -- **Wingdings** - Wingdings-style symbol mapping - **Zalgo** - Stacked combining marks (“glitch” text) #### **Visual** - **Disemvowel** - Remove vowels (speech game) - **Emoji Speak** - Emoji-heavy “speak” transform +- **Javanais** - French “javanais” vowel-insertion game +- **Latin Gibberish** - Latin-flavored pseudo-text +- **Leetspeak** - 1337-style character substitutions +- **Louchebem** - French argot (loucherbem-style) +- **Pig Latin** - English Pig Latin - **Rövarspråket** - Swedish consonant-doubling game - **Ubbi Dubbi** - Insert “ub” before vowel sounds @@ -201,7 +261,7 @@ Tabs appear in **UI order** below. **OpenRouter** (optional or required per tool ### 🔤 **Transform** -- **159 Transforms**: Encodings, ciphers, Unicode styles, formats, and more (full catalog above). +- **223 Transforms**: Encodings, ciphers, Unicode styles, formats, and more (full catalog above). - **Categories**: Grouped sections you can **reorder**; quick-jump legend; **randomizer** last. - **Favorites & last used**: Pin transforms and recall recent picks. - **Per-transform options**: Gear icon where a transform exposes settings. @@ -382,7 +442,7 @@ npm run preview # npm run build, then serve dist/ | [build/README.md](build/README.md) | What each `build:*` script does | | [templates/README.md](templates/README.md) | Editing tool HTML templates | -**Keeping the transform list in this README in sync:** when you add or rename a transformer, add a one-line description to `DESCRIPTIONS` in `build/readme-transform-section.js`, run `node build/readme-transform-section.js`, and replace the **Text Transformations** section here (details in [src/transformers/README.md](src/transformers/README.md)). +**Keeping the transform list in this README in sync:** when you add, rename, or move a transformer, update the **Text Transformations** section below manually — one bullet per transform under the correct category heading (`case`, `cipher`, `concealment`, `encoding`, `format`, `signwriting`, `special`, `symbol`, `technical`, `unicode`, `visual`). Use the transform’s UI `name` and a short description. Category comes from the folder under `src/transformers/` (see [src/transformers/README.md](src/transformers/README.md)). ## 🛠️ **Technical Details** @@ -391,7 +451,7 @@ npm run preview # npm run build, then serve dist/ - **Tool System**: Modular tool registry with build-time template injection - **Encoding**: UTF-8 with proper Unicode handling - **Steganography**: Variation selectors and Tags Unicode block -- **Transforms**: Individual transformer modules live under `src/transformers/` (159; the bundle is generated by `npm run build:transforms`) +- **Transforms**: Individual transformer modules live under `src/transformers/` (223; the bundle is generated by `npm run build:transforms`) - **Build Process**: - `npm run build` writes the runnable app under `dist/` (ignored by git in most setups) - Transformers are bundled from `src/transformers/` to `dist/js/bundles/transforms-bundle.js` @@ -421,7 +481,7 @@ npm run preview # npm run build, then serve dist/ - 🆕 **AI Translation**: Translate to 20+ languages (including dead/exotic) via OpenRouter using TranslateGemma prompt format - 🆕 **PromptCraft Tool**: AI-powered prompt mutation with 9 strategies and 48+ models - 🆕 **OpenRouter Integration**: Unified API key management for all AI-powered features -- 🆕 **159 Transformations**: Full catalog of encodings, ciphers, Unicode styles, fantasy and ancient scripts, and technical codes (see README transform list) +- 🆕 **223 Transformations**: Full catalog of encodings, ciphers, Unicode styles, symbol alphabets, SignWriting, and technical codes (see README transform list) - 🆕 **More Encodings/Ciphers**: Base58, Base62, Vigenère, Rail Fence, Roman Numerals - 🆕 **Category Organization**: Better organized transform categories - 🆕 **Enhanced Styling**: New color schemes for each category @@ -432,7 +492,7 @@ npm run preview # npm run build, then serve dist/ ### **Creative Writing** - Create unique text styles for stories - Encode secret messages in plain sight -- Generate fantasy language text +- Generate symbolic or script-style text ### **Education** - Learn about different writing systems @@ -477,6 +537,7 @@ This project is open source. See LICENSE file for details. - **Star Wars** creators for Aurebesh - **Bethesda** for Dovahzul language - **Unicode Consortium** for character standards +- **[RaidedCluster](https://github.com/RaidedCluster)** — SignWriting transforms --- diff --git a/build/README.md b/build/README.md index 197af96..854c107 100644 --- a/build/README.md +++ b/build/README.md @@ -55,8 +55,24 @@ Injects tool templates from `templates/` into `dist/index.html` npm run build:templates ``` +### `build-alphabet-transforms.js` +Regenerates hand-maintained symbol alphabet files from `data/alphabets/*.json` into `src/transformers/symbol/`. + +```bash +npm run build:alphabets +``` + +Runs automatically before `build-transforms.js` (`npm run build:transforms`). + +### `build-code-vendor.js` +Bundles QR and barcode libraries into `js/vendor/` for the Codes tool (no CDN). + +```bash +npm run build:codes-vendor +``` + ### `build-index.js` -Generates transformer index +Generates `src/transformers/index.js` (Node/test import index). ```bash npm run build:index @@ -66,12 +82,13 @@ npm run build:index ```bash npm run build # Runs all scripts in order: -# 1. build:copy - Copy static files to dist/ -# 2. build:index - Generate transformer index -# 3. build:transforms - Bundle transformers to dist/js/bundles/ -# 4. build:emoji - Generate emoji data to dist/js/data/ -# 5. build:tools - Inject tool scripts -# 6. build:templates - Inject templates to dist/index.html +# 1. build:tools - Inject tool scripts into index.template.html + toolRegistry +# 2. build:codes-vendor - Bundle qrcode, JsBarcode, ZXing → js/vendor/ +# 3. build:copy - Copy static files to dist/ +# 4. build:index - Generate src/transformers/index.js +# 5. build:transforms - build:alphabets + bundle transformers → dist/js/bundles/ +# 6. build:emoji - Generate emoji data to dist/js/data/ +# 7. build:templates - Inject templates → dist/index.html ``` ## Output Structure diff --git a/build/build-alphabet-transforms.js b/build/build-alphabet-transforms.js new file mode 100644 index 0000000..dcc1ada --- /dev/null +++ b/build/build-alphabet-transforms.js @@ -0,0 +1,178 @@ +#!/usr/bin/env node +/** + * Generate symbol-alphabet transforms from data/alphabets/*.json + * Output: src/transformers/symbol/.js (regenerated each build) + */ + +const fs = require('fs'); +const path = require('path'); + +const root = path.join(__dirname, '..'); +const dataDir = path.join(root, 'data', 'alphabets'); +const outDir = path.join(root, 'src', 'transformers', 'symbol'); +const GENERATED_HEADER = '// @generated from data/alphabets — do not edit by hand\n'; + +function slugToExportName(slug) { + return slug.replace(/-/g, '_'); +} + +function escapeJsString(s) { + return s.replace(/\\/g, '\\\\').replace(/'/g, "\\'"); +} + +function escapeRegexCharClass(ch) { + return ch.replace(/\\/g, '\\\\').replace(/\]/g, '\\]'); +} + +function buildDetectorBlock(entry) { + if (entry.detectorHint) { + return `, + detector: function(text) { + return new RegExp('${escapeJsString(entry.detectorHint)}', 'u').test(text); + }`; + } + const chars = [...new Set(Object.values(entry.map))]; + if (chars.length === 0) return ''; + const classContent = chars.map(ch => escapeRegexCharClass(ch)).join(''); + return `, + detector: function(text) { + return /[${classContent}]/u.test(text); + }`; +} + +function buildMapObject(map) { + const lines = []; + for (const [key, value] of Object.entries(map)) { + lines.push(` '${escapeJsString(key)}': '${escapeJsString(value)}'`); + } + return lines.join(',\n'); +} + +function generateTransformFile(entry, slug) { + const name = entry.name || slug; + const priority = entry.priority != null ? entry.priority : 100; + const description = entry.description ? `\n description: '${escapeJsString(entry.description)}',` : ''; + const mapBlock = buildMapObject(entry.map); + + return `${GENERATED_HEADER}import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: '${escapeJsString(name)}', + priority: ${priority}, + category: 'symbol',${description} + map: { +${mapBlock} + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[${escapeJsString(slug)}]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }${buildDetectorBlock(entry)} +}); +`; +} + +function validateEntry(entry, file) { + if (!entry.name || !entry.map || typeof entry.map !== 'object') { + throw new Error(`${file}: requires "name" and "map" object`); + } + const keys = Object.keys(entry.map); + if (keys.length < 26) { + console.warn(`⚠️ ${file}: map has only ${keys.length} entries`); + } +} + +function loadUnicodeMaps() { + const unicodeDir = path.join(root, 'src', 'transformers', 'unicode'); + const maps = []; + if (!fs.existsSync(unicodeDir)) return maps; + for (const file of fs.readdirSync(unicodeDir)) { + if (!file.endsWith('.js')) continue; + const content = fs.readFileSync(path.join(unicodeDir, file), 'utf8'); + const nameMatch = content.match(/name:\s*'([^']+)'/); + const map = {}; + for (const match of content.matchAll(/'([^']+)':\s*'([^']+)'/g)) { + map[match[1]] = match[2]; + } + if (Object.keys(map).length >= 20) { + maps.push({ name: nameMatch ? nameMatch[1] : file, map }); + } + } + return maps; +} + +function overlapScore(entryMap, existingMap) { + let matched = 0; + let total = 0; + for (const [key, value] of Object.entries(entryMap)) { + total++; + const variants = [key, key.toLowerCase(), key.toUpperCase()]; + for (const variant of variants) { + if (existingMap[variant] === value) { + matched++; + break; + } + } + } + return { matched, total }; +} + +function checkOverlap(entry, file, unicodeMaps) { + for (const existing of unicodeMaps) { + const { matched, total } = overlapScore(entry.map, existing.map); + if (total >= 20 && matched / total >= 0.9) { + throw new Error( + `${file}: ${matched}/${total} glyphs match existing Unicode transform "${existing.name}" — use that instead or pick distinct symbols` + ); + } + if (total >= 20 && matched / total >= 0.75) { + console.warn(`⚠️ ${file}: ${matched}/${total} glyphs overlap "${existing.name}"`); + } + } +} + +function main() { + if (!fs.existsSync(dataDir)) { + fs.mkdirSync(dataDir, { recursive: true }); + console.log('Created data/alphabets/ (add JSON files to generate symbol transforms)'); + return; + } + + fs.mkdirSync(outDir, { recursive: true }); + + // Remove previously generated symbol transforms + for (const file of fs.readdirSync(outDir)) { + if (!file.endsWith('.js')) continue; + const full = path.join(outDir, file); + const head = fs.readFileSync(full, 'utf8').slice(0, 80); + if (head.includes('@generated')) { + fs.unlinkSync(full); + } + } + + const jsonFiles = fs.readdirSync(dataDir).filter(f => f.endsWith('.json')).sort(); + if (!jsonFiles.length) { + console.log('No alphabet JSON files in data/alphabets/'); + return; + } + + let count = 0; + const unicodeMaps = loadUnicodeMaps(); + for (const file of jsonFiles) { + const slug = file.replace(/\.json$/, ''); + const raw = fs.readFileSync(path.join(dataDir, file), 'utf8'); + const entry = JSON.parse(raw); + validateEntry(entry, file); + checkOverlap(entry, file, unicodeMaps); + const outPath = path.join(outDir, `${slug}.js`); + fs.writeFileSync(outPath, generateTransformFile(entry, slug), 'utf8'); + console.log(`✅ Alphabet: ${slug} → symbol/${slug}.js`); + count++; + } + + console.log(`\n✨ Generated ${count} symbol alphabet transform(s)`); +} + +main(); diff --git a/build/build-code-vendor.js b/build/build-code-vendor.js new file mode 100644 index 0000000..5953bd6 --- /dev/null +++ b/build/build-code-vendor.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node +/** + * Bundle QR/barcode vendor libraries for the Codes tool (local copies, no CDN). + */ + +const fs = require('fs'); +const path = require('path'); +const esbuild = require('esbuild'); + +const projectRoot = path.join(__dirname, '..'); +const vendorDir = path.join(projectRoot, 'js/vendor'); + +if (!fs.existsSync(vendorDir)) { + fs.mkdirSync(vendorDir, { recursive: true }); +} + +const bundles = [ + { + entry: path.join(projectRoot, 'node_modules/qrcode/lib/browser.js'), + outfile: path.join(vendorDir, 'qrcode.min.js'), + globalName: 'QRCode' + }, + { + entry: path.join(projectRoot, 'node_modules/jsbarcode/bin/JsBarcode.js'), + outfile: path.join(vendorDir, 'JsBarcode.min.js'), + globalName: 'JsBarcode' + } +]; + +console.log('📦 Building Codes tool vendor bundles...\n'); + +bundles.forEach(function(spec) { + esbuild.buildSync({ + entryPoints: [spec.entry], + bundle: true, + format: 'iife', + globalName: spec.globalName, + outfile: spec.outfile, + minify: true, + platform: 'browser' + }); + const sizeKb = (fs.statSync(spec.outfile).size / 1024).toFixed(1); + console.log('✅ ' + path.basename(spec.outfile) + ' (' + sizeKb + 'KB)'); +}); + +const zxingSrc = path.join(projectRoot, 'node_modules/@zxing/library/umd/index.min.js'); +const zxingDest = path.join(vendorDir, 'zxing.min.js'); +fs.copyFileSync(zxingSrc, zxingDest); +console.log('✅ zxing.min.js (' + (fs.statSync(zxingDest).size / 1024).toFixed(1) + 'KB)'); +console.log('\n✨ Codes vendor bundles ready\n'); diff --git a/build/build-transforms.js b/build/build-transforms.js index 9fb4bbe..504ccf5 100755 --- a/build/build-transforms.js +++ b/build/build-transforms.js @@ -101,8 +101,15 @@ for (const [name, filePath] of Object.entries(transforms)) { .replace(/export default\s*/g, '') // Remove export statement .trim(); + if (/^(const|let|var|function)\s/m.test(cleanContent)) { + console.error(`❌ ${name}: top-level declarations break the bundle — wrap in export default (function(){ ... return new BaseTransformer(...); })();`); + process.exit(1); + } + output += `// ${name} (from ${filePath})\n`; - if (/^new BaseTransformer\s*\(/.test(cleanContent)) { + if (/^\(function\s*\(\)/.test(cleanContent)) { + output += `transforms['${name}'] = ${cleanContent}\n\n`; + } else if (/^new BaseTransformer\s*\(/.test(cleanContent)) { output += `transforms['${name}'] = ${cleanContent}\n\n`; } else { output += `transforms['${name}'] = ${cleanContent}\n\n`; diff --git a/build/inject-tool-templates.js b/build/inject-tool-templates.js index 94056a3..0412edb 100644 --- a/build/inject-tool-templates.js +++ b/build/inject-tool-templates.js @@ -22,7 +22,8 @@ const templateFiles = [ 'bijection.html', 'splitter.html', 'gibberish.html', - 'spellingalphabet.html' + 'spellingalphabet.html', + 'codes.html' ]; @@ -53,6 +54,7 @@ if (!fs.existsSync(templatePath)) { } let indexContent = fs.readFileSync(templatePath, 'utf8'); +indexContent = indexContent.replace(/\r\n/g, '\n'); // Find the tool-content-container const startMarker = '
'; diff --git a/css/style.css b/css/style.css index 38b8001..d26fdd6 100644 --- a/css/style.css +++ b/css/style.css @@ -1,3 +1,6 @@ +/* SignWriting font (Google Fonts) — ISWA 2010 glyphs (U+1D800–U+1DAFF) */ +@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SignWriting&display=swap'); + .danger-modal-backdrop { display: none; } .danger-modal-backdrop.danger-active { display: none; } .danger-modal { display: none; } @@ -27,44 +30,51 @@ --sidebar-width: 420px; /* Transform category colors */ - --encoding-color: #7e57c2; /* Purple for encoding/decoding */ + /* Transform category colors — one distinct hue per category */ + --case-color: #7986cb; /* Periwinkle — case transforms */ + --case-color-rgb: 121, 134, 203; + --cipher-color: #00897b; /* Teal — classical ciphers */ + --cipher-color-rgb: 0, 137, 123; + --concealment-color: #7cb342; /* Olive — steganography / hidden text */ + --concealment-color-rgb: 124, 179, 66; + --encoding-color: #7e57c2; /* Purple — byte & data encodings */ --encoding-color-rgb: 126, 87, 194; - --cipher-color: #26a69a; /* Teal for ciphers */ - --cipher-color-rgb: 38, 166, 154; - --visual-color: #ef5350; /* Red for visual transformations */ - --visual-color-rgb: 239, 83, 80; - --format-color: #ffb74d; /* Orange for formatting */ - --format-color-rgb: 255, 183, 77; - --unicode-color: #42a5f5; /* Blue for unicode transformations */ + --format-color: #fb8c00; /* Orange — text formatting */ + --format-color-rgb: 251, 140, 0; + --signwriting-color: #8d6e63; /* Brown — SignWriting notation */ + --signwriting-color-rgb: 141, 110, 99; + --special-color: #43a047; /* Green — misc / randomizer-adjacent */ + --special-color-rgb: 67, 160, 71; + --symbol-color: #d4af37; /* Gold — scripts & symbol alphabets */ + --symbol-color-rgb: 212, 175, 55; + --technical-color: #00acc1; /* Cyan — Morse, NATO, phone codes */ + --technical-color-rgb: 0, 172, 193; + --unicode-color: #42a5f5; /* Blue — Unicode letter styles */ --unicode-color-rgb: 66, 165, 245; - --special-color: #66bb6a; /* Green for special transformations */ - --special-color-rgb: 102, 187, 106; - --fantasy-color: #ff6b9d; /* Pink for fantasy languages */ - --fantasy-color-rgb: 255, 107, 157; - --ancient-color: #d4af37; /* Gold for ancient scripts */ - --ancient-color-rgb: 212, 175, 55; - --technical-color: #00bcd4; /* Cyan for technical codes */ - --technical-color-rgb: 0, 188, 212; - --randomizer-color: #9c27b0; /* Purple for randomizer */ - --randomizer-color-rgb: 156, 39, 176; - --case-color: #9575cd; /* Indigo for case transformations */ - --case-color-rgb: 149, 117, 205; - --custom-spelling-color: #ff7043; /* Deep orange for user spelling alphabets */ + --visual-color: #ef5350; /* Coral — visual / spoken effects */ + --visual-color-rgb: 239, 83, 80; + --randomizer-color: #ec407a; /* Pink — random mix */ + --randomizer-color-rgb: 236, 64, 122; + --custom-spelling-color: #ff7043; /* Deep orange — user spelling alphabets */ --custom-spelling-color-rgb: 255, 112, 67; + --translate-color: #b388ff; /* Violet — AI translation (inline tool) */ + --translate-color-rgb: 179, 136, 255; /* Active state gradient end colors */ + --case-active-end: #9fa8da; + --cipher-active-end: #26a69a; + --concealment-active-end: #aed581; --encoding-active-end: #9575cd; - --cipher-active-end: #4db6ac; - --visual-active-end: #e57373; - --format-active-end: #ffcc80; - --unicode-active-end: #64b5f6; - --special-active-end: #81c784; - --fantasy-active-end: #ff8aad; - --ancient-active-end: #e6c84c; + --format-active-end: #ffb74d; + --signwriting-active-end: #a1887f; + --special-active-end: #66bb6a; + --symbol-active-end: #e6c84c; --technical-active-end: #26c6da; - --randomizer-active-end: #ab47bc; - --case-active-end: #b39ddb; + --unicode-active-end: #64b5f6; + --visual-active-end: #e57373; + --randomizer-active-end: #f06292; --custom-spelling-active-end: #ff8a65; + --translate-active-end: #d1b3ff; /* Spacing scale */ --spacing-xs: 4px; @@ -381,13 +391,18 @@ body { min-height: 46px; } +/* Transform picker dropdown (Splitter, Decoder, etc.) */ +select.transform-select { + width: auto; + max-width: min(100%, 320px); + min-width: min(200px, 100%); +} + /* Decoder: method select beside label (override full-width select defaults) */ select.decoder-method-select { margin-left: 15px; padding: 5px 10px; border-radius: 6px; - width: auto; - max-width: min(100%, 320px); } /* Tokenade text payload block label */ @@ -1468,48 +1483,52 @@ body.dark-theme .mobile-tool-dropdown { box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } -.legend-item.transform-category-encoding { - border-left-color: var(--encoding-color); +.legend-item.transform-category-case { + border-left-color: var(--case-color); } .legend-item.transform-category-cipher { border-left-color: var(--cipher-color); } -.legend-item.transform-category-visual { - border-left-color: var(--visual-color); +.legend-item.transform-category-concealment { + border-left-color: var(--concealment-color); +} + +.legend-item.transform-category-encoding { + border-left-color: var(--encoding-color); } .legend-item.transform-category-format { border-left-color: var(--format-color); } -.legend-item.transform-category-unicode { - border-left-color: var(--unicode-color); +.legend-item.transform-category-signwriting { + border-left-color: var(--signwriting-color); } .legend-item.transform-category-special { border-left-color: var(--special-color); } -.legend-item.transform-category-fantasy { - border-left-color: var(--fantasy-color); -} - -.legend-item.transform-category-ancient { - border-left-color: var(--ancient-color); +.legend-item.transform-category-symbol { + border-left-color: var(--symbol-color); } .legend-item.transform-category-technical { border-left-color: var(--technical-color); } -.legend-item.transform-category-randomizer { - border-left-color: var(--randomizer-color); +.legend-item.transform-category-unicode { + border-left-color: var(--unicode-color); } -.legend-item.transform-category-case { - border-left-color: var(--case-color); +.legend-item.transform-category-visual { + border-left-color: var(--visual-color); +} + +.legend-item.transform-category-randomizer { + border-left-color: var(--randomizer-color); } .legend-item.transform-category-custom_spelling { @@ -1638,48 +1657,52 @@ body.dark-theme .mobile-tool-dropdown { position: relative; } -.category-title.transform-category-encoding { - border-left-color: var(--encoding-color); +.category-title.transform-category-case { + border-left-color: var(--case-color); } .category-title.transform-category-cipher { border-left-color: var(--cipher-color); } -.category-title.transform-category-visual { - border-left-color: var(--visual-color); +.category-title.transform-category-concealment { + border-left-color: var(--concealment-color); +} + +.category-title.transform-category-encoding { + border-left-color: var(--encoding-color); } .category-title.transform-category-format { border-left-color: var(--format-color); } -.category-title.transform-category-unicode { - border-left-color: var(--unicode-color); +.category-title.transform-category-signwriting { + border-left-color: var(--signwriting-color); } .category-title.transform-category-special { border-left-color: var(--special-color); } -.category-title.transform-category-fantasy { - border-left-color: var(--fantasy-color); -} - -.category-title.transform-category-ancient { - border-left-color: var(--ancient-color); +.category-title.transform-category-symbol { + border-left-color: var(--symbol-color); } .category-title.transform-category-technical { border-left-color: var(--technical-color); } -.category-title.transform-category-randomizer { - border-left-color: var(--randomizer-color); +.category-title.transform-category-unicode { + border-left-color: var(--unicode-color); } -.category-title.transform-category-case { - border-left-color: var(--case-color); +.category-title.transform-category-visual { + border-left-color: var(--visual-color); +} + +.category-title.transform-category-randomizer { + border-left-color: var(--randomizer-color); } .category-title.transform-category-custom_spelling { @@ -1687,7 +1710,7 @@ body.dark-theme .mobile-tool-dropdown { } .category-title.transform-category-translate { - border-left-color: var(--ancient-color); + border-left-color: var(--translate-color); text-transform: none; margin-bottom: 10px; padding-bottom: 6px; @@ -1785,13 +1808,13 @@ button.translate-custom-label-btn { button.translate-custom-label-btn:hover { opacity: 1; - background: rgba(var(--ancient-color-rgb), 0.08); + background: rgba(var(--translate-color-rgb), 0.08); border-color: var(--input-border); } button.translate-custom-label-btn:focus { outline: none; - box-shadow: 0 0 0 2px rgba(var(--ancient-color-rgb), 0.35); + box-shadow: 0 0 0 2px rgba(var(--translate-color-rgb), 0.35); } .translate-custom-toggle-end { @@ -1809,8 +1832,8 @@ button.translate-custom-label-btn:focus { button.translate-custom-label-btn:hover .translate-custom-toggle-end { background: var(--button-hover-bg); - border-color: var(--ancient-color); - color: var(--ancient-color); + border-color: var(--translate-color); + color: var(--translate-color); } .translate-lang-grid { @@ -1838,12 +1861,12 @@ button.translate-custom-label-btn:hover .translate-custom-toggle-end { cursor: pointer; transition: all 0.2s ease; box-sizing: border-box; - background: linear-gradient(to right, rgba(var(--ancient-color-rgb), 0.06), var(--button-bg)); + background: linear-gradient(to right, rgba(var(--translate-color-rgb), 0.06), var(--button-bg)); } .translate-lang-btn:hover:not(:disabled) { - background: linear-gradient(to right, rgba(var(--ancient-color-rgb), 0.14), var(--button-hover-bg)); - box-shadow: 0 2px 8px rgba(var(--ancient-color-rgb), 0.18); + background: linear-gradient(to right, rgba(var(--translate-color-rgb), 0.14), var(--button-hover-bg)); + box-shadow: 0 2px 8px rgba(var(--translate-color-rgb), 0.18); } .translate-lang-btn:disabled { @@ -1852,7 +1875,7 @@ button.translate-custom-label-btn:hover .translate-custom-toggle-end { } .translate-lang-exotic { - background: linear-gradient(to right, rgba(var(--ancient-color-rgb), 0.09), var(--button-bg)); + background: linear-gradient(to right, rgba(var(--translate-color-rgb), 0.09), var(--button-bg)); } .translate-lang-custom { @@ -1867,7 +1890,7 @@ button.translate-custom-label-btn:hover .translate-custom-toggle-end { } .translate-custom-flag { - color: var(--ancient-color); + color: var(--translate-color); font-size: 1.1rem; } @@ -1928,7 +1951,7 @@ button.translate-custom-label-btn:hover .translate-custom-toggle-end { .translate-add-btn:hover:not(:disabled) { background: var(--button-hover-bg); - border-color: var(--ancient-color); + border-color: var(--translate-color); } .translate-empty-custom { @@ -2571,55 +2594,72 @@ button.endsequence-item:hover .endsequence-copy-affordance { transition: all 0.2s ease; } -.transform-category-encoding .transform-preview { - color: rgba(var(--encoding-color-rgb), 0.9); +.transform-category-case .transform-preview { + color: rgba(var(--case-color-rgb), 0.9); } .transform-category-cipher .transform-preview { color: rgba(var(--cipher-color-rgb), 0.9); } -.transform-category-visual .transform-preview { - color: rgba(var(--visual-color-rgb), 0.9); +.transform-category-concealment .transform-preview { + color: rgba(var(--concealment-color-rgb), 0.9); +} + +.transform-category-encoding .transform-preview { + color: rgba(var(--encoding-color-rgb), 0.9); } .transform-category-format .transform-preview { color: rgba(var(--format-color-rgb), 0.9); } -.transform-category-unicode .transform-preview { - color: rgba(var(--unicode-color-rgb), 0.9); +.transform-category-signwriting .transform-preview { + color: rgba(var(--signwriting-color-rgb), 0.9); + font-family: 'Noto Sans SignWriting', 'Fira Code', monospace; + line-height: 2; + letter-spacing: 0.05em; } .transform-category-special .transform-preview { color: rgba(var(--special-color-rgb), 0.9); } -.transform-category-fantasy .transform-preview { - color: rgba(var(--fantasy-color-rgb), 0.9); -} - -.transform-category-ancient .transform-preview { - color: rgba(var(--ancient-color-rgb), 0.9); +.transform-category-symbol .transform-preview { + color: rgba(var(--symbol-color-rgb), 0.9); } .transform-category-technical .transform-preview { color: rgba(var(--technical-color-rgb), 0.9); } -.transform-category-randomizer .transform-preview { - color: #e1baff; - text-shadow: 0 0 8px rgba(225,186,255,.35); +.transform-category-unicode .transform-preview { + color: rgba(var(--unicode-color-rgb), 0.9); } -.transform-category-case .transform-preview { - color: rgba(var(--case-color-rgb), 0.9); +.transform-category-visual .transform-preview { + color: rgba(var(--visual-color-rgb), 0.9); +} + +.transform-category-randomizer .transform-preview { + color: rgba(var(--randomizer-color-rgb), 0.95); + text-shadow: 0 0 8px rgba(var(--randomizer-color-rgb), 0.35); } .transform-category-custom_spelling .transform-preview { color: rgba(var(--custom-spelling-color-rgb), 0.9); } +.transform-category-translate .transform-preview { + color: rgba(var(--translate-color-rgb), 0.9); +} + +.output-container.signwriting-output textarea { + font-family: 'Noto Sans SignWriting', 'Fira Code', 'Courier New', monospace; + line-height: 2; + letter-spacing: 0.1em; +} + .transform-button:hover .transform-preview { background-color: rgba(0, 0, 0, 0.18); opacity: 1; @@ -2656,13 +2696,13 @@ button.endsequence-item:hover .endsequence-copy-affordance { transition: all 0.2s ease; } -.transform-category-encoding { - background: linear-gradient(to right, rgba(var(--encoding-color-rgb), 0.05), var(--button-bg)); +.transform-category-case { + background: linear-gradient(to right, rgba(var(--case-color-rgb), 0.05), var(--button-bg)); } -.transform-category-encoding:hover { - background: linear-gradient(to right, rgba(var(--encoding-color-rgb), 0.15), var(--button-hover-bg)); - box-shadow: 0 3px 10px rgba(var(--encoding-color-rgb), 0.2); +.transform-category-case:hover { + background: linear-gradient(to right, rgba(var(--case-color-rgb), 0.15), var(--button-hover-bg)); + box-shadow: 0 3px 10px rgba(var(--case-color-rgb), 0.2); } .transform-category-cipher { @@ -2674,13 +2714,22 @@ button.endsequence-item:hover .endsequence-copy-affordance { box-shadow: 0 3px 10px rgba(var(--cipher-color-rgb), 0.2); } -.transform-category-visual { - background: linear-gradient(to right, rgba(var(--visual-color-rgb), 0.05), var(--button-bg)); +.transform-category-concealment { + background: linear-gradient(to right, rgba(var(--concealment-color-rgb), 0.05), var(--button-bg)); } -.transform-category-visual:hover { - background: linear-gradient(to right, rgba(var(--visual-color-rgb), 0.15), var(--button-hover-bg)); - box-shadow: 0 3px 10px rgba(var(--visual-color-rgb), 0.2); +.transform-category-concealment:hover { + background: linear-gradient(to right, rgba(var(--concealment-color-rgb), 0.15), var(--button-hover-bg)); + box-shadow: 0 3px 10px rgba(var(--concealment-color-rgb), 0.2); +} + +.transform-category-encoding { + background: linear-gradient(to right, rgba(var(--encoding-color-rgb), 0.05), var(--button-bg)); +} + +.transform-category-encoding:hover { + background: linear-gradient(to right, rgba(var(--encoding-color-rgb), 0.15), var(--button-hover-bg)); + box-shadow: 0 3px 10px rgba(var(--encoding-color-rgb), 0.2); } .transform-category-format { @@ -2692,13 +2741,13 @@ button.endsequence-item:hover .endsequence-copy-affordance { box-shadow: 0 3px 10px rgba(var(--format-color-rgb), 0.2); } -.transform-category-unicode { - background: linear-gradient(to right, rgba(var(--unicode-color-rgb), 0.05), var(--button-bg)); +.transform-category-signwriting { + background: linear-gradient(to right, rgba(var(--signwriting-color-rgb), 0.05), var(--button-bg)); } -.transform-category-unicode:hover { - background: linear-gradient(to right, rgba(var(--unicode-color-rgb), 0.15), var(--button-hover-bg)); - box-shadow: 0 3px 10px rgba(var(--unicode-color-rgb), 0.2); +.transform-category-signwriting:hover { + background: linear-gradient(to right, rgba(var(--signwriting-color-rgb), 0.15), var(--button-hover-bg)); + box-shadow: 0 3px 10px rgba(var(--signwriting-color-rgb), 0.2); } .transform-category-special { @@ -2710,22 +2759,13 @@ button.endsequence-item:hover .endsequence-copy-affordance { box-shadow: 0 3px 10px rgba(var(--special-color-rgb), 0.2); } -.transform-category-fantasy { - background: linear-gradient(to right, rgba(var(--fantasy-color-rgb), 0.05), var(--button-bg)); +.transform-category-symbol { + background: linear-gradient(to right, rgba(var(--symbol-color-rgb), 0.05), var(--button-bg)); } -.transform-category-fantasy:hover { - background: linear-gradient(to right, rgba(var(--fantasy-color-rgb), 0.15), var(--button-hover-bg)); - box-shadow: 0 3px 10px rgba(var(--fantasy-color-rgb), 0.2); -} - -.transform-category-ancient { - background: linear-gradient(to right, rgba(var(--ancient-color-rgb), 0.05), var(--button-bg)); -} - -.transform-category-ancient:hover { - background: linear-gradient(to right, rgba(var(--ancient-color-rgb), 0.15), var(--button-hover-bg)); - box-shadow: 0 3px 10px rgba(var(--ancient-color-rgb), 0.2); +.transform-category-symbol:hover { + background: linear-gradient(to right, rgba(var(--symbol-color-rgb), 0.15), var(--button-hover-bg)); + box-shadow: 0 3px 10px rgba(var(--symbol-color-rgb), 0.2); } .transform-category-technical { @@ -2737,6 +2777,24 @@ button.endsequence-item:hover .endsequence-copy-affordance { box-shadow: 0 3px 10px rgba(var(--technical-color-rgb), 0.2); } +.transform-category-unicode { + background: linear-gradient(to right, rgba(var(--unicode-color-rgb), 0.05), var(--button-bg)); +} + +.transform-category-unicode:hover { + background: linear-gradient(to right, rgba(var(--unicode-color-rgb), 0.15), var(--button-hover-bg)); + box-shadow: 0 3px 10px rgba(var(--unicode-color-rgb), 0.2); +} + +.transform-category-visual { + background: linear-gradient(to right, rgba(var(--visual-color-rgb), 0.05), var(--button-bg)); +} + +.transform-category-visual:hover { + background: linear-gradient(to right, rgba(var(--visual-color-rgb), 0.15), var(--button-hover-bg)); + box-shadow: 0 3px 10px rgba(var(--visual-color-rgb), 0.2); +} + .transform-category-randomizer { background: linear-gradient(to right, rgba(var(--randomizer-color-rgb), 0.05), var(--button-bg)); } @@ -2746,15 +2804,6 @@ button.endsequence-item:hover .endsequence-copy-affordance { box-shadow: 0 3px 10px rgba(var(--randomizer-color-rgb), 0.2); } -.transform-category-case { - background: linear-gradient(to right, rgba(var(--case-color-rgb), 0.05), var(--button-bg)); -} - -.transform-category-case:hover { - background: linear-gradient(to right, rgba(var(--case-color-rgb), 0.15), var(--button-hover-bg)); - box-shadow: 0 3px 10px rgba(var(--case-color-rgb), 0.2); -} - .transform-category-custom_spelling { background: linear-gradient(to right, rgba(var(--custom-spelling-color-rgb), 0.05), var(--button-bg)); } @@ -2764,6 +2813,15 @@ button.endsequence-item:hover .endsequence-copy-affordance { box-shadow: 0 3px 10px rgba(var(--custom-spelling-color-rgb), 0.2); } +.transform-category-translate { + background: linear-gradient(to right, rgba(var(--translate-color-rgb), 0.05), var(--button-bg)); +} + +.transform-category-translate:hover { + background: linear-gradient(to right, rgba(var(--translate-color-rgb), 0.15), var(--button-hover-bg)); + box-shadow: 0 3px 10px rgba(var(--translate-color-rgb), 0.2); +} + .transform-button:before { content: ''; position: absolute; @@ -2803,9 +2861,9 @@ button.endsequence-item:hover .endsequence-copy-affordance { } /* Category-specific active states */ -.transform-category-encoding.active { - background: linear-gradient(to right, var(--encoding-color), var(--encoding-active-end)); - box-shadow: 0 3px 12px rgba(var(--encoding-color-rgb), 0.4); +.transform-category-case.active { + background: linear-gradient(to right, var(--case-color), var(--case-active-end)); + box-shadow: 0 3px 12px rgba(var(--case-color-rgb), 0.4); } .transform-category-cipher.active { @@ -2813,9 +2871,14 @@ button.endsequence-item:hover .endsequence-copy-affordance { box-shadow: 0 3px 12px rgba(var(--cipher-color-rgb), 0.4); } -.transform-category-visual.active { - background: linear-gradient(to right, var(--visual-color), var(--visual-active-end)); - box-shadow: 0 3px 12px rgba(var(--visual-color-rgb), 0.4); +.transform-category-concealment.active { + background: linear-gradient(to right, var(--concealment-color), var(--concealment-active-end)); + box-shadow: 0 3px 12px rgba(var(--concealment-color-rgb), 0.4); +} + +.transform-category-encoding.active { + background: linear-gradient(to right, var(--encoding-color), var(--encoding-active-end)); + box-shadow: 0 3px 12px rgba(var(--encoding-color-rgb), 0.4); } .transform-category-format.active { @@ -2823,9 +2886,9 @@ button.endsequence-item:hover .endsequence-copy-affordance { box-shadow: 0 3px 12px rgba(var(--format-color-rgb), 0.4); } -.transform-category-unicode.active { - background: linear-gradient(to right, var(--unicode-color), var(--unicode-active-end)); - box-shadow: 0 3px 12px rgba(var(--unicode-color-rgb), 0.4); +.transform-category-signwriting.active { + background: linear-gradient(to right, var(--signwriting-color), var(--signwriting-active-end)); + box-shadow: 0 3px 12px rgba(var(--signwriting-color-rgb), 0.4); } .transform-category-special.active { @@ -2833,14 +2896,9 @@ button.endsequence-item:hover .endsequence-copy-affordance { box-shadow: 0 3px 12px rgba(var(--special-color-rgb), 0.4); } -.transform-category-fantasy.active { - background: linear-gradient(to right, var(--fantasy-color), var(--fantasy-active-end)); - box-shadow: 0 3px 12px rgba(var(--fantasy-color-rgb), 0.4); -} - -.transform-category-ancient.active { - background: linear-gradient(to right, var(--ancient-color), var(--ancient-active-end)); - box-shadow: 0 3px 12px rgba(var(--ancient-color-rgb), 0.4); +.transform-category-symbol.active { + background: linear-gradient(to right, var(--symbol-color), var(--symbol-active-end)); + box-shadow: 0 3px 12px rgba(var(--symbol-color-rgb), 0.4); } .transform-category-technical.active { @@ -2848,16 +2906,26 @@ button.endsequence-item:hover .endsequence-copy-affordance { box-shadow: 0 3px 12px rgba(var(--technical-color-rgb), 0.4); } +.transform-category-translate.active { + background: linear-gradient(to right, var(--translate-color), var(--translate-active-end)); + box-shadow: 0 3px 12px rgba(var(--translate-color-rgb), 0.4); +} + +.transform-category-unicode.active { + background: linear-gradient(to right, var(--unicode-color), var(--unicode-active-end)); + box-shadow: 0 3px 12px rgba(var(--unicode-color-rgb), 0.4); +} + +.transform-category-visual.active { + background: linear-gradient(to right, var(--visual-color), var(--visual-active-end)); + box-shadow: 0 3px 12px rgba(var(--visual-color-rgb), 0.4); +} + .transform-category-randomizer.active { background: linear-gradient(to right, var(--randomizer-color), var(--randomizer-active-end)); box-shadow: 0 3px 12px rgba(var(--randomizer-color-rgb), 0.4); } -.transform-category-case.active { - background: linear-gradient(to right, var(--case-color), var(--case-active-end)); - box-shadow: 0 3px 12px rgba(var(--case-color-rgb), 0.4); -} - .transform-category-custom_spelling.active { background: linear-gradient(to right, var(--custom-spelling-color), var(--custom-spelling-active-end)); box-shadow: 0 3px 12px rgba(var(--custom-spelling-color-rgb), 0.4); @@ -4768,9 +4836,9 @@ html { position: relative; } -/* Transform chain select - only unique override for larger screens */ -.transform-chain-item select { - min-width: min(200px, 100%); /* Never exceed container width */ +/* Transform chain select inherits .transform-select sizing */ +.transform-chain-item .transform-select { + min-width: min(200px, 100%); } @@ -4952,7 +5020,7 @@ html { text-align: left; } - .transform-chain-item select { + .transform-chain-item .transform-select { min-width: 100%; /* Full width on smaller screens */ } @@ -5275,7 +5343,7 @@ html { } /* Transform chain items stack vertically */ - .transform-chain-item select { + .transform-chain-item .transform-select { min-width: 100%; width: 100%; } @@ -5408,3 +5476,146 @@ html { background: rgba(var(--custom-spelling-color-rgb), 0.08); border: 1px solid rgba(var(--custom-spelling-color-rgb), 0.25); } + +/* Codes tool (QR + barcodes) */ +.codes-layout .codes-mode-tabs { + display: flex; + gap: var(--spacing-sm); + margin-bottom: var(--spacing-md); +} + +.codes-mode-btn { + flex: 1; + max-width: 220px; + padding: 10px 16px; + border: 1px solid var(--border-color); + border-radius: 8px; + background: var(--bg-secondary); + color: var(--text-color); + cursor: pointer; + font-size: 0.95rem; + transition: border-color 0.15s, background 0.15s; +} + +.codes-mode-btn:hover { + border-color: var(--accent-color); +} + +.codes-mode-btn.active { + border-color: var(--accent-color); + background: rgba(var(--accent-color-rgb, 99, 102, 241), 0.12); + font-weight: 600; +} + +.codes-options-grid { + margin-bottom: var(--spacing-md); +} + +.codes-checkbox-label { + display: flex; + align-items: center; + gap: 8px; + align-self: end; +} + +.codes-error { + margin: var(--spacing-sm) 0; + padding: var(--spacing-sm) var(--spacing-md); + border-radius: 8px; + background: rgba(220, 53, 69, 0.12); + border: 1px solid rgba(220, 53, 69, 0.35); + color: #dc3545; +} + +.codes-output-card { + margin-top: var(--spacing-md); + padding: var(--spacing-md); + border: 1px solid var(--border-color); + border-radius: 12px; + background: var(--bg-secondary); +} + +.codes-preview-wrap { + display: flex; + justify-content: center; + align-items: center; + padding: var(--spacing-md); + background: #fff; + border-radius: 8px; + margin-bottom: var(--spacing-md); +} + +.codes-preview-image { + max-width: 100%; + height: auto; +} + +.codes-upload-zone { + margin-bottom: var(--spacing-md); +} + +.codes-upload-label { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); + padding: var(--spacing-lg); + border: 2px dashed var(--border-color); + border-radius: 12px; + cursor: pointer; + text-align: center; + transition: border-color 0.15s, background 0.15s; +} + +.codes-upload-label:hover { + border-color: var(--accent-color); + background: rgba(var(--accent-color-rgb, 99, 102, 241), 0.06); +} + +.codes-upload-label input[type="file"] { + display: none; +} + +.codes-upload-label i { + font-size: 2rem; + color: var(--accent-color); +} + +.codes-hint { + margin-top: var(--spacing-sm); + color: var(--text-muted); + font-size: 0.9rem; +} + +.codes-loading { + padding: var(--spacing-md); + color: var(--text-muted); +} + +.codes-decode-preview { + margin: var(--spacing-md) 0; + text-align: center; +} + +.codes-decode-preview img { + max-width: 100%; + max-height: 280px; + border-radius: 8px; + border: 1px solid var(--border-color); +} + +.codes-decode-result { + margin-top: var(--spacing-md); + padding: var(--spacing-md); + border: 1px solid var(--border-color); + border-radius: 12px; + background: var(--bg-secondary); +} + +.codes-decode-meta { + margin-bottom: var(--spacing-sm); + color: var(--text-muted); + font-size: 0.9rem; +} + diff --git a/data/alphabets/alchemical.json b/data/alphabets/alchemical.json new file mode 100644 index 0000000..2914262 --- /dev/null +++ b/data/alphabets/alchemical.json @@ -0,0 +1,13 @@ +{ + "name": "Alchemical Symbols", + "priority": 100, + "description": "Classical alchemical symbol alphabet", + "detectorHint": "[🜂🜃🜄🜅🜆🜇🜈🜉]", + "map": { + "A": "🜂", "B": "🜃", "C": "🜄", "D": "🜅", "E": "🜆", "F": "🜇", + "G": "🜈", "H": "🜉", "I": "🜊", "J": "🜋", "K": "🜌", "L": "🜍", + "M": "🜎", "N": "🜏", "O": "🜐", "P": "🜑", "Q": "🜒", "R": "🜓", + "S": "🜔", "T": "🜕", "U": "🜖", "V": "🜗", "W": "🜘", "X": "🜙", + "Y": "🜚", "Z": "🜛" + } +} diff --git a/data/alphabets/celestial.json b/data/alphabets/celestial.json new file mode 100644 index 0000000..9c7d3a1 --- /dev/null +++ b/data/alphabets/celestial.json @@ -0,0 +1,13 @@ +{ + "name": "Celestial Alphabet", + "priority": 100, + "description": "Agrippa's celestial / angelic symbol alphabet", + "detectorHint": "[☉☽☿♀♂♃♄♅♆♇☊☋]", + "map": { + "A": "☉", "B": "☽", "C": "☿", "D": "♀", "E": "♂", "F": "♃", + "G": "♄", "H": "♅", "I": "♆", "J": "♇", "K": "☊", "L": "☋", + "M": "⚳", "N": "⚴", "O": "⚵", "P": "⚶", "Q": "⚷", "R": "⚸", + "S": "⚹", "T": "⚺", "U": "⚻", "V": "⚼", "W": "⚽", "X": "⚾", + "Y": "⛢", "Z": "⛣" + } +} diff --git a/data/alphabets/daedric.json b/data/alphabets/daedric.json new file mode 100644 index 0000000..d64bbd0 --- /dev/null +++ b/data/alphabets/daedric.json @@ -0,0 +1,13 @@ +{ + "name": "Daedric Alphabet", + "priority": 100, + "description": "Elder Scrolls inspired Daedric-style symbols", + "detectorHint": "[ᚠᚡᚢᚣᚤᚥᚦᚧᚨᚩ]", + "map": { + "A": "ᚠ", "B": "ᚡ", "C": "ᚢ", "D": "ᚣ", "E": "ᚤ", "F": "ᚥ", + "G": "ᚦ", "H": "ᚧ", "I": "ᚨ", "J": "ᚩ", "K": "ᚪ", "L": "ᚫ", + "M": "ᚬ", "N": "ᚭ", "O": "ᚮ", "P": "ᚯ", "Q": "ᚰ", "R": "ᚱ", + "S": "ᚲ", "T": "ᚳ", "U": "ᚴ", "V": "ᚵ", "W": "ᚶ", "X": "ᚷ", + "Y": "ᚸ", "Z": "ᚹ" + } +} diff --git a/data/alphabets/dancing-men.json b/data/alphabets/dancing-men.json new file mode 100644 index 0000000..e89e79b --- /dev/null +++ b/data/alphabets/dancing-men.json @@ -0,0 +1,13 @@ +{ + "name": "Dancing Men Cipher", + "priority": 100, + "description": "Sherlock Holmes stick-figure cipher (Unicode approximations)", + "detectorHint": "[┣┫┳┻├┤┬┴╋╞╡╤╧]", + "map": { + "A": "┣", "B": "┫", "C": "┳", "D": "┻", "E": "├", "F": "┤", + "G": "┬", "H": "┴", "I": "╋", "J": "╞", "K": "╡", "L": "╤", + "M": "╧", "N": "╥", "O": "╨", "P": "╪", "Q": "╫", "R": "╬", + "S": "╭", "T": "╮", "U": "╯", "V": "╰", "W": "▸", "X": "◂", + "Y": "▴", "Z": "▾" + } +} diff --git a/data/alphabets/enochian.json b/data/alphabets/enochian.json new file mode 100644 index 0000000..d2f6625 --- /dev/null +++ b/data/alphabets/enochian.json @@ -0,0 +1,13 @@ +{ + "name": "Enochian Alphabet", + "priority": 100, + "description": "Enochian angelic script (Unicode approximations)", + "detectorHint": "[ᛂᛃᛄᛅᛆᛇᛈᛉᛊᛋ]", + "map": { + "A": "ᛂ", "B": "ᛃ", "C": "ᛄ", "D": "ᛅ", "E": "ᛆ", "F": "ᛇ", + "G": "ᛈ", "H": "ᛉ", "I": "ᛊ", "J": "ᛋ", "K": "ᛌ", "L": "ᛍ", + "M": "ᛎ", "N": "ᛏ", "O": "ᛐ", "P": "ᛑ", "Q": "ᛒ", "R": "ᛓ", + "S": "ᛔ", "T": "ᛕ", "U": "ᛖ", "V": "ᛗ", "W": "ᛘ", "X": "ᛙ", + "Y": "ᛚ", "Z": "ᛛ" + } +} diff --git a/data/alphabets/malachim.json b/data/alphabets/malachim.json new file mode 100644 index 0000000..fa2e19e --- /dev/null +++ b/data/alphabets/malachim.json @@ -0,0 +1,13 @@ +{ + "name": "Malachim Alphabet", + "priority": 100, + "description": "Malachim / angel script symbol substitution", + "detectorHint": "[✁✂✃✄✆✇✈✉✊✋✌✍✎✏]", + "map": { + "A": "✁", "B": "✂", "C": "✃", "D": "✄", "E": "✆", "F": "✇", + "G": "✈", "H": "✉", "I": "✊", "J": "✋", "K": "✌", "L": "✍", + "M": "✎", "N": "✏", "O": "✐", "P": "✑", "Q": "✒", "R": "✓", + "S": "✔", "T": "✕", "U": "✖", "V": "✗", "W": "✘", "X": "✙", + "Y": "✚", "Z": "✛" + } +} diff --git a/data/alphabets/mary-stuart.json b/data/alphabets/mary-stuart.json new file mode 100644 index 0000000..e24a618 --- /dev/null +++ b/data/alphabets/mary-stuart.json @@ -0,0 +1,13 @@ +{ + "name": "Mary Stuart Cipher", + "priority": 100, + "description": "Mary Queen of Scots nomenclator-style symbols", + "detectorHint": "[❶❷❸❹❺❻❼❽❾]", + "map": { + "A": "❶", "B": "❷", "C": "❸", "D": "❹", "E": "❺", "F": "❻", + "G": "❼", "H": "❽", "I": "❾", "J": "❿", "K": "➀", "L": "➁", + "M": "➂", "N": "➃", "O": "➄", "P": "➅", "Q": "➆", "R": "➇", + "S": "➈", "T": "➉", "U": "➊", "V": "➋", "W": "➌", "X": "➍", + "Y": "➎", "Z": "➏" + } +} diff --git a/data/alphabets/moon-alphabet.json b/data/alphabets/moon-alphabet.json new file mode 100644 index 0000000..aabb69d --- /dev/null +++ b/data/alphabets/moon-alphabet.json @@ -0,0 +1,13 @@ +{ + "name": "Moon Alphabet", + "priority": 100, + "description": "Moon phase / lunar symbol alphabet", + "detectorHint": "[☾☽☊☋⚸⚹⚺⚻]", + "map": { + "A": "☾", "B": "☽", "C": "☊", "D": "☋", "E": "⚸", "F": "⚹", + "G": "⚺", "H": "⚻", "I": "⚼", "J": "⚽", "K": "⚾", "L": "⛢", + "M": "⛣", "N": "⛤", "O": "⛥", "P": "⛦", "Q": "⛧", "R": "⛨", + "S": "⛩", "T": "⛪", "U": "⛫", "V": "⛬", "W": "⛭", "X": "⛮", + "Y": "⛯", "Z": "⛰" + } +} diff --git a/data/alphabets/passing-the-river.json b/data/alphabets/passing-the-river.json new file mode 100644 index 0000000..bc5fb25 --- /dev/null +++ b/data/alphabets/passing-the-river.json @@ -0,0 +1,13 @@ +{ + "name": "Passing the River Alphabet", + "priority": 100, + "description": "Golden Dawn Passing the River tarot script", + "detectorHint": "[♠♣♥♦♤♧♡♢]", + "map": { + "A": "♠", "B": "♣", "C": "♥", "D": "♦", "E": "♤", "F": "♧", + "G": "♡", "H": "♢", "I": "♩", "J": "♪", "K": "♫", "L": "♬", + "M": "♭", "N": "♮", "O": "♯", "P": "°", "Q": "±", "R": "×", + "S": "÷", "T": "∓", "U": "∔", "V": "∕", "W": "∖", "X": "∗", + "Y": "∘", "Z": "∙" + } +} diff --git a/data/alphabets/rosicrucian.json b/data/alphabets/rosicrucian.json new file mode 100644 index 0000000..a6692b6 --- /dev/null +++ b/data/alphabets/rosicrucian.json @@ -0,0 +1,13 @@ +{ + "name": "Rosicrucian Cipher", + "priority": 100, + "description": "Rosicrucian / Golden Dawn symbol alphabet", + "detectorHint": "[⛤⛥⛦⛧⛨⛩⛪⛫]", + "map": { + "A": "⛤", "B": "⛥", "C": "⛦", "D": "⛧", "E": "⛨", "F": "⛩", + "G": "⛪", "H": "⛫", "I": "⛬", "J": "⛭", "K": "⛮", "L": "⛯", + "M": "⛰", "N": "⛱", "O": "⛲", "P": "⛳", "Q": "⛴", "R": "⛵", + "S": "⛶", "T": "⛷", "U": "⛸", "V": "⛹", "W": "⛺", "X": "⛻", + "Y": "⛼", "Z": "⛽" + } +} diff --git a/data/alphabets/templars.json b/data/alphabets/templars.json new file mode 100644 index 0000000..ff22589 --- /dev/null +++ b/data/alphabets/templars.json @@ -0,0 +1,13 @@ +{ + "name": "Templars Cipher", + "priority": 100, + "description": "Templar / pigpen variant with dot markers", + "detectorHint": "[◧◨◩◪◫◬◭◮◯]", + "map": { + "A": "◧", "B": "◨", "C": "◩", "D": "◪", "E": "◫", "F": "◬", + "G": "◭", "H": "◮", "I": "◯", "J": "◰", "K": "◱", "L": "◲", + "M": "◳", "N": "◴", "O": "◵", "P": "◶", "Q": "◷", "R": "◸", + "S": "◹", "T": "◺", "U": "◻", "V": "◼", "W": "◽", "X": "◾", + "Y": "◿", "Z": "⬒" + } +} diff --git a/data/alphabets/theban.json b/data/alphabets/theban.json new file mode 100644 index 0000000..674c792 --- /dev/null +++ b/data/alphabets/theban.json @@ -0,0 +1,13 @@ +{ + "name": "Theban Alphabet", + "priority": 100, + "description": "Honoric / Theban witch alphabet (symbol substitution)", + "detectorHint": "[∀∁∂∃∄∅∆∇∈∉∊∋∌∍∎∏∐∑−∓∔∕∖∗∘∙√∛∜∝]", + "map": { + "A": "∀", "B": "∁", "C": "∂", "D": "∃", "E": "∄", "F": "∅", + "G": "∆", "H": "∇", "I": "∈", "J": "∉", "K": "∊", "L": "∋", + "M": "∌", "N": "∍", "O": "∎", "P": "∏", "Q": "∐", "R": "∑", + "S": "−", "T": "∓", "U": "∔", "V": "∕", "W": "∖", "X": "∗", + "Y": "∘", "Z": "∙" + } +} diff --git a/index.template.html b/index.template.html index ae65b4b..1992695 100644 --- a/index.template.html +++ b/index.template.html @@ -430,11 +430,13 @@ + + @@ -447,6 +449,11 @@ + + + + + diff --git a/js/core/toolRegistry.js b/js/core/toolRegistry.js index 901fa71..765ae42 100644 --- a/js/core/toolRegistry.js +++ b/js/core/toolRegistry.js @@ -181,6 +181,9 @@ if (typeof AntiClassifierTool !== 'undefined') { if (typeof BijectionTool !== 'undefined') { window.toolRegistry.register(new BijectionTool()); } +if (typeof CodesTool !== 'undefined') { + window.toolRegistry.register(new CodesTool()); +} if (typeof DecodeTool !== 'undefined') { window.toolRegistry.register(new DecodeTool()); } diff --git a/js/core/transformSelect.js b/js/core/transformSelect.js new file mode 100644 index 0000000..ff26542 --- /dev/null +++ b/js/core/transformSelect.js @@ -0,0 +1,123 @@ +/** + * Shared transform picker dropdown (category optgroups + favorites). + * Used by Splitter, Universal Decoder, and any tool that picks a transform. + */ +(function(global) { + 'use strict'; + + function transformSelectFilter(root, decodableOnly) { + const list = (root && root.transforms) ? root.transforms : []; + if (!decodableOnly) return list; + return list.filter(function(t) { + return t && typeof t.reverse === 'function' && t.name !== 'Random Mix'; + }); + } + + function transformSelectFavorites(root, decodableOnly) { + const favorites = (root && root.favorites) ? root.favorites : []; + const pool = transformSelectFilter(root, decodableOnly); + return favorites + .filter(function(f) { return typeof f === 'string'; }) + .map(function(name) { return pool.find(function(t) { return t.name === name; }); }) + .filter(Boolean); + } + + function transformSelectByCategory(root, category, decodableOnly) { + const pool = transformSelectFilter(root, decodableOnly); + const list = pool.filter(function(t) { return t.category === category; }); + const favorites = (root && root.favorites) ? root.favorites : []; + if (!favorites.length) return list; + return list.filter(function(t) { + return !favorites.some(function(f) { return typeof f === 'string' && f === t.name; }); + }); + } + + function transformSelectCategoryOrder(root) { + if (root && Array.isArray(root.categories) && root.categories.length) { + return root.categories; + } + const pool = transformSelectFilter(root, false); + const set = new Set(); + pool.forEach(function(t) { + if (t.category) set.add(t.category); + }); + const cats = Array.from(set).filter(function(c) { return c !== 'randomizer'; }).sort(); + if (set.has('randomizer')) cats.push('randomizer'); + return cats; + } + + function transformSelectCategoryLabel(category) { + if (!category) return ''; + return category.charAt(0).toUpperCase() + category.slice(1); + } + + function registerTransformSelectComponent(Vue) { + Vue.component('transform-select', { + props: { + value: { type: String, default: '' }, + decodableOnly: { type: Boolean, default: false }, + includeAuto: { type: Boolean, default: false }, + showEmpty: { type: Boolean, default: false }, + emptyLabel: { type: String, default: 'None' }, + selectClass: { type: [String, Object, Array], default: 'transform-select' } + }, + computed: { + categoryOrder: function() { + return transformSelectCategoryOrder(this.$root); + }, + favoriteTransforms: function() { + return transformSelectFavorites(this.$root, this.decodableOnly); + }, + visibleCategories: function() { + var self = this; + return this.categoryOrder.filter(function(category) { + return self.transformsForCategory(category).length > 0; + }); + } + }, + methods: { + categoryDisplayName: function(category) { + return transformSelectCategoryLabel(category); + }, + transformsForCategory: function(category) { + return transformSelectByCategory(this.$root, category, this.decodableOnly); + }, + onChange: function(event) { + this.$emit('input', event.target.value); + this.$emit('change', event); + } + }, + template: '\ +' + }); + } + + global.transformSelectFilter = transformSelectFilter; + global.transformSelectFavorites = transformSelectFavorites; + global.transformSelectByCategory = transformSelectByCategory; + global.transformSelectCategoryOrder = transformSelectCategoryOrder; + global.transformSelectCategoryLabel = transformSelectCategoryLabel; + global.registerTransformSelectComponent = registerTransformSelectComponent; + + if (typeof Vue !== 'undefined') { + registerTransformSelectComponent(Vue); + } +})(typeof window !== 'undefined' ? window : global); diff --git a/js/tools/CodesTool.js b/js/tools/CodesTool.js new file mode 100644 index 0000000..bee1dcb --- /dev/null +++ b/js/tools/CodesTool.js @@ -0,0 +1,262 @@ +/** + * Codes Tool — generate and decode QR codes and barcodes. + */ +class CodesTool extends Tool { + constructor() { + super({ + id: 'codes', + name: 'Codes', + icon: 'fa-qrcode', + title: 'QR codes and barcodes', + order: 9 + }); + } + + getVueData() { + return { + codesMode: 'generate', + codesFormat: 'qr', + codesInput: '', + codesQrSize: 256, + codesQrMargin: 2, + codesQrEcl: 'M', + codesBarcodeHeight: 80, + codesBarcodeWidth: 2, + codesBarcodeDisplayValue: true, + codesOutputUrl: '', + codesOutputSvg: '', + codesError: '', + codesDecodeResult: '', + codesDecodeFormat: '', + codesDecodeError: '', + codesDecodeLoading: false, + codesDecodePreview: '' + }; + } + + getVueMethods() { + return { + codesFormatLabel: function(format) { + var labels = { + qr: 'QR Code', + code128: 'Code 128', + ean13: 'EAN-13', + code39: 'Code 39' + }; + return labels[format] || format; + }, + codesValidateGenerateInput: function() { + var text = String(this.codesInput || '').trim(); + if (!text) { + return 'Enter text or data to encode.'; + } + if (this.codesFormat === 'ean13') { + var digits = text.replace(/\D/g, ''); + if (digits.length !== 12 && digits.length !== 13) { + return 'EAN-13 requires 12 or 13 digits (check digit is calculated automatically for 12).'; + } + } + if (this.codesFormat === 'code39' && !/^[0-9A-Z\s\-\.\$\/\+\%]+$/.test(text.toUpperCase())) { + return 'Code 39 supports A–Z, 0–9, space, and - . $ / + %.'; + } + return ''; + }, + codesClearOutput: function() { + this.codesOutputUrl = ''; + this.codesOutputSvg = ''; + this.codesError = ''; + }, + codesGenerate: function() { + var validationError = this.codesValidateGenerateInput(); + if (validationError) { + this.codesError = validationError; + this.codesClearOutput(); + return; + } + + this.codesError = ''; + this.codesOutputUrl = ''; + this.codesOutputSvg = ''; + + var text = String(this.codesInput || '').trim(); + if (this.codesFormat === 'ean13') { + text = text.replace(/\D/g, ''); + } + if (this.codesFormat === 'code39') { + text = text.toUpperCase(); + } + + var self = this; + + if (this.codesFormat === 'qr') { + if (typeof window.QRCode === 'undefined' || typeof window.QRCode.toDataURL !== 'function') { + this.codesError = 'QR library not loaded. Rebuild the app (npm run build).'; + return; + } + window.QRCode.toDataURL(text, { + width: Math.max(128, Math.min(1024, Number(this.codesQrSize) || 256)), + margin: Math.max(0, Math.min(20, Number(this.codesQrMargin) || 2)), + errorCorrectionLevel: this.codesQrEcl || 'M' + }).then(function(url) { + self.codesOutputUrl = url; + if (typeof self.showNotification === 'function') { + self.showNotification('QR code generated', 'success', 'fas fa-qrcode'); + } + }).catch(function(err) { + self.codesError = (err && err.message) || 'Failed to generate QR code.'; + }); + return; + } + + if (typeof window.JsBarcode === 'undefined') { + this.codesError = 'Barcode library not loaded. Rebuild the app (npm run build).'; + return; + } + + try { + var formatMap = { + code128: 'CODE128', + ean13: 'EAN13', + code39: 'CODE39' + }; + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + window.JsBarcode(svg, text, { + format: formatMap[this.codesFormat] || 'CODE128', + displayValue: !!this.codesBarcodeDisplayValue, + height: Math.max(40, Math.min(200, Number(this.codesBarcodeHeight) || 80)), + width: Math.max(1, Math.min(4, Number(this.codesBarcodeWidth) || 2)), + margin: 10 + }); + var svgMarkup = new XMLSerializer().serializeToString(svg); + this.codesOutputSvg = svgMarkup; + this.codesOutputUrl = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svgMarkup); + if (typeof this.showNotification === 'function') { + this.showNotification(this.codesFormatLabel(this.codesFormat) + ' generated', 'success', 'fas fa-barcode'); + } + } catch (err) { + this.codesError = (err && err.message) || 'Failed to generate barcode.'; + } + }, + codesDownload: function() { + if (!this.codesOutputUrl) { + return; + } + var ext = this.codesFormat === 'qr' ? 'png' : 'svg'; + var link = document.createElement('a'); + link.href = this.codesOutputUrl; + link.download = 'code-' + this.codesFormat + '.' + ext; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + if (typeof this.showNotification === 'function') { + this.showNotification('Download started', 'success', 'fas fa-download'); + } + }, + codesCopyOutput: function() { + if (!this.codesInput.trim()) { + return; + } + if (typeof this.copyToClipboard === 'function') { + this.copyToClipboard(this.codesInput); + } else if (navigator.clipboard) { + navigator.clipboard.writeText(this.codesInput); + } + }, + codesResetDecode: function() { + this.codesDecodeResult = ''; + this.codesDecodeFormat = ''; + this.codesDecodeError = ''; + this.codesDecodePreview = ''; + this.codesDecodeLoading = false; + }, + codesHandleFileUpload: function(event) { + var file = event && event.target && event.target.files && event.target.files[0]; + if (!file) { + return; + } + this.codesDecodeFromFile(file); + event.target.value = ''; + }, + codesDecodeFromFile: function(file) { + var self = this; + if (!file || !file.type.match(/^image\//)) { + this.codesDecodeError = 'Choose a PNG, JPEG, GIF, or WebP image.'; + return; + } + if (typeof window.ZXing === 'undefined' || !window.ZXing.BrowserMultiFormatReader) { + this.codesDecodeError = 'Scanner library not loaded. Rebuild the app (npm run build).'; + return; + } + + this.codesDecodeLoading = true; + this.codesDecodeError = ''; + this.codesDecodeResult = ''; + this.codesDecodeFormat = ''; + + var reader = new FileReader(); + reader.onload = function(loadEvent) { + self.codesDecodePreview = loadEvent.target.result; + self.codesScanImage(loadEvent.target.result); + }; + reader.onerror = function() { + self.codesDecodeLoading = false; + self.codesDecodeError = 'Could not read that file.'; + }; + reader.readAsDataURL(file); + }, + codesScanImage: function(dataUrl) { + var self = this; + var codeReader = new window.ZXing.BrowserMultiFormatReader(); + + codeReader.decodeFromImageUrl(dataUrl).then(function(result) { + self.codesDecodeResult = result.getText(); + self.codesDecodeFormat = result.getBarcodeFormat + ? String(result.getBarcodeFormat()) + : 'unknown'; + self.codesDecodeError = ''; + if (typeof self.showNotification === 'function') { + self.showNotification('Code decoded', 'success', 'fas fa-search'); + } + }).catch(function() { + self.codesDecodeResult = ''; + self.codesDecodeFormat = ''; + self.codesDecodeError = 'No QR code or barcode found in that image.'; + }).finally(function() { + self.codesDecodeLoading = false; + codeReader.reset(); + }); + }, + codesUseDecodedText: function() { + if (!this.codesDecodeResult) { + return; + } + this.codesMode = 'generate'; + this.codesInput = this.codesDecodeResult; + if (typeof this.showNotification === 'function') { + this.showNotification('Copied decoded text to Generate tab', 'success', 'fas fa-arrow-right'); + } + } + }; + } + + getVueWatchers() { + return { + codesMode: function() { + this.codesError = ''; + }, + codesFormat: function() { + this.codesClearOutput(); + } + }; + } + + onActivate(vueInstance) { + vueInstance.codesError = ''; + } +} + +if (typeof module !== 'undefined' && module.exports) { + module.exports = CodesTool; +} else { + window.CodesTool = CodesTool; +} diff --git a/js/tools/DecodeTool.js b/js/tools/DecodeTool.js index ec7a935..1ef2387 100644 --- a/js/tools/DecodeTool.js +++ b/js/tools/DecodeTool.js @@ -135,7 +135,9 @@ class DecodeTool extends Tool { var self = this; return { getAllTransformsWithReverse: function() { - return this.transforms.filter(t => t && typeof t.reverse === 'function'); + return (typeof transformSelectFilter === 'function') + ? transformSelectFilter(this, true) + : this.transforms.filter(t => t && typeof t.reverse === 'function'); }, runUniversalDecode: function() { const input = this.decoderInput; diff --git a/js/tools/SplitterTool.js b/js/tools/SplitterTool.js index cda2038..6107f05 100644 --- a/js/tools/SplitterTool.js +++ b/js/tools/SplitterTool.js @@ -13,9 +13,6 @@ class SplitterTool extends Tool { } getVueData() { - // Load category order (same as TransformTool) - const categoryOrder = this.getCategoryOrder(); - return { // Message Splitter Tab splitterInput: '', @@ -35,78 +32,12 @@ class SplitterTool extends Tool { splitterTokenizer: 'cl100k', // tokenizer for token-based mode splitterTokenCount: 3, // token count per chunk for token-based mode splitterPreserveEmptyLines: false, // preserve empty lines for line/sentence modes - splitMessages: [], - categoryOrder: categoryOrder + splitMessages: [] }; } - getCategoryOrder() { - // Get all categories from transforms - if (!window.transforms) return []; - - const categorySet = new Set(); - Object.values(window.transforms).forEach(transform => { - if (transform.category) { - categorySet.add(transform.category); - } - }); - - const allCategories = Array.from(categorySet); - const savedOrder = this.loadCategoryOrder(); - - return this.mergeCategoryOrder(allCategories, savedOrder); - } - - loadCategoryOrder() { - try { - const saved = localStorage.getItem('transformCategoryOrder'); - if (saved) { - return JSON.parse(saved); - } - } catch (e) { - console.warn('Failed to load category order:', e); - } - return null; - } - - mergeCategoryOrder(allCategories, savedOrder) { - // Always ensure randomizer is last - const categoriesWithoutRandomizer = allCategories.filter(c => c !== 'randomizer'); - - if (!savedOrder || savedOrder.length === 0) { - // Default: alphabetical, randomizer last - const sorted = categoriesWithoutRandomizer.sort((a, b) => a.localeCompare(b)); - return [...sorted, 'randomizer']; - } - - // Use saved order, but filter out categories that no longer exist and remove duplicates - const validSavedOrder = savedOrder - .filter(cat => allCategories.includes(cat)) - .filter((cat, index, arr) => arr.indexOf(cat) === index); // Remove duplicates - - // Find new categories not in saved order - const newCategories = categoriesWithoutRandomizer.filter(cat => !validSavedOrder.includes(cat)); - - // Build final order: saved order (filtered, deduplicated) + new categories (alphabetically) + randomizer - const finalOrder = [...validSavedOrder]; - if (newCategories.length > 0) { - finalOrder.push(...newCategories.sort((a, b) => a.localeCompare(b))); - } - - // Ensure randomizer is always last and remove any duplicates - const finalWithoutRandomizer = finalOrder.filter(c => c !== 'randomizer'); - const uniqueFinal = finalWithoutRandomizer.filter((cat, index, arr) => arr.indexOf(cat) === index); - return [...uniqueFinal, 'randomizer']; - } - getVueMethods() { return { - /** - * Get display name for category (capitalized) - */ - getCategoryDisplayName: function(category) { - return category.charAt(0).toUpperCase() + category.slice(1); - }, /** * Set encapsulation start and end strings * @param {string} start - The start string diff --git a/js/vendor/JsBarcode.min.js b/js/vendor/JsBarcode.min.js new file mode 100644 index 0000000..f53e9bc --- /dev/null +++ b/js/vendor/JsBarcode.min.js @@ -0,0 +1 @@ +"use strict";var JsBarcode=(()=>{var f=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var l=f(ie=>{"use strict";Object.defineProperty(ie,"__esModule",{value:!0});function qr(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var Lr=function t(e,n){qr(this,t),this.data=e,this.text=n.text||e,this.options=n};ie.default=Lr});var dt=f(X=>{"use strict";Object.defineProperty(X,"__esModule",{value:!0});X.CODE39=void 0;var jr=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var D;function ue(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var _t=c.SET_A=0,vt=c.SET_B=1,st=c.SET_C=2,Hf=c.SHIFT=98,Jr=c.START_A=103,Wr=c.START_B=104,Qr=c.START_C=105,Ff=c.MODULO=103,$f=c.STOP=106,Uf=c.FNC1=207,Xf=c.SET_BY_CODE=(D={},ue(D,Jr,_t),ue(D,Wr,vt),ue(D,Qr,st),D),zf=c.SWAP={101:_t,100:vt,99:st},Vf=c.A_START_CHAR="\xD0",Yf=c.B_START_CHAR="\xD1",Jf=c.C_START_CHAR="\xD2",Wf=c.A_CHARS="[\0-_\xC8-\xCF]",Qf=c.B_CHARS="[ -\x7F\xC8-\xCF]",Zf=c.C_CHARS="(\xCF*[0-9]{2}\xCF*)",Kf=c.BARS=[11011001100,11001101100,11001100110,10010011e3,10010001100,10001001100,10011001e3,10011000100,10001100100,11001001e3,11001000100,11000100100,10110011100,10011011100,10011001110,10111001100,10011101100,10011100110,11001110010,11001011100,11001001110,11011100100,11001110100,11101101110,11101001100,11100101100,11100100110,11101100100,11100110100,11100110010,11011011e3,11011000110,11000110110,10100011e3,10001011e3,10001000110,10110001e3,10001101e3,10001100010,11010001e3,11000101e3,11000100010,10110111e3,10110001110,10001101110,10111011e3,10111000110,10001110110,11101110110,11010001110,11000101110,11011101e3,11011100010,11011101110,11101011e3,11101000110,11100010110,11101101e3,11101100010,11100011010,11101111010,11001000010,11110001010,1010011e4,10100001100,1001011e4,10010000110,10000101100,10000100110,1011001e4,10110000100,1001101e4,10011000010,10000110100,10000110010,11000010010,1100101e4,11110111010,11000010100,10001111010,10100111100,10010111100,10010011110,10111100100,10011110100,10011110010,11110100100,11110010100,11110010010,11011011110,11011110110,11110110110,10101111e3,10100011110,10001011110,10111101e3,10111100010,11110101e3,11110100010,10111011110,10111101110,11101011110,11110101110,11010000100,1101001e4,11010011100,1100011101011]});var B=f(oe=>{"use strict";Object.defineProperty(oe,"__esModule",{value:!0});var Zr=(function(){function t(e,n){for(var r=0;r=200){o=r.shift()-105;var s=d.SWAP[o];s!==void 0?u=e.next(r,i+1,s):((a===d.SET_A||a===d.SET_B)&&o===d.SHIFT&&(r[0]=a===d.SET_A?r[0]>95?r[0]-96:r[0]:r[0]<32?r[0]+96:r[0]),u=e.next(r,i+1,a))}else o=e.correctIndex(r,a),u=e.next(r,i+1,a);var g=e.getBar(o),Br=o*i;return{result:g+u.result,checksum:Br+u.checksum}}}]),e})(en.default);oe.default=un});var Et=f(ce=>{"use strict";Object.defineProperty(ce,"__esModule",{value:!0});var O=m(),yt=function(e){return e.match(new RegExp("^"+O.A_CHARS+"*"))[0].length},pt=function(e){return e.match(new RegExp("^"+O.B_CHARS+"*"))[0].length},gt=function(e){return e.match(new RegExp("^"+O.C_CHARS+"*"))[0]};function fe(t,e){var n=e?O.A_CHARS:O.B_CHARS,r=t.match(new RegExp("^("+n+"+?)(([0-9]{2}){2,})([^0-9]|$)"));if(r)return r[1]+"\xCC"+Ot(t.substring(r[1].length));var i=t.match(new RegExp("^"+n+"+"))[0];return i.length===t.length?t:i+String.fromCharCode(e?205:206)+fe(t.substring(i.length),!e)}function Ot(t){var e=gt(t),n=e.length;if(n===t.length)return t;t=t.substring(n);var r=yt(t)>=pt(t);return e+String.fromCharCode(r?206:205)+fe(t,r)}ce.default=function(t){var e=void 0,n=gt(t).length;if(n>=2)e=O.C_START_CHAR+Ot(t);else{var r=yt(t)>pt(t);e=(r?O.A_START_CHAR:O.B_START_CHAR)+fe(t,r)}return e.replace(/[\xCD\xCE]([^])[\xCD\xCE]/,function(i,a){return"\xCB"+a})}});var wt=f(he=>{"use strict";Object.defineProperty(he,"__esModule",{value:!0});var on=B(),fn=bt(on),cn=Et(),ln=bt(cn);function bt(t){return t&&t.__esModule?t:{default:t}}function hn(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function le(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e&&(typeof e=="object"||typeof e=="function")?e:t}function dn(t,e){if(typeof e!="function"&&e!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var _n=(function(t){dn(e,t);function e(n,r){if(hn(this,e),/^[\x00-\x7F\xC8-\xD3]+$/.test(n))var i=le(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,(0,ln.default)(n),r));else var i=le(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,n,r));return le(i)}return e})(fn.default);he.default=_n});var St=f(de=>{"use strict";Object.defineProperty(de,"__esModule",{value:!0});var vn=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(_e,"__esModule",{value:!0});var wn=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(ve,"__esModule",{value:!0});var Mn=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(y,"__esModule",{value:!0});y.CODE128C=y.CODE128B=y.CODE128A=y.CODE128=void 0;var Nn=wt(),Cn=z(Nn),Gn=St(),Hn=z(Gn),Fn=Rt(),$n=z(Fn),Un=Tt(),Xn=z(Un);function z(t){return t&&t.__esModule?t:{default:t}}y.CODE128=Cn.default;y.CODE128A=Hn.default;y.CODE128B=$n.default;y.CODE128C=Xn.default});var S=f(E=>{"use strict";Object.defineProperty(E,"__esModule",{value:!0});var f0=E.SIDE_BIN="101",c0=E.MIDDLE_BIN="01010",l0=E.BINARIES={L:["0001101","0011001","0010011","0111101","0100011","0110001","0101111","0111011","0110111","0001011"],G:["0100111","0110011","0011011","0100001","0011101","0111001","0000101","0010001","0001001","0010111"],R:["1110010","1100110","1101100","1000010","1011100","1001110","1010000","1000100","1001000","1110100"],O:["0001101","0011001","0010011","0111101","0100011","0110001","0101111","0111011","0110111","0001011"],E:["0100111","0110011","0011011","0100001","0011101","0111001","0000101","0010001","0001001","0010111"]},h0=E.EAN2_STRUCTURE=["LL","LG","GL","GG"],d0=E.EAN5_STRUCTURE=["GGLLL","GLGLL","GLLGL","GLLLG","LGGLL","LLGGL","LLLGG","LGLGL","LGLLG","LLGLG"],_0=E.EAN13_STRUCTURE=["LLLLLL","LLGLGG","LLGGLG","LLGGGL","LGLLGG","LGGLLG","LGGGLL","LGLGLG","LGLGGL","LGGLGL"]});var x=f(se=>{"use strict";Object.defineProperty(se,"__esModule",{value:!0});var zn=S(),Vn=function(e,n,r){var i=e.split("").map(function(u,o){return zn.BINARIES[n[o]]}).map(function(u,o){return u?u[e[o]]:""});if(r){var a=e.length-1;i=i.map(function(u,o){return o{"use strict";Object.defineProperty(ye,"__esModule",{value:!0});var Yn=(function(){function t(e,n){for(var r=0;rr.width*10?r.width*10:r.fontSize,i.guardHeight=r.height+i.fontSize/2+r.textMargin,i}return Yn(e,[{key:"encode",value:function(){return this.options.flat?this.encodeFlat():this.encodeGuarded()}},{key:"leftText",value:function(r,i){return this.text.substr(r,i)}},{key:"leftEncode",value:function(r,i){return(0,Mt.default)(r,i)}},{key:"rightText",value:function(r,i){return this.text.substr(r,i)}},{key:"rightEncode",value:function(r,i){return(0,Mt.default)(r,i)}},{key:"encodeGuarded",value:function(){var r={fontSize:this.fontSize},i={height:this.guardHeight};return[{data:R.SIDE_BIN,options:i},{data:this.leftEncode(),text:this.leftText(),options:r},{data:R.MIDDLE_BIN,options:i},{data:this.rightEncode(),text:this.rightText(),options:r},{data:R.SIDE_BIN,options:i}]}},{key:"encodeFlat",value:function(){var r=[R.SIDE_BIN,this.leftEncode(),R.MIDDLE_BIN,this.rightEncode(),R.SIDE_BIN];return{data:r.join(""),text:this.text}}}]),e})(Qn.default);ye.default=ti});var Dt=f(ge=>{"use strict";Object.defineProperty(ge,"__esModule",{value:!0});var ri=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(Oe,"__esModule",{value:!0});var hi=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(Ee,"__esModule",{value:!0});var Oi=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(be,"__esModule",{value:!0});var Mi=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(Y,"__esModule",{value:!0});var Gi=(function(){function t(e,n){for(var r=0;rr.width*10?i.fontSize=r.width*10:i.fontSize=r.fontSize,i.guardHeight=r.height+i.fontSize/2+r.textMargin,i}return Gi(e,[{key:"valid",value:function(){return this.data.search(/^[0-9]{12}$/)!==-1&&this.data[11]==we(this.data)}},{key:"encode",value:function(){return this.options.flat?this.flatEncoding():this.guardedEncoding()}},{key:"flatEncoding",value:function(){var r="";return r+="101",r+=(0,A.default)(this.data.substr(0,6),"LLLLLL"),r+="01010",r+=(0,A.default)(this.data.substr(6,6),"RRRRRR"),r+="101",{data:r,text:this.text}}},{key:"guardedEncoding",value:function(){var r=[];return this.displayValue&&r.push({data:"00000000",text:this.text.substr(0,1),options:{textAlign:"left",fontSize:this.fontSize}}),r.push({data:"101"+(0,A.default)(this.data[0],"L"),options:{height:this.guardHeight}}),r.push({data:(0,A.default)(this.data.substr(1,5),"LLLLL"),text:this.text.substr(1,5),options:{fontSize:this.fontSize}}),r.push({data:"01010",options:{height:this.guardHeight}}),r.push({data:(0,A.default)(this.data.substr(6,5),"RRRRR"),text:this.text.substr(6,5),options:{fontSize:this.fontSize}}),r.push({data:(0,A.default)(this.data[11],"R")+"101",options:{height:this.guardHeight}}),this.displayValue&&r.push({data:"00000000",text:this.text.substr(11,1),options:{textAlign:"right",fontSize:this.fontSize}}),r}}]),e})($i.default);function we(t){var e=0,n;for(n=1;n<11;n+=2)e+=parseInt(t[n]);for(n=0;n<11;n+=2)e+=parseInt(t[n])*3;return(10-e%10)%10}Y.default=Vi});var $t=f(xe=>{"use strict";Object.defineProperty(xe,"__esModule",{value:!0});var Yi=(function(){function t(e,n){for(var r=0;rr.width*10?i.fontSize=r.width*10:i.fontSize=r.fontSize,i.guardHeight=r.height+i.fontSize/2+r.textMargin,i}return Yi(e,[{key:"valid",value:function(){return this.isValid}},{key:"encode",value:function(){return this.options.flat?this.flatEncoding():this.guardedEncoding()}},{key:"flatEncoding",value:function(){var r="";return r+="101",r+=this.encodeMiddleDigits(),r+="010101",{data:r,text:this.text}}},{key:"guardedEncoding",value:function(){var r=[];return this.displayValue&&r.push({data:"00000000",text:this.text[0],options:{textAlign:"left",fontSize:this.fontSize}}),r.push({data:"101",options:{height:this.guardHeight}}),r.push({data:this.encodeMiddleDigits(),text:this.text.substring(1,7),options:{fontSize:this.fontSize}}),r.push({data:"010101",options:{height:this.guardHeight}}),this.displayValue&&r.push({data:"00000000",text:this.text[7],options:{textAlign:"right",fontSize:this.fontSize}}),r}},{key:"encodeMiddleDigits",value:function(){var r=this.upcA[0],i=this.upcA[this.upcA.length-1],a=na[parseInt(i)][parseInt(r)];return(0,Wi.default)(this.middleDigits,a)}}]),e})(Zi.default);function Ht(t,e){for(var n=parseInt(t[t.length-1]),r=ra[n],i="",a=0,u=0;u{"use strict";Object.defineProperty(h,"__esModule",{value:!0});h.UPCE=h.UPC=h.EAN2=h.EAN5=h.EAN8=h.EAN13=void 0;var aa=Dt(),ua=T(aa),oa=qt(),fa=T(oa),ca=jt(),la=T(ca),ha=Ct(),da=T(ha),_a=me(),va=T(_a),sa=$t(),ya=T(sa);function T(t){return t&&t.__esModule?t:{default:t}}h.EAN13=ua.default;h.EAN8=fa.default;h.EAN5=la.default;h.EAN2=da.default;h.UPC=va.default;h.UPCE=ya.default});var Xt=f(L=>{"use strict";Object.defineProperty(L,"__esModule",{value:!0});var S0=L.START_BIN="1010",x0=L.END_BIN="11101",R0=L.BINARIES=["00110","10001","01001","11000","00101","10100","01100","00011","10010","01010"]});var Ae=f(Re=>{"use strict";Object.defineProperty(Re,"__esModule",{value:!0});var pa=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(Te,"__esModule",{value:!0});var xa=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(P,"__esModule",{value:!0});P.ITF14=P.ITF=void 0;var Da=Ae(),Ba=Yt(Da),qa=Vt(),La=Yt(qa);function Yt(t){return t&&t.__esModule?t:{default:t}}P.ITF=Ba.default;P.ITF14=La.default});var M=f(Pe=>{"use strict";Object.defineProperty(Pe,"__esModule",{value:!0});var ja=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(W,"__esModule",{value:!0});W.mod10=za;W.mod11=Va;function za(t){for(var e=0,n=0;n{"use strict";Object.defineProperty(Me,"__esModule",{value:!0});var Ya=M(),Ja=Qa(Ya),Wa=j();function Qa(t){return t&&t.__esModule?t:{default:t}}function Za(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function Ka(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e&&(typeof e=="object"||typeof e=="function")?e:t}function eu(t,e){if(typeof e!="function"&&e!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var tu=(function(t){eu(e,t);function e(n,r){return Za(this,e),Ka(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,n+(0,Wa.mod10)(n),r))}return e})(Ja.default);Me.default=tu});var Qt=f(Ie=>{"use strict";Object.defineProperty(Ie,"__esModule",{value:!0});var ru=M(),nu=au(ru),iu=j();function au(t){return t&&t.__esModule?t:{default:t}}function uu(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function ou(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e&&(typeof e=="object"||typeof e=="function")?e:t}function fu(t,e){if(typeof e!="function"&&e!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var cu=(function(t){fu(e,t);function e(n,r){return uu(this,e),ou(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,n+(0,iu.mod11)(n),r))}return e})(nu.default);Ie.default=cu});var Kt=f(ke=>{"use strict";Object.defineProperty(ke,"__esModule",{value:!0});var lu=M(),hu=du(lu),Zt=j();function du(t){return t&&t.__esModule?t:{default:t}}function _u(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function vu(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e&&(typeof e=="object"||typeof e=="function")?e:t}function su(t,e){if(typeof e!="function"&&e!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var yu=(function(t){su(e,t);function e(n,r){return _u(this,e),n+=(0,Zt.mod10)(n),n+=(0,Zt.mod10)(n),vu(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,n,r))}return e})(hu.default);ke.default=yu});var tr=f(De=>{"use strict";Object.defineProperty(De,"__esModule",{value:!0});var pu=M(),gu=Ou(pu),er=j();function Ou(t){return t&&t.__esModule?t:{default:t}}function Eu(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function bu(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e&&(typeof e=="object"||typeof e=="function")?e:t}function wu(t,e){if(typeof e!="function"&&e!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var mu=(function(t){wu(e,t);function e(n,r){return Eu(this,e),n+=(0,er.mod11)(n),n+=(0,er.mod10)(n),bu(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,n,r))}return e})(gu.default);De.default=mu});var rr=f(_=>{"use strict";Object.defineProperty(_,"__esModule",{value:!0});_.MSI1110=_.MSI1010=_.MSI11=_.MSI10=_.MSI=void 0;var Su=M(),xu=N(Su),Ru=Wt(),Au=N(Ru),Tu=Qt(),Pu=N(Tu),Mu=Kt(),Iu=N(Mu),ku=tr(),Du=N(ku);function N(t){return t&&t.__esModule?t:{default:t}}_.MSI=xu.default;_.MSI10=Au.default;_.MSI11=Pu.default;_.MSI1010=Iu.default;_.MSI1110=Du.default});var nr=f(Q=>{"use strict";Object.defineProperty(Q,"__esModule",{value:!0});Q.pharmacode=void 0;var Bu=(function(){function t(e,n){for(var r=0;r=3&&this.number<=131070}}]),e})(Lu.default);Q.pharmacode=Hu});var ir=f(Z=>{"use strict";Object.defineProperty(Z,"__esModule",{value:!0});Z.codabar=void 0;var Fu=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(C,"__esModule",{value:!0});var G0=C.SYMBOLS=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","-","."," ","$","/","+","%","($)","(%)","(/)","(+)","\xFF"],H0=C.BINARIES=["100010100","101001000","101000100","101000010","100101000","100100100","100100010","101010000","100010010","100001010","110101000","110100100","110100010","110010100","110010010","110001010","101101000","101100100","101100010","100110100","100011010","101011000","101001100","101000110","100101100","100010110","110110100","110110010","110101100","110100110","110010110","110011010","101101100","101100110","100110110","100111010","100101110","111010100","111010010","111001010","101101110","101110110","110101110","100100110","111011010","111010110","100110010","101011110"],F0=C.MULTI_SYMBOLS={"\0":["(%)","U"],"":["($)","A"],"":["($)","B"],"":["($)","C"],"":["($)","D"],"":["($)","E"],"":["($)","F"],"\x07":["($)","G"],"\b":["($)","H"]," ":["($)","I"],"\n":["($)","J"],"\v":["($)","K"],"\f":["($)","L"],"\r":["($)","M"],"":["($)","N"],"":["($)","O"],"":["($)","P"],"":["($)","Q"],"":["($)","R"],"":["($)","S"],"":["($)","T"],"":["($)","U"],"":["($)","V"],"":["($)","W"],"":["($)","X"],"":["($)","Y"],"":["($)","Z"],"\x1B":["(%)","A"],"":["(%)","B"],"":["(%)","C"],"":["(%)","D"],"":["(%)","E"],"!":["(/)","A"],'"':["(/)","B"],"#":["(/)","C"],"&":["(/)","F"],"'":["(/)","G"],"(":["(/)","H"],")":["(/)","I"],"*":["(/)","J"],",":["(/)","L"],":":["(/)","Z"],";":["(%)","F"],"<":["(%)","G"],"=":["(%)","H"],">":["(%)","I"],"?":["(%)","J"],"@":["(%)","V"],"[":["(%)","K"],"\\":["(%)","L"],"]":["(%)","M"],"^":["(%)","N"],_:["(%)","O"],"`":["(%)","W"],a:["(+)","A"],b:["(+)","B"],c:["(+)","C"],d:["(+)","D"],e:["(+)","E"],f:["(+)","F"],g:["(+)","G"],h:["(+)","H"],i:["(+)","I"],j:["(+)","J"],k:["(+)","K"],l:["(+)","L"],m:["(+)","M"],n:["(+)","N"],o:["(+)","O"],p:["(+)","P"],q:["(+)","Q"],r:["(+)","R"],s:["(+)","S"],t:["(+)","T"],u:["(+)","U"],v:["(+)","V"],w:["(+)","W"],x:["(+)","X"],y:["(+)","Y"],z:["(+)","Z"],"{":["(%)","P"],"|":["(%)","Q"],"}":["(%)","R"],"~":["(%)","S"],"\x7F":["(%)","T"]}});var qe=f(Be=>{"use strict";Object.defineProperty(Be,"__esModule",{value:!0});var Wu=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(Le,"__esModule",{value:!0});var io=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(I,"__esModule",{value:!0});I.CODE93FullASCII=I.CODE93=void 0;var _o=qe(),vo=or(_o),so=ur(),yo=or(so);function or(t){return t&&t.__esModule?t:{default:t}}I.CODE93=vo.default;I.CODE93FullASCII=yo.default});var cr=f(ee=>{"use strict";Object.defineProperty(ee,"__esModule",{value:!0});ee.GenericBarcode=void 0;var po=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(je,"__esModule",{value:!0});var xo=dt(),te=Pt(),k=Ut(),lr=Jt(),G=rr(),Ro=nr(),Ao=ir(),hr=fr(),To=cr();je.default={CODE39:xo.CODE39,CODE128:te.CODE128,CODE128A:te.CODE128A,CODE128B:te.CODE128B,CODE128C:te.CODE128C,EAN13:k.EAN13,EAN8:k.EAN8,EAN5:k.EAN5,EAN2:k.EAN2,UPC:k.UPC,UPCE:k.UPCE,ITF14:lr.ITF14,ITF:lr.ITF,MSI:G.MSI,MSI10:G.MSI10,MSI11:G.MSI11,MSI1010:G.MSI1010,MSI1110:G.MSI1110,pharmacode:Ro.pharmacode,codabar:Ao.codabar,CODE93:hr.CODE93,CODE93FullASCII:hr.CODE93FullASCII,GenericBarcode:To.GenericBarcode}});var H=f(Ne=>{"use strict";Object.defineProperty(Ne,"__esModule",{value:!0});var Po=Object.assign||function(t){for(var e=1;e{"use strict";Object.defineProperty(Ce,"__esModule",{value:!0});Ce.default=Mo;function Mo(t){var e=[];function n(r){if(Array.isArray(r))for(var i=0;i{"use strict";Object.defineProperty(Ge,"__esModule",{value:!0});Ge.default=Io;function Io(t){return t.marginTop=t.marginTop||t.margin,t.marginBottom=t.marginBottom||t.margin,t.marginRight=t.marginRight||t.margin,t.marginLeft=t.marginLeft||t.margin,t}});var Fe=f(He=>{"use strict";Object.defineProperty(He,"__esModule",{value:!0});He.default=ko;function ko(t){var e=["width","height","textMargin","fontSize","margin","marginTop","marginBottom","marginLeft","marginRight"];for(var n in e)e.hasOwnProperty(n)&&(n=e[n],typeof t[n]=="string"&&(t[n]=parseInt(t[n],10)));return typeof t.displayValue=="string"&&(t.displayValue=t.displayValue!="false"),t}});var Ue=f($e=>{"use strict";Object.defineProperty($e,"__esModule",{value:!0});var Do={width:2,height:100,format:"auto",displayValue:!0,fontOptions:"",font:"monospace",text:void 0,textAlign:"center",textPosition:"bottom",textMargin:2,fontSize:20,background:"#ffffff",lineColor:"#000000",margin:10,marginTop:void 0,marginBottom:void 0,marginLeft:void 0,marginRight:void 0,valid:function(){}};$e.default=Do});var pr=f(Xe=>{"use strict";Object.defineProperty(Xe,"__esModule",{value:!0});var Bo=Fe(),qo=yr(Bo),Lo=Ue(),sr=yr(Lo);function yr(t){return t&&t.__esModule?t:{default:t}}function jo(t){var e={};for(var n in sr.default)sr.default.hasOwnProperty(n)&&(t.hasAttribute("jsbarcode-"+n.toLowerCase())&&(e[n]=t.getAttribute("jsbarcode-"+n.toLowerCase())),t.hasAttribute("data-"+n.toLowerCase())&&(e[n]=t.getAttribute("data-"+n.toLowerCase())));return e.value=t.getAttribute("jsbarcode-value")||t.getAttribute("data-value"),e=(0,qo.default)(e),e}Xe.default=jo});var ze=f(v=>{"use strict";Object.defineProperty(v,"__esModule",{value:!0});v.getTotalWidthOfEncodings=v.calculateEncodingAttributes=v.getBarcodePadding=v.getEncodingHeight=v.getMaximumHeightOfEncodings=void 0;var No=H(),Co=Go(No);function Go(t){return t&&t.__esModule?t:{default:t}}function gr(t,e){return e.height+(e.displayValue&&t.text.length>0?e.fontSize+e.textMargin:0)+e.marginTop+e.marginBottom}function Or(t,e,n){if(n.displayValue&&ee&&(e=t[n].height);return e}function Uo(t,e,n){var r;if(n)r=n;else if(typeof document<"u")r=document.createElement("canvas").getContext("2d");else return 0;r.font=e.fontOptions+" "+e.fontSize+"px "+e.font;var i=r.measureText(t);if(!i)return 0;var a=i.width;return a}v.getMaximumHeightOfEncodings=$o;v.getEncodingHeight=gr;v.getBarcodePadding=Or;v.calculateEncodingAttributes=Ho;v.getTotalWidthOfEncodings=Fo});var Er=f(Ye=>{"use strict";Object.defineProperty(Ye,"__esModule",{value:!0});var Xo=(function(){function t(e,n){for(var r=0;r0?(u=0,i.textAlign="left"):n.textAlign=="right"?(u=r.width-1,i.textAlign="right"):(u=r.width/2,i.textAlign="center"),i.fillText(r.text,u,o)}}},{key:"moveCanvasDrawing",value:function(n){var r=this.canvas.getContext("2d");r.translate(n.width,0)}},{key:"restoreCanvas",value:function(){var n=this.canvas.getContext("2d");n.restore()}}]),t})();Ye.default=Wo});var br=f(We=>{"use strict";Object.defineProperty(We,"__esModule",{value:!0});var Qo=(function(){function t(e,n){for(var r=0;r0&&(this.drawRect(s-r.width*o,u,r.width*o,r.height,n),o=0);o>0&&this.drawRect(s-r.width*(o-1),u,r.width*o,r.height,n)}},{key:"drawSVGText",value:function(n,r,i){var a=this.document.createElementNS(re,"text");if(r.displayValue){var u,o;a.setAttribute("font-family",r.font),a.setAttribute("font-size",r.fontSize),r.fontOptions.includes("bold")&&a.setAttribute("font-weight","bold"),r.fontOptions.includes("italic")&&a.setAttribute("font-style","italic"),r.textPosition=="top"?o=r.fontSize-r.textMargin:o=r.height+r.textMargin+r.fontSize,r.textAlign=="left"||i.barcodePadding>0?(u=0,a.setAttribute("text-anchor","start")):r.textAlign=="right"?(u=i.width-1,a.setAttribute("text-anchor","end")):(u=i.width/2,a.setAttribute("text-anchor","middle")),a.setAttribute("x",u),a.setAttribute("y",o),a.appendChild(this.document.createTextNode(i.text)),n.appendChild(a)}}},{key:"setSvgAttributes",value:function(n,r){var i=this.svg;i.setAttribute("width",n+"px"),i.setAttribute("height",r+"px"),i.setAttribute("x","0px"),i.setAttribute("y","0px"),i.setAttribute("viewBox","0 0 "+n+" "+r),i.setAttribute("xmlns",re),i.setAttribute("version","1.1")}},{key:"createGroup",value:function(n,r,i){var a=this.document.createElementNS(re,"g");return a.setAttribute("transform","translate("+n+", "+r+")"),i.appendChild(a),a}},{key:"setGroupOptions",value:function(n,r){n.setAttribute("fill",r.lineColor)}},{key:"drawRect",value:function(n,r,i,a,u){var o=this.document.createElementNS(re,"rect");return o.setAttribute("x",n),o.setAttribute("y",r),o.setAttribute("width",i),o.setAttribute("height",a),u.appendChild(o),o}}]),t})();We.default=rf});var wr=f(Qe=>{"use strict";Object.defineProperty(Qe,"__esModule",{value:!0});var nf=(function(){function t(e,n){for(var r=0;r{"use strict";Object.defineProperty(Ke,"__esModule",{value:!0});var of=Er(),ff=Ze(of),cf=br(),lf=Ze(cf),hf=wr(),df=Ze(hf);function Ze(t){return t&&t.__esModule?t:{default:t}}Ke.default={CanvasRenderer:ff.default,SVGRenderer:lf.default,ObjectRenderer:df.default}});var nt=f(F=>{"use strict";Object.defineProperty(F,"__esModule",{value:!0});function et(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function tt(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e&&(typeof e=="object"||typeof e=="function")?e:t}function rt(t,e){if(typeof e!="function"&&e!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var _f=(function(t){rt(e,t);function e(n,r){et(this,e);var i=tt(this,(e.__proto__||Object.getPrototypeOf(e)).call(this));return i.name="InvalidInputException",i.symbology=n,i.input=r,i.message='"'+i.input+'" is not a valid input for '+i.symbology,i}return e})(Error),vf=(function(t){rt(e,t);function e(){et(this,e);var n=tt(this,(e.__proto__||Object.getPrototypeOf(e)).call(this));return n.name="InvalidElementException",n.message="Not supported type to render on",n}return e})(Error),sf=(function(t){rt(e,t);function e(){et(this,e);var n=tt(this,(e.__proto__||Object.getPrototypeOf(e)).call(this));return n.name="NoElementException",n.message="No element to render on.",n}return e})(Error);F.InvalidInputException=_f;F.InvalidElementException=vf;F.NoElementException=sf});var xr=f(ut=>{"use strict";Object.defineProperty(ut,"__esModule",{value:!0});var yf=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},pf=pr(),it=Sr(pf),gf=mr(),$=Sr(gf),Of=nt();function Sr(t){return t&&t.__esModule?t:{default:t}}function at(t){if(typeof t=="string")return Ef(t);if(Array.isArray(t)){for(var e=[],n=0;n"u"?"undefined":yf(t))==="object"&&!t.nodeName)return{element:t,renderer:$.default.ObjectRenderer};throw new Of.InvalidElementException}}function Ef(t){var e=document.querySelectorAll(t);if(e.length!==0){for(var n=[],r=0;r{"use strict";Object.defineProperty(ot,"__esModule",{value:!0});var wf=(function(){function t(e,n){for(var r=0;r{var xf=dr(),w=b(xf),Rf=H(),U=b(Rf),Af=_r(),Tr=b(Af),Tf=vr(),Ar=b(Tf),Pf=xr(),Mf=b(Pf),If=Fe(),kf=b(If),Df=Rr(),Bf=b(Df),Pr=nt(),qf=Ue(),Mr=b(qf);function b(t){return t&&t.__esModule?t:{default:t}}var p=function(){},ne=function(e,n,r){var i=new p;if(typeof e>"u")throw Error("No element to render on was provided.");return i._renderProperties=(0,Mf.default)(e),i._encodings=[],i._options=Mr.default,i._errorHandler=new Bf.default(i),typeof n<"u"&&(r=r||{},r.format||(r.format=kr()),i.options(r)[r.format](n,r).render()),i};ne.getModule=function(t){return w.default[t]};for(ft in w.default)w.default.hasOwnProperty(ft)&&Lf(w.default,ft);var ft;function Lf(t,e){p.prototype[e]=p.prototype[e.toUpperCase()]=p.prototype[e.toLowerCase()]=function(n,r){var i=this;return i._errorHandler.wrapBarcodeCall(function(){r.text=typeof r.text>"u"?void 0:""+r.text;var a=(0,U.default)(i._options,r);a=(0,kf.default)(a);var u=t[e],o=Ir(n,u,a);return i._encodings.push(o),i})}}function Ir(t,e,n){t=""+t;var r=new e(t,n);if(!r.valid())throw new Pr.InvalidInputException(r.constructor.name,t);var i=r.encode();i=(0,Tr.default)(i);for(var a=0;a{var g=(n,t)=>()=>(t||n((t={exports:{}}).exports,t),t.exports);var _t=g((Sn,Lt)=>{Lt.exports=function(){return typeof Promise=="function"&&Promise.prototype&&Promise.prototype.then}});var I=g(P=>{var st,Le=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706];P.getSymbolSize=function(t){if(!t)throw new Error('"version" cannot be null or undefined');if(t<1||t>40)throw new Error('"version" should be in range from 1 to 40');return t*4+17};P.getSymbolTotalCodewords=function(t){return Le[t]};P.getBCHDigit=function(n){let t=0;for(;n!==0;)t++,n>>>=1;return t};P.setToSJISFunction=function(t){if(typeof t!="function")throw new Error('"toSJISFunc" is not a valid function.');st=t};P.isKanjiModeEnabled=function(){return typeof st<"u"};P.toSJIS=function(t){return st(t)}});var j=g(m=>{m.L={bit:1};m.M={bit:0};m.Q={bit:3};m.H={bit:2};function _e(n){if(typeof n!="string")throw new Error("Param is not a string");switch(n.toLowerCase()){case"l":case"low":return m.L;case"m":case"medium":return m.M;case"q":case"quartile":return m.Q;case"h":case"high":return m.H;default:throw new Error("Unknown EC Level: "+n)}}m.isValid=function(t){return t&&typeof t.bit<"u"&&t.bit>=0&&t.bit<4};m.from=function(t,e){if(m.isValid(t))return t;try{return _e(t)}catch{return e}}});var qt=g((Rn,Ut)=>{function xt(){this.buffer=[],this.length=0}xt.prototype={get:function(n){let t=Math.floor(n/8);return(this.buffer[t]>>>7-n%8&1)===1},put:function(n,t){for(let e=0;e>>t-e-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(n){let t=Math.floor(this.length/8);this.buffer.length<=t&&this.buffer.push(0),n&&(this.buffer[t]|=128>>>this.length%8),this.length++}};Ut.exports=xt});var Ft=g((Ln,Dt)=>{function k(n){if(!n||n<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=n,this.data=new Uint8Array(n*n),this.reservedBit=new Uint8Array(n*n)}k.prototype.set=function(n,t,e,r){let o=n*this.size+t;this.data[o]=e,r&&(this.reservedBit[o]=!0)};k.prototype.get=function(n,t){return this.data[n*this.size+t]};k.prototype.xor=function(n,t,e){this.data[n*this.size+t]^=e};k.prototype.isReserved=function(n,t){return this.reservedBit[n*this.size+t]};Dt.exports=k});var kt=g(G=>{var xe=I().getSymbolSize;G.getRowColCoords=function(t){if(t===1)return[];let e=Math.floor(t/7)+2,r=xe(t),o=r===145?26:Math.ceil((r-13)/(2*e-2))*2,i=[r-7];for(let s=1;s{var Ue=I().getSymbolSize,zt=7;Vt.getPositions=function(t){let e=Ue(t);return[[0,0],[e-zt,0],[0,e-zt]]}});var Kt=g(d=>{d.Patterns={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var b={N1:3,N2:3,N3:40,N4:10};d.isValid=function(t){return t!=null&&t!==""&&!isNaN(t)&&t>=0&&t<=7};d.from=function(t){return d.isValid(t)?parseInt(t,10):void 0};d.getPenaltyN1=function(t){let e=t.size,r=0,o=0,i=0,s=null,u=null;for(let c=0;c=5&&(r+=b.N1+(o-5)),s=a,o=1),a=t.get(l,c),a===u?i++:(i>=5&&(r+=b.N1+(i-5)),u=a,i=1)}o>=5&&(r+=b.N1+(o-5)),i>=5&&(r+=b.N1+(i-5))}return r};d.getPenaltyN2=function(t){let e=t.size,r=0;for(let o=0;o=10&&(o===1488||o===93)&&r++,i=i<<1&2047|t.get(u,s),u>=10&&(i===1488||i===93)&&r++}return r*b.N3};d.getPenaltyN4=function(t){let e=0,r=t.data.length;for(let i=0;i{var N=j(),Q=[1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,4,1,2,4,4,2,4,4,4,2,4,6,5,2,4,6,6,2,5,8,8,4,5,8,8,4,5,8,11,4,8,10,11,4,9,12,16,4,9,16,16,6,10,12,18,6,10,17,16,6,11,16,19,6,13,18,21,7,14,21,25,8,16,20,25,8,17,23,25,9,17,23,34,9,18,25,30,10,20,27,32,12,21,29,35,12,23,34,37,12,25,34,40,13,26,35,42,14,28,38,45,15,29,40,48,16,31,43,51,17,33,45,54,18,35,48,57,19,37,51,60,19,38,53,63,20,40,56,66,21,43,59,70,22,45,62,74,24,47,65,77,25,49,68,81],$=[7,10,13,17,10,16,22,28,15,26,36,44,20,36,52,64,26,48,72,88,36,64,96,112,40,72,108,130,48,88,132,156,60,110,160,192,72,130,192,224,80,150,224,264,96,176,260,308,104,198,288,352,120,216,320,384,132,240,360,432,144,280,408,480,168,308,448,532,180,338,504,588,196,364,546,650,224,416,600,700,224,442,644,750,252,476,690,816,270,504,750,900,300,560,810,960,312,588,870,1050,336,644,952,1110,360,700,1020,1200,390,728,1050,1260,420,784,1140,1350,450,812,1200,1440,480,868,1290,1530,510,924,1350,1620,540,980,1440,1710,570,1036,1530,1800,570,1064,1590,1890,600,1120,1680,1980,630,1204,1770,2100,660,1260,1860,2220,720,1316,1950,2310,750,1372,2040,2430];ut.getBlocksCount=function(t,e){switch(e){case N.L:return Q[(t-1)*4+0];case N.M:return Q[(t-1)*4+1];case N.Q:return Q[(t-1)*4+2];case N.H:return Q[(t-1)*4+3];default:return}};ut.getTotalCodewordsCount=function(t,e){switch(e){case N.L:return $[(t-1)*4+0];case N.M:return $[(t-1)*4+1];case N.Q:return $[(t-1)*4+2];case N.H:return $[(t-1)*4+3];default:return}}});var Jt=g(Z=>{var z=new Uint8Array(512),W=new Uint8Array(256);(function(){let t=1;for(let e=0;e<255;e++)z[e]=t,W[t]=e,t<<=1,t&256&&(t^=285);for(let e=255;e<512;e++)z[e]=z[e-255]})();Z.log=function(t){if(t<1)throw new Error("log("+t+")");return W[t]};Z.exp=function(t){return z[t]};Z.mul=function(t,e){return t===0||e===0?0:z[W[t]+W[e]]}});var Yt=g(V=>{var lt=Jt();V.mul=function(t,e){let r=new Uint8Array(t.length+e.length-1);for(let o=0;o=0;){let o=r[0];for(let s=0;s{var Ot=Yt();function at(n){this.genPoly=void 0,this.degree=n,this.degree&&this.initialize(this.degree)}at.prototype.initialize=function(t){this.degree=t,this.genPoly=Ot.generateECPolynomial(this.degree)};at.prototype.encode=function(t){if(!this.genPoly)throw new Error("Encoder not initialized");let e=new Uint8Array(t.length+this.degree);e.set(t);let r=Ot.mod(e,this.genPoly),o=this.degree-r.length;if(o>0){let i=new Uint8Array(this.degree);return i.set(r,o),i}return r};jt.exports=at});var ft=g(Qt=>{Qt.isValid=function(t){return!isNaN(t)&&t>=1&&t<=40}});var gt=g(B=>{var $t="[0-9]+",De="[A-Z $%*+\\-./:]+",H="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";H=H.replace(/u/g,"\\u");var Fe="(?:(?![A-Z0-9 $%*+\\-./:]|"+H+`)(?:.|[\r +]))+`;B.KANJI=new RegExp(H,"g");B.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g");B.BYTE=new RegExp(Fe,"g");B.NUMERIC=new RegExp($t,"g");B.ALPHANUMERIC=new RegExp(De,"g");var ke=new RegExp("^"+H+"$"),ze=new RegExp("^"+$t+"$"),Ve=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");B.testKanji=function(t){return ke.test(t)};B.testNumeric=function(t){return ze.test(t)};B.testAlphanumeric=function(t){return Ve.test(t)}});var M=g(p=>{var He=ft(),dt=gt();p.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]};p.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]};p.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]};p.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]};p.MIXED={bit:-1};p.getCharCountIndicator=function(t,e){if(!t.ccBits)throw new Error("Invalid mode: "+t);if(!He.isValid(e))throw new Error("Invalid version: "+e);return e>=1&&e<10?t.ccBits[0]:e<27?t.ccBits[1]:t.ccBits[2]};p.getBestModeForData=function(t){return dt.testNumeric(t)?p.NUMERIC:dt.testAlphanumeric(t)?p.ALPHANUMERIC:dt.testKanji(t)?p.KANJI:p.BYTE};p.toString=function(t){if(t&&t.id)return t.id;throw new Error("Invalid mode")};p.isValid=function(t){return t&&t.bit&&t.ccBits};function Ke(n){if(typeof n!="string")throw new Error("Param is not a string");switch(n.toLowerCase()){case"numeric":return p.NUMERIC;case"alphanumeric":return p.ALPHANUMERIC;case"kanji":return p.KANJI;case"byte":return p.BYTE;default:throw new Error("Unknown mode: "+n)}}p.from=function(t,e){if(p.isValid(t))return t;try{return Ke(t)}catch{return e}}});var te=g(R=>{var X=I(),Je=ct(),Wt=j(),S=M(),ht=ft(),Xt=7973,Zt=X.getBCHDigit(Xt);function Ye(n,t,e){for(let r=1;r<=40;r++)if(t<=R.getCapacity(r,e,n))return r}function vt(n,t){return S.getCharCountIndicator(n,t)+4}function Oe(n,t){let e=0;return n.forEach(function(r){let o=vt(r.mode,t);e+=o+r.getBitsLength()}),e}function je(n,t){for(let e=1;e<=40;e++)if(Oe(n,e)<=R.getCapacity(e,t,S.MIXED))return e}R.from=function(t,e){return ht.isValid(t)?parseInt(t,10):e};R.getCapacity=function(t,e,r){if(!ht.isValid(t))throw new Error("Invalid QR Code version");typeof r>"u"&&(r=S.BYTE);let o=X.getSymbolTotalCodewords(t),i=Je.getTotalCodewordsCount(t,e),s=(o-i)*8;if(r===S.MIXED)return s;let u=s-vt(r,t);switch(r){case S.NUMERIC:return Math.floor(u/10*3);case S.ALPHANUMERIC:return Math.floor(u/11*2);case S.KANJI:return Math.floor(u/13);case S.BYTE:default:return Math.floor(u/8)}};R.getBestVersionForData=function(t,e){let r,o=Wt.from(e,Wt.M);if(Array.isArray(t)){if(t.length>1)return je(t,o);if(t.length===0)return 1;r=t[0]}else r=t;return Ye(r.mode,r.getLength(),o)};R.getEncodedBits=function(t){if(!ht.isValid(t)||t<7)throw new Error("Invalid QR Code version");let e=t<<12;for(;X.getBCHDigit(e)-Zt>=0;)e^=Xt<{var pt=I(),ne=1335,Ge=21522,ee=pt.getBCHDigit(ne);re.getEncodedBits=function(t,e){let r=t.bit<<3|e,o=r<<10;for(;pt.getBCHDigit(o)-ee>=0;)o^=ne<{var Qe=M();function x(n){this.mode=Qe.NUMERIC,this.data=n.toString()}x.getBitsLength=function(t){return 10*Math.floor(t/3)+(t%3?t%3*3+1:0)};x.prototype.getLength=function(){return this.data.length};x.prototype.getBitsLength=function(){return x.getBitsLength(this.data.length)};x.prototype.write=function(t){let e,r,o;for(e=0;e+3<=this.data.length;e+=3)r=this.data.substr(e,3),o=parseInt(r,10),t.put(o,10);let i=this.data.length-e;i>0&&(r=this.data.substr(e),o=parseInt(r,10),t.put(o,i*3+1))};ie.exports=x});var ce=g((On,ue)=>{var $e=M(),wt=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function U(n){this.mode=$e.ALPHANUMERIC,this.data=n}U.getBitsLength=function(t){return 11*Math.floor(t/2)+6*(t%2)};U.prototype.getLength=function(){return this.data.length};U.prototype.getBitsLength=function(){return U.getBitsLength(this.data.length)};U.prototype.write=function(t){let e;for(e=0;e+2<=this.data.length;e+=2){let r=wt.indexOf(this.data[e])*45;r+=wt.indexOf(this.data[e+1]),t.put(r,11)}this.data.length%2&&t.put(wt.indexOf(this.data[e]),6)};ue.exports=U});var ae=g((jn,le)=>{var We=M();function q(n){this.mode=We.BYTE,typeof n=="string"?this.data=new TextEncoder().encode(n):this.data=new Uint8Array(n)}q.getBitsLength=function(t){return t*8};q.prototype.getLength=function(){return this.data.length};q.prototype.getBitsLength=function(){return q.getBitsLength(this.data.length)};q.prototype.write=function(n){for(let t=0,e=this.data.length;t{var Ze=M(),Xe=I();function D(n){this.mode=Ze.KANJI,this.data=n}D.getBitsLength=function(t){return t*13};D.prototype.getLength=function(){return this.data.length};D.prototype.getBitsLength=function(){return D.getBitsLength(this.data.length)};D.prototype.write=function(n){let t;for(t=0;t=33088&&e<=40956)e-=33088;else if(e>=57408&&e<=60351)e-=49472;else throw new Error("Invalid SJIS character: "+this.data[t]+` +Make sure your charset is UTF-8`);e=(e>>>8&255)*192+(e&255),n.put(e,13)}};fe.exports=D});var de=g((Qn,mt)=>{"use strict";var K={single_source_shortest_paths:function(n,t,e){var r={},o={};o[t]=0;var i=K.PriorityQueue.make();i.push(t,0);for(var s,u,c,l,a,w,h,y,A;!i.empty();){s=i.pop(),u=s.value,l=s.cost,a=n[u]||{};for(c in a)a.hasOwnProperty(c)&&(w=a[c],h=l+w,y=o[c],A=typeof o[c]>"u",(A||y>h)&&(o[c]=h,i.push(c,h),r[c]=u))}if(typeof e<"u"&&typeof o[e]>"u"){var T=["Could not find a path from ",t," to ",e,"."].join("");throw new Error(T)}return r},extract_shortest_path_from_predecessor_list:function(n,t){for(var e=[],r=t,o;r;)e.push(r),o=n[r],r=n[r];return e.reverse(),e},find_path:function(n,t,e){var r=K.single_source_shortest_paths(n,t,e);return K.extract_shortest_path_from_predecessor_list(r,e)},PriorityQueue:{make:function(n){var t=K.PriorityQueue,e={},r;n=n||{};for(r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e.queue=[],e.sorter=n.sorter||t.default_sorter,e},default_sorter:function(n,t){return n.cost-t.cost},push:function(n,t){var e={value:n,cost:t};this.queue.push(e),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};typeof mt<"u"&&(mt.exports=K)});var Be=g(F=>{var f=M(),we=se(),me=ce(),ye=ae(),Ee=ge(),J=gt(),v=I(),ve=de();function he(n){return unescape(encodeURIComponent(n)).length}function Y(n,t,e){let r=[],o;for(;(o=n.exec(e))!==null;)r.push({data:o[0],index:o.index,mode:t,length:o[0].length});return r}function Ce(n){let t=Y(J.NUMERIC,f.NUMERIC,n),e=Y(J.ALPHANUMERIC,f.ALPHANUMERIC,n),r,o;return v.isKanjiModeEnabled()?(r=Y(J.BYTE,f.BYTE,n),o=Y(J.KANJI,f.KANJI,n)):(r=Y(J.BYTE_KANJI,f.BYTE,n),o=[]),t.concat(e,r,o).sort(function(s,u){return s.index-u.index}).map(function(s){return{data:s.data,mode:s.mode,length:s.length}})}function yt(n,t){switch(t){case f.NUMERIC:return we.getBitsLength(n);case f.ALPHANUMERIC:return me.getBitsLength(n);case f.KANJI:return Ee.getBitsLength(n);case f.BYTE:return ye.getBitsLength(n)}}function tn(n){return n.reduce(function(t,e){let r=t.length-1>=0?t[t.length-1]:null;return r&&r.mode===e.mode?(t[t.length-1].data+=e.data,t):(t.push(e),t)},[])}function en(n){let t=[];for(let e=0;e{var et=I(),Et=j(),rn=qt(),on=Ft(),sn=kt(),un=Ht(),At=Kt(),Tt=ct(),cn=Gt(),tt=te(),ln=oe(),an=M(),Ct=Be();function fn(n,t){let e=n.size,r=un.getPositions(t);for(let o=0;o=0&&u<=6&&(c===0||c===6)||c>=0&&c<=6&&(u===0||u===6)||u>=2&&u<=4&&c>=2&&c<=4?n.set(i+u,s+c,!0,!0):n.set(i+u,s+c,!1,!0))}}function gn(n){let t=n.size;for(let e=8;e>u&1)===1,n.set(o,i,s,!0),n.set(i,o,s,!0)}function Bt(n,t,e){let r=n.size,o=ln.getEncodedBits(t,e),i,s;for(i=0;i<15;i++)s=(o>>i&1)===1,i<6?n.set(i,8,s,!0):i<8?n.set(i+1,8,s,!0):n.set(r-15+i,8,s,!0),i<8?n.set(8,r-i-1,s,!0):i<9?n.set(8,15-i-1+1,s,!0):n.set(8,15-i-1,s,!0);n.set(r-8,8,1,!0)}function pn(n,t){let e=n.size,r=-1,o=e-1,i=7,s=0;for(let u=e-1;u>0;u-=2)for(u===6&&u--;;){for(let c=0;c<2;c++)if(!n.isReserved(o,u-c)){let l=!1;s>>i&1)===1),n.set(o,u-c,l),i--,i===-1&&(s++,i=7)}if(o+=r,o<0||e<=o){o-=r,r=-r;break}}}function wn(n,t,e){let r=new rn;e.forEach(function(c){r.put(c.mode.bit,4),r.put(c.getLength(),an.getCharCountIndicator(c.mode,n)),c.write(r)});let o=et.getSymbolTotalCodewords(n),i=Tt.getTotalCodewordsCount(n,t),s=(o-i)*8;for(r.getLengthInBits()+4<=s&&r.put(0,4);r.getLengthInBits()%8!==0;)r.putBit(0);let u=(s-r.getLengthInBits())/8;for(let c=0;c=7&&hn(c,t),pn(c,s),isNaN(r)&&(r=At.getBestMask(c,Bt.bind(null,c,e))),At.applyMask(r,c),Bt(c,e,r),{modules:c,version:t,errorCorrectionLevel:e,maskPattern:r,segments:o}}Ae.create=function(t,e){if(typeof t>"u"||t==="")throw new Error("No input text");let r=Et.M,o,i;return typeof e<"u"&&(r=Et.from(e.errorCorrectionLevel,Et.M),o=tt.from(e.version),i=At.from(e.maskPattern),e.toSJISFunc&&et.setToSJISFunction(e.toSJISFunc)),yn(t,o,r,i)}});var It=g(L=>{function Ie(n){if(typeof n=="number"&&(n=n.toString()),typeof n!="string")throw new Error("Color should be defined as hex string");let t=n.slice().replace("#","").split("");if(t.length<3||t.length===5||t.length>8)throw new Error("Invalid hex color: "+n);(t.length===3||t.length===4)&&(t=Array.prototype.concat.apply([],t.map(function(r){return[r,r]}))),t.length===6&&t.push("F","F");let e=parseInt(t.join(""),16);return{r:e>>24&255,g:e>>16&255,b:e>>8&255,a:e&255,hex:"#"+t.slice(0,6).join("")}}L.getOptions=function(t){t||(t={}),t.color||(t.color={});let e=typeof t.margin>"u"||t.margin===null||t.margin<0?4:t.margin,r=t.width&&t.width>=21?t.width:void 0,o=t.scale||4;return{width:r,scale:r?4:o,margin:e,color:{dark:Ie(t.color.dark||"#000000ff"),light:Ie(t.color.light||"#ffffffff")},type:t.type,rendererOpts:t.rendererOpts||{}}};L.getScale=function(t,e){return e.width&&e.width>=t+e.margin*2?e.width/(t+e.margin*2):e.scale};L.getImageWidth=function(t,e){let r=L.getScale(t,e);return Math.floor((t+e.margin*2)*r)};L.qrToImageData=function(t,e,r){let o=e.modules.size,i=e.modules.data,s=L.getScale(o,r),u=Math.floor((o+r.margin*2)*s),c=r.margin*s,l=[r.color.light,r.color.dark];for(let a=0;a=c&&w>=c&&a{var Nt=It();function En(n,t,e){n.clearRect(0,0,t.width,t.height),t.style||(t.style={}),t.height=e,t.width=e,t.style.height=e+"px",t.style.width=e+"px"}function Cn(){try{return document.createElement("canvas")}catch{throw new Error("You need to specify a canvas element")}}nt.render=function(t,e,r){let o=r,i=e;typeof o>"u"&&(!e||!e.getContext)&&(o=e,e=void 0),e||(i=Cn()),o=Nt.getOptions(o);let s=Nt.getImageWidth(t.modules.size,o),u=i.getContext("2d"),c=u.createImageData(s,s);return Nt.qrToImageData(c.data,t,o),En(u,i,s),u.putImageData(c,0,0),i};nt.renderToDataURL=function(t,e,r){let o=r;typeof o>"u"&&(!e||!e.getContext)&&(o=e,e=void 0),o||(o={});let i=nt.render(t,e,o),s=o.type||"image/png",u=o.rendererOpts||{};return i.toDataURL(s,u.quality)}});var Pe=g(Se=>{var Bn=It();function Me(n,t){let e=n.a/255,r=t+'="'+n.hex+'"';return e<1?r+" "+t+'-opacity="'+e.toFixed(2).slice(1)+'"':r}function Mt(n,t,e){let r=n+t;return typeof e<"u"&&(r+=" "+e),r}function An(n,t,e){let r="",o=0,i=!1,s=0;for(let u=0;u0&&c>0&&n[u-1]||(r+=i?Mt("M",c+e,.5+l+e):Mt("m",o,0),o=0,i=!1),c+1':"",l="',a='viewBox="0 0 '+u+" "+u+'"',h=''+c+l+` +`;return typeof r=="function"&&r(null,h),h}});var Nn=g(O=>{var Tn=_t(),St=Te(),be=Ne(),In=Pe();function Pt(n,t,e,r,o){let i=[].slice.call(arguments,1),s=i.length,u=typeof i[s-1]=="function";if(!u&&!Tn())throw new Error("Callback required as last argument");if(u){if(s<2)throw new Error("Too few arguments provided");s===2?(o=e,e=t,t=r=void 0):s===3&&(t.getContext&&typeof o>"u"?(o=r,r=void 0):(o=r,r=e,e=t,t=void 0))}else{if(s<1)throw new Error("Too few arguments provided");return s===1?(e=t,t=r=void 0):s===2&&!t.getContext&&(r=e,e=t,t=void 0),new Promise(function(c,l){try{let a=St.create(e,r);c(n(a,t,r))}catch(a){l(a)}})}try{let c=St.create(e,r);o(null,n(c,t,r))}catch(c){o(c)}}O.create=St.create;O.toCanvas=Pt.bind(null,be.render);O.toDataURL=Pt.bind(null,be.renderToDataURL);O.toString=Pt.bind(null,function(n,t,e){return In.render(n,e)})});return Nn();})(); diff --git a/js/vendor/zxing.min.js b/js/vendor/zxing.min.js new file mode 100644 index 0000000..ccef114 --- /dev/null +++ b/js/vendor/zxing.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ZXing={})}(this,function(t){"use strict";var e,r,n=(e=function(t,r){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])},e(t,r)},function(t,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function n(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}),i=function(t){function e(e,r){var n,i,s,o=this.constructor,a=t.call(this,e,r)||this;return Object.defineProperty(a,"name",{value:o.name,enumerable:!1,configurable:!0}),n=a,i=o.prototype,(s=Object.setPrototypeOf)?s(n,i):n.__proto__=i,function(t,e){void 0===e&&(e=t.constructor);var r=Error.captureStackTrace;r&&r(t,e)}(a),a}return n(e,t),e}(Error);class s extends i{constructor(t=void 0){super(t),this.message=t}getKind(){return this.constructor.kind}}s.kind="Exception";class o extends s{}o.kind="ArgumentException";class a extends s{}a.kind="IllegalArgumentException";class h{constructor(t){if(this.binarizer=t,null===t)throw new a("Binarizer must be non-null.")}getWidth(){return this.binarizer.getWidth()}getHeight(){return this.binarizer.getHeight()}getBlackRow(t,e){return this.binarizer.getBlackRow(t,e)}getBlackMatrix(){return null!==this.matrix&&void 0!==this.matrix||(this.matrix=this.binarizer.getBlackMatrix()),this.matrix}isCropSupported(){return this.binarizer.getLuminanceSource().isCropSupported()}crop(t,e,r,n){const i=this.binarizer.getLuminanceSource().crop(t,e,r,n);return new h(this.binarizer.createBinarizer(i))}isRotateSupported(){return this.binarizer.getLuminanceSource().isRotateSupported()}rotateCounterClockwise(){const t=this.binarizer.getLuminanceSource().rotateCounterClockwise();return new h(this.binarizer.createBinarizer(t))}rotateCounterClockwise45(){const t=this.binarizer.getLuminanceSource().rotateCounterClockwise45();return new h(this.binarizer.createBinarizer(t))}toString(){try{return this.getBlackMatrix().toString()}catch(t){return""}}}class l extends s{static getChecksumInstance(){return new l}}l.kind="ChecksumException";class c{constructor(t){this.source=t}getLuminanceSource(){return this.source}getWidth(){return this.source.getWidth()}getHeight(){return this.source.getHeight()}}class d{static arraycopy(t,e,r,n,i){if(t===r&&er)throw new a("fromIndex("+e+") > toIndex("+r+")");if(e<0)throw new g(e);if(r>t)throw new g(r)}static asList(...t){return t}static create(t,e,r){return Array.from({length:t}).map(t=>Array.from({length:e}).fill(r))}static createInt32Array(t,e,r){return Array.from({length:t}).map(t=>Int32Array.from({length:e}).fill(r))}static equals(t,e){if(!t)return!1;if(!e)return!1;if(!t.length)return!1;if(!e.length)return!1;if(t.length!==e.length)return!1;for(let r=0,n=t.length;r>1,o=r(e,t[s]);if(o>0)n=s+1;else{if(!(o<0))return s;i=s-1}}return-n-1}static numberComparator(t,e){return t-e}}class w{static numberOfTrailingZeros(t){let e;if(0===t)return 32;let r=31;return e=t<<16,0!==e&&(r-=16,t=e),e=t<<8,0!==e&&(r-=8,t=e),e=t<<4,0!==e&&(r-=4,t=e),e=t<<2,0!==e&&(r-=2,t=e),r-(t<<1>>>31)}static numberOfLeadingZeros(t){if(0===t)return 32;let e=1;return t>>>16==0&&(e+=16,t<<=16),t>>>24==0&&(e+=8,t<<=8),t>>>28==0&&(e+=4,t<<=4),t>>>30==0&&(e+=2,t<<=2),e-=t>>>31,e}static toHexString(t){return t.toString(16)}static toBinaryString(t){return String(parseInt(String(t),2))}static bitCount(t){return t=(t=(858993459&(t-=t>>>1&1431655765))+(t>>>2&858993459))+(t>>>4)&252645135,t+=t>>>8,63&(t+=t>>>16)}static truncDivision(t,e){return Math.trunc(t/e)}static parseInt(t,e=void 0){return parseInt(t,e)}}w.MIN_VALUE_32_BITS=-2147483648,w.MAX_VALUE=Number.MAX_SAFE_INTEGER;class C{constructor(t,e){void 0===t?(this.size=0,this.bits=new Int32Array(1)):(this.size=t,this.bits=null==e?C.makeArray(t):e)}getSize(){return this.size}getSizeInBytes(){return Math.floor((this.size+7)/8)}ensureCapacity(t){if(t>32*this.bits.length){const e=C.makeArray(t);d.arraycopy(this.bits,0,e,0,this.bits.length),this.bits=e}}get(t){return!!(this.bits[Math.floor(t/32)]&1<<(31&t))}set(t){this.bits[Math.floor(t/32)]|=1<<(31&t)}flip(t){this.bits[Math.floor(t/32)]^=1<<(31&t)}getNextSet(t){const e=this.size;if(t>=e)return e;const r=this.bits;let n=Math.floor(t/32),i=r[n];i&=~((1<<(31&t))-1);const s=r.length;for(;0===i;){if(++n===s)return e;i=r[n]}const o=32*n+w.numberOfTrailingZeros(i);return o>e?e:o}getNextUnset(t){const e=this.size;if(t>=e)return e;const r=this.bits;let n=Math.floor(t/32),i=~r[n];i&=~((1<<(31&t))-1);const s=r.length;for(;0===i;){if(++n===s)return e;i=~r[n]}const o=32*n+w.numberOfTrailingZeros(i);return o>e?e:o}setBulk(t,e){this.bits[Math.floor(t/32)]=e}setRange(t,e){if(ethis.size)throw new a;if(e===t)return;e--;const r=Math.floor(t/32),n=Math.floor(e/32),i=this.bits;for(let s=r;s<=n;s++){const o=(2<<(sr?0:31&t));i[s]|=o}}clear(){const t=this.bits.length,e=this.bits;for(let r=0;rthis.size)throw new a;if(e===t)return!0;e--;const n=Math.floor(t/32),i=Math.floor(e/32),s=this.bits;for(let o=n;o<=i;o++){const a=(2<<(on?0:31&t))&4294967295;if((s[o]&a)!==(r?a:0))return!1}return!0}appendBit(t){this.ensureCapacity(this.size+1),t&&(this.bits[Math.floor(this.size/32)]|=1<<(31&this.size)),this.size++}appendBits(t,e){if(e<0||e>32)throw new a("Num bits must be between 0 and 32");this.ensureCapacity(this.size+e);for(let r=e;r>0;r--)this.appendBit(1==(t>>r-1&1))}appendBitArray(t){const e=t.size;this.ensureCapacity(this.size+e);for(let r=0;r>1&1431655765|(1431655765&r)<<1,r=r>>2&858993459|(858993459&r)<<2,r=r>>4&252645135|(252645135&r)<<4,r=r>>8&16711935|(16711935&r)<<8,r=r>>16&65535|(65535&r)<<16,t[e-i]=r}if(this.size!==32*r){const e=32*r-this.size;let n=t[0]>>>e;for(let i=1;i>>e}t[r-1]=n}this.bits=t}static makeArray(t){return new Int32Array(Math.floor((t+31)/32))}equals(t){if(!(t instanceof C))return!1;const e=t;return this.size===e.size&&f.equals(this.bits,e.bits)}hashCode(){return 31*this.size+f.hashCode(this.bits)}toString(){let t="";for(let e=0,r=this.size;e=900)throw new m("incorect value");const e=I.VALUES_TO_ECI.get(t);if(void 0===e)throw new m("incorect value");return e}static getCharacterSetECIByName(t){const e=I.NAME_TO_ECI.get(t);if(void 0===e)throw new m("incorect value");return e}equals(t){if(!(t instanceof I))return!1;const e=t;return this.getName()===e.getName()}}I.VALUE_IDENTIFIER_TO_ECI=new Map,I.VALUES_TO_ECI=new Map,I.NAME_TO_ECI=new Map,I.Cp437=new I(A.Cp437,Int32Array.from([0,2]),"Cp437"),I.ISO8859_1=new I(A.ISO8859_1,Int32Array.from([1,3]),"ISO-8859-1","ISO88591","ISO8859_1"),I.ISO8859_2=new I(A.ISO8859_2,4,"ISO-8859-2","ISO88592","ISO8859_2"),I.ISO8859_3=new I(A.ISO8859_3,5,"ISO-8859-3","ISO88593","ISO8859_3"),I.ISO8859_4=new I(A.ISO8859_4,6,"ISO-8859-4","ISO88594","ISO8859_4"),I.ISO8859_5=new I(A.ISO8859_5,7,"ISO-8859-5","ISO88595","ISO8859_5"),I.ISO8859_6=new I(A.ISO8859_6,8,"ISO-8859-6","ISO88596","ISO8859_6"),I.ISO8859_7=new I(A.ISO8859_7,9,"ISO-8859-7","ISO88597","ISO8859_7"),I.ISO8859_8=new I(A.ISO8859_8,10,"ISO-8859-8","ISO88598","ISO8859_8"),I.ISO8859_9=new I(A.ISO8859_9,11,"ISO-8859-9","ISO88599","ISO8859_9"),I.ISO8859_10=new I(A.ISO8859_10,12,"ISO-8859-10","ISO885910","ISO8859_10"),I.ISO8859_11=new I(A.ISO8859_11,13,"ISO-8859-11","ISO885911","ISO8859_11"),I.ISO8859_13=new I(A.ISO8859_13,15,"ISO-8859-13","ISO885913","ISO8859_13"),I.ISO8859_14=new I(A.ISO8859_14,16,"ISO-8859-14","ISO885914","ISO8859_14"),I.ISO8859_15=new I(A.ISO8859_15,17,"ISO-8859-15","ISO885915","ISO8859_15"),I.ISO8859_16=new I(A.ISO8859_16,18,"ISO-8859-16","ISO885916","ISO8859_16"),I.SJIS=new I(A.SJIS,20,"SJIS","Shift_JIS"),I.Cp1250=new I(A.Cp1250,21,"Cp1250","windows-1250"),I.Cp1251=new I(A.Cp1251,22,"Cp1251","windows-1251"),I.Cp1252=new I(A.Cp1252,23,"Cp1252","windows-1252"),I.Cp1256=new I(A.Cp1256,24,"Cp1256","windows-1256"),I.UnicodeBigUnmarked=new I(A.UnicodeBigUnmarked,25,"UnicodeBigUnmarked","UTF-16BE","UnicodeBig"),I.UTF8=new I(A.UTF8,26,"UTF8","UTF-8"),I.ASCII=new I(A.ASCII,Int32Array.from([27,170]),"ASCII","US-ASCII"),I.Big5=new I(A.Big5,28,"Big5"),I.GB18030=new I(A.GB18030,29,"GB18030","GB2312","EUC_CN","GBK"),I.EUC_KR=new I(A.EUC_KR,30,"EUC_KR","EUC-KR");class _ extends s{}_.kind="UnsupportedOperationException";class S{static decode(t,e){const r=this.encodingName(e);return this.customDecoder?this.customDecoder(t,r):"undefined"==typeof TextDecoder||this.shouldDecodeOnFallback(r)?this.decodeFallback(t,r):new TextDecoder(r).decode(t)}static shouldDecodeOnFallback(t){return!1}static encode(t,e){const r=this.encodingName(e);return this.customEncoder?this.customEncoder(t,r):"undefined"==typeof TextEncoder?this.encodeFallback(t):(new TextEncoder).encode(t)}static isBrowser(){return"undefined"!=typeof window&&"[object Window]"==={}.toString.call(window)}static encodingName(t){return"string"==typeof t?t:t.getName()}static encodingCharacterSet(t){return t instanceof I?t:I.getCharacterSetECIByName(t)}static decodeFallback(t,e){const r=this.encodingCharacterSet(e);if(S.isDecodeFallbackSupported(r)){let e="";for(let r=0,n=t.length;r3&&239===t[0]&&187===t[1]&&191===t[2];for(let e=0;e0?128&r?o--:s=!1:128&r&&(64&r?(o++,32&r?(o++,16&r?(o++,8&r?s=!1:l++):h++):a++):s=!1)),n&&(r>127&&r<160?n=!1:r>159&&(r<192||215===r||247===r)&&C++),i&&(c>0?r<64||127===r||r>252?i=!1:c--:128===r||160===r||r>239?i=!1:r>160&&r<224?(d++,g=0,u++,u>f&&(f=u)):r>127?(c++,u=0,g++,g>w&&(w=g)):(u=0,g=0))}return s&&o>0&&(s=!1),i&&c>0&&(i=!1),s&&(A||a+h+l>0)?p.UTF8:i&&(p.ASSUME_SHIFT_JIS||f>=3||w>=3)?p.SHIFT_JIS:n&&i?2===f&&2===d||10*C>=r?p.SHIFT_JIS:p.ISO88591:n?p.ISO88591:i?p.SHIFT_JIS:s?p.UTF8:p.PLATFORM_DEFAULT_ENCODING}static format(t,...e){let r=-1;return t.replace(/%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g,function(t,n,i,s,o,a){if("%%"===t)return"%";if(void 0===e[++r])return;t=s?parseInt(s.substr(1)):void 0;let h,l=o?parseInt(o.substr(1)):void 0;switch(a){case"s":h=e[r];break;case"c":h=e[r][0];break;case"f":h=parseFloat(e[r]).toFixed(t);break;case"p":h=parseFloat(e[r]).toPrecision(t);break;case"e":h=parseFloat(e[r]).toExponential(t);break;case"x":h=parseInt(e[r]).toString(l||16);break;case"d":h=parseFloat(parseInt(e[r],l||10).toPrecision(t)).toFixed(0)}h="object"==typeof h?JSON.stringify(h):(+h).toString(l);let c=parseInt(i),d=i&&i[0]+""=="0"?"0":" ";for(;h.length>5),this.rowSize=r,null==n&&(this.bits=new Int32Array(this.rowSize*this.height))}static parseFromBooleanArray(t){const e=t.length,r=t[0].length,n=new R(r,e);for(let i=0;is){if(-1===o)o=i-s;else if(i-s!==o)throw new a("row lengths do not match");s=i,h++}l++}else if(t.substring(l,l+e.length)===e)l+=e.length,n[i]=!0,i++;else{if(t.substring(l,l+r.length)!==r)throw new a("illegal character encountered: "+t.substring(l));l+=r.length,n[i]=!1,i++}if(i>s){if(-1===o)o=i-s;else if(i-s!==o)throw new a("row lengths do not match");h++}const c=new R(o,h);for(let t=0;t>5);return!!(this.bits[r]>>>(31&t)&1)}set(t,e){const r=e*this.rowSize+(t>>5);this.bits[r]|=1<<(31&t)&4294967295}unset(t,e){const r=e*this.rowSize+(t>>5);this.bits[r]&=~(1<<(31&t)&4294967295)}flip(t,e){const r=e*this.rowSize+(t>>5);this.bits[r]^=1<<(31&t)&4294967295}xor(t){if(this.width!==t.getWidth()||this.height!==t.getHeight()||this.rowSize!==t.getRowSize())throw new a("input matrix dimensions do not match");const e=new C(1+(this.width>>5)),r=this.rowSize,n=this.bits;for(let i=0,s=this.height;ithis.height||i>this.width)throw new a("The region must fit inside the matrix");const o=this.rowSize,h=this.bits;for(let r=e;r>5)]|=1<<(31&r)&4294967295}}getRow(t,e){null==e||e.getSize()a&&(a=t),32*eo){let t=31;for(;h>>>t===0;)t--;32*e+t>o&&(o=32*e+t)}}}return o=0&&0===e[r];)r--;if(r<0)return null;const n=Math.floor(r/t);let i=32*Math.floor(r%t);const s=e[r];let o=31;for(;s>>>o===0;)o--;return i+=o,Int32Array.from([i,n])}getWidth(){return this.width}getHeight(){return this.height}getRowSize(){return this.rowSize}equals(t){if(!(t instanceof R))return!1;const e=t;return this.width===e.width&&this.height===e.height&&this.rowSize===e.rowSize&&f.equals(this.bits,e.bits)}hashCode(){let t=this.width;return t=31*t+this.width,t=31*t+this.height,t=31*t+this.rowSize,t=31*t+f.hashCode(this.bits),t}toString(t="X ",e=" ",r="\n"){return this.buildToString(t,e,r)}buildToString(t,e,r){let n=new T;for(let i=0,s=this.height;i>D.LUMINANCE_SHIFT]++;const o=D.estimateBlackPoint(s);if(n<3)for(let t=0;t>D.LUMINANCE_SHIFT]++}}const s=D.estimateBlackPoint(i),o=t.getMatrix();for(let t=0;ti&&(n=s,i=t[s]),t[s]>r&&(r=t[s]);let s=0,o=0;for(let r=0;ro&&(s=r,o=i)}if(n>s){const t=n;n=s,s=t}if(s-n<=e/16)throw new N;let a=s-1,h=-1;for(let e=s-1;e>n;e--){const i=e-n,o=i*i*(s-e)*(r-t[e]);o>h&&(a=e,h=o)}return a<=M.MINIMUM_DIMENSION&&r>=M.MINIMUM_DIMENSION){const n=t.getMatrix();let i=e>>M.BLOCK_SIZE_POWER;0!==(e&M.BLOCK_SIZE_MASK)&&i++;let s=r>>M.BLOCK_SIZE_POWER;0!==(r&M.BLOCK_SIZE_MASK)&&s++;const o=M.calculateBlackPoints(n,i,s,e,r),a=new R(e,r);M.calculateThresholdForBlock(n,i,s,e,r,o,a),this.matrix=a}else this.matrix=super.getBlackMatrix();return this.matrix}createBinarizer(t){return new M(t)}static calculateThresholdForBlock(t,e,r,n,i,s,o){const a=i-M.BLOCK_SIZE,h=n-M.BLOCK_SIZE;for(let i=0;ia&&(l=a);const c=M.cap(i,2,r-3);for(let r=0;rh&&(i=h);const a=M.cap(r,2,e-3);let d=0;for(let t=-2;t<=2;t++){const e=s[c+t];d+=e[a-2]+e[a-1]+e[a]+e[a+1]+e[a+2]}const u=d/25;M.thresholdBlock(t,i,l,u,n,o)}}}static cap(t,e,r){return tr?r:t}static thresholdBlock(t,e,r,n,i,s){for(let o=0,a=r*i+e;os&&(r=s);for(let s=0;so&&(e=o);let h=0,l=255,c=0;for(let i=0,s=r*n+e;ic&&(c=r)}if(c-l>M.MIN_DYNAMIC_RANGE)for(i++,s+=n;i>2*M.BLOCK_SIZE_POWER;if(c-l<=M.MIN_DYNAMIC_RANGE&&(d=l/2,i>0&&s>0)){const t=(a[i-1][s]+2*a[i][s-1]+a[i-1][s-1])/4;l=s?i:new Uint8ClampedArray(s);b.FRAME_INDEX=!b.FRAME_INDEX;const a=!b.FRAME_INDEX&&n?255:0;for(let e=0,r=0,n=t.length;e>10}o[r]=n^a}return o}getRow(t,e){if(t<0||t>=this.getHeight())throw new a("Requested row is outside the image: "+t);const r=this.getWidth(),n=t*r;return null===e?e=this.buffer.slice(n,n+r):(e.lengthnew B(t.deviceId,t.label))})}findDeviceById(t){return P(this,void 0,void 0,function*(){const e=yield this.listVideoInputDevices();return e?e.find(e=>e.deviceId===t):null})}decodeFromInputVideoDevice(t,e){return P(this,void 0,void 0,function*(){return yield this.decodeOnceFromVideoDevice(t,e)})}decodeOnceFromVideoDevice(t,e){return P(this,void 0,void 0,function*(){let r;this.reset(),r=t?{deviceId:{exact:t}}:{facingMode:"environment"};const n={video:r};return yield this.decodeOnceFromConstraints(n,e)})}decodeOnceFromConstraints(t,e){return P(this,void 0,void 0,function*(){const r=yield navigator.mediaDevices.getUserMedia(t);return yield this.decodeOnceFromStream(r,e)})}decodeOnceFromStream(t,e){return P(this,void 0,void 0,function*(){this.reset();const r=yield this.attachStreamToVideo(t,e);return yield this.decodeOnce(r)})}decodeFromInputVideoDeviceContinuously(t,e,r){return P(this,void 0,void 0,function*(){return yield this.decodeFromVideoDevice(t,e,r)})}decodeFromVideoDevice(t,e,r){return P(this,void 0,void 0,function*(){let n;n=t?{deviceId:{exact:t}}:{facingMode:"environment"};const i={video:n};return yield this.decodeFromConstraints(i,e,r)})}decodeFromConstraints(t,e,r){return P(this,void 0,void 0,function*(){const n=yield navigator.mediaDevices.getUserMedia(t);return yield this.decodeFromStream(n,e,r)})}decodeFromStream(t,e,r){return P(this,void 0,void 0,function*(){this.reset();const n=yield this.attachStreamToVideo(t,e);return yield this.decodeContinuously(n,r)})}stopAsyncDecode(){this._stopAsyncDecode=!0}stopContinuousDecode(){this._stopContinuousDecode=!0}attachStreamToVideo(t,e){return P(this,void 0,void 0,function*(){const r=this.prepareVideoElement(e);return this.addVideoSource(r,t),this.videoElement=r,this.stream=t,yield this.playVideoOnLoadAsync(r),r})}playVideoOnLoadAsync(t){return new Promise((e,r)=>this.playVideoOnLoad(t,()=>e()))}playVideoOnLoad(t,e){this.videoEndedListener=()=>this.stopStreams(),this.videoCanPlayListener=()=>this.tryPlayVideo(t),t.addEventListener("ended",this.videoEndedListener),t.addEventListener("canplay",this.videoCanPlayListener),t.addEventListener("playing",e),this.tryPlayVideo(t)}isVideoPlaying(t){return t.currentTime>0&&!t.paused&&!t.ended&&t.readyState>2}tryPlayVideo(t){return P(this,void 0,void 0,function*(){if(this.isVideoPlaying(t))console.warn("Trying to play video that is already playing.");else try{yield t.play()}catch(t){console.warn("It was not possible to play the video.")}})}getMediaElement(t,e){const r=document.getElementById(t);if(!r)throw new o(`element with id '${t}' not found`);if(r.nodeName.toLowerCase()!==e.toLowerCase())throw new o(`element with id '${t}' must be an ${e} element`);return r}decodeFromImage(t,e){if(!t&&!e)throw new o("either imageElement with a src set or an url must be provided");return e&&!t?this.decodeFromImageUrl(e):this.decodeFromImageElement(t)}decodeFromVideo(t,e){if(!t&&!e)throw new o("Either an element with a src set or an URL must be provided");return e&&!t?this.decodeFromVideoUrl(e):this.decodeFromVideoElement(t)}decodeFromVideoContinuously(t,e,r){if(void 0===t&&void 0===e)throw new o("Either an element with a src set or an URL must be provided");return e&&!t?this.decodeFromVideoUrlContinuously(e,r):this.decodeFromVideoElementContinuously(t,r)}decodeFromImageElement(t){if(!t)throw new o("An image element must be provided.");this.reset();const e=this.prepareImageElement(t);let r;return this.imageElement=e,r=this.isImageLoaded(e)?this.decodeOnce(e,!1,!0):this._decodeOnLoadImage(e),r}decodeFromVideoElement(t){const e=this._decodeFromVideoElementSetup(t);return this._decodeOnLoadVideo(e)}decodeFromVideoElementContinuously(t,e){const r=this._decodeFromVideoElementSetup(t);return this._decodeOnLoadVideoContinuously(r,e)}_decodeFromVideoElementSetup(t){if(!t)throw new o("A video element must be provided.");this.reset();const e=this.prepareVideoElement(t);return this.videoElement=e,e}decodeFromImageUrl(t){if(!t)throw new o("An URL must be provided.");this.reset();const e=this.prepareImageElement();this.imageElement=e;const r=this._decodeOnLoadImage(e);return e.src=t,r}decodeFromVideoUrl(t){if(!t)throw new o("An URL must be provided.");this.reset();const e=this.prepareVideoElement(),r=this.decodeFromVideoElement(e);return e.src=t,r}decodeFromVideoUrlContinuously(t,e){if(!t)throw new o("An URL must be provided.");this.reset();const r=this.prepareVideoElement(),n=this.decodeFromVideoElementContinuously(r,e);return r.src=t,n}_decodeOnLoadImage(t){return new Promise((e,r)=>{this.imageLoadedListener=()=>this.decodeOnce(t,!1,!0).then(e,r),t.addEventListener("load",this.imageLoadedListener)})}_decodeOnLoadVideo(t){return P(this,void 0,void 0,function*(){return yield this.playVideoOnLoadAsync(t),yield this.decodeOnce(t)})}_decodeOnLoadVideoContinuously(t,e){return P(this,void 0,void 0,function*(){yield this.playVideoOnLoadAsync(t),this.decodeContinuously(t,e)})}isImageLoaded(t){return!!t.complete&&0!==t.naturalWidth}prepareImageElement(t){let e;return void 0===t&&(e=document.createElement("img"),e.width=200,e.height=200),"string"==typeof t&&(e=this.getMediaElement(t,"img")),t instanceof HTMLImageElement&&(e=t),e}prepareVideoElement(t){let e;return t||"undefined"==typeof document||(e=document.createElement("video"),e.width=200,e.height=200),"string"==typeof t&&(e=this.getMediaElement(t,"video")),t instanceof HTMLVideoElement&&(e=t),e.setAttribute("autoplay","true"),e.setAttribute("muted","true"),e.setAttribute("playsinline","true"),e}decodeOnce(t,e=!0,r=!0){this._stopAsyncDecode=!1;const n=(i,s)=>{if(this._stopAsyncDecode)return s(new N("Video stream has ended before any code could be detected.")),void(this._stopAsyncDecode=void 0);try{i(this.decode(t))}catch(t){if(e&&t instanceof N||(t instanceof l||t instanceof m)&&r)return setTimeout(n,this._timeBetweenDecodingAttempts,i,s);s(t)}};return new Promise((t,e)=>n(t,e))}decodeContinuously(t,e){this._stopContinuousDecode=!1;const r=()=>{if(this._stopContinuousDecode)this._stopContinuousDecode=void 0;else try{const n=this.decode(t);e(n,null),setTimeout(r,this.timeBetweenScansMillis)}catch(t){e(null,t);t instanceof l||t instanceof m||t instanceof N?setTimeout(r,this._timeBetweenDecodingAttempts):console.error("BrowserCodeReader: unexpected error during decode, stopping scan loop:",t)}};r()}decode(t){const e=this.createBinaryBitmap(t);try{return this.decodeBitmap(e)}catch(e){if(e instanceof N){const e=this.getCaptureCanvas(t),r=new b(e,!1),n=new D(r),i=new h(n);return this.decodeBitmap(i)}throw e}}createBinaryBitmap(t){this.getCaptureCanvasContext(t);let e=!1;t instanceof HTMLVideoElement?(this.drawFrameOnCanvas(t),e=!0):this.drawImageOnCanvas(t);const r=this.getCaptureCanvas(t),n=new b(r,e,this._grayscaleBuffer);this._grayscaleBuffer=n.getMatrix();const i=new M(n);return new h(i)}getCaptureCanvasContext(t){if(!this.captureCanvasContext){const e=this.getCaptureCanvas(t);let r;try{r=e.getContext("2d",{willReadFrequently:!0})}catch(t){r=e.getContext("2d")}this.captureCanvasContext=r}return this.captureCanvasContext}getCaptureCanvas(t){if(!this.captureCanvas){const e=this.createCaptureCanvas(t);this.captureCanvas=e}return this.captureCanvas}drawFrameOnCanvas(t,e={sx:0,sy:0,sWidth:t.videoWidth,sHeight:t.videoHeight,dx:0,dy:0,dWidth:t.videoWidth,dHeight:t.videoHeight},r=this.captureCanvasContext){r.drawImage(t,e.sx,e.sy,e.sWidth,e.sHeight,e.dx,e.dy,e.dWidth,e.dHeight)}drawImageOnCanvas(t,e={sx:0,sy:0,sWidth:t.naturalWidth,sHeight:t.naturalHeight,dx:0,dy:0,dWidth:t.naturalWidth,dHeight:t.naturalHeight},r=this.captureCanvasContext){r.drawImage(t,e.sx,e.sy,e.sWidth,e.sHeight,e.dx,e.dy,e.dWidth,e.dHeight)}decodeBitmap(t){try{return this.reader.decode(t,this._hints)}finally{this.reader.reset()}}createCaptureCanvas(t){if("undefined"==typeof document)return this._destroyCaptureCanvas(),null;const e=document.createElement("canvas");let r,n;return void 0!==t&&(t instanceof HTMLVideoElement?(r=t.videoWidth,n=t.videoHeight):t instanceof HTMLImageElement&&(r=t.naturalWidth||t.width,n=t.naturalHeight||t.height)),e.style.width=r+"px",e.style.height=n+"px",e.width=r,e.height=n,e}stopStreams(){this.stream&&(this.stream.getVideoTracks().forEach(t=>t.stop()),this.stream=void 0),!1===this._stopAsyncDecode&&this.stopAsyncDecode(),!1===this._stopContinuousDecode&&this.stopContinuousDecode()}reset(){this.stopStreams(),this._destroyVideoElement(),this._destroyImageElement(),this._destroyCaptureCanvas()}_destroyVideoElement(){this.videoElement&&(void 0!==this.videoEndedListener&&this.videoElement.removeEventListener("ended",this.videoEndedListener),void 0!==this.videoPlayingEventListener&&this.videoElement.removeEventListener("playing",this.videoPlayingEventListener),void 0!==this.videoCanPlayListener&&this.videoElement.removeEventListener("loadedmetadata",this.videoCanPlayListener),this.cleanVideoSource(this.videoElement),this.videoElement=void 0)}_destroyImageElement(){this.imageElement&&(void 0!==this.imageLoadedListener&&this.imageElement.removeEventListener("load",this.imageLoadedListener),this.imageElement.src=void 0,this.imageElement.removeAttribute("src"),this.imageElement=void 0)}_destroyCaptureCanvas(){this.captureCanvasContext=void 0,this.captureCanvas=void 0}addVideoSource(t,e){try{t.srcObject=e}catch(r){t.src=URL.createObjectURL(e)}}cleanVideoSource(t){try{t.srcObject=null}catch(e){t.src=""}this.videoElement.removeAttribute("src")}}let F=class{constructor(t,e,r=(null==e?0:8*e.length),n,i,s=d.currentTimeMillis()){this.text=t,this.rawBytes=e,this.numBits=r,this.resultPoints=n,this.format=i,this.timestamp=s,this.text=t,this.rawBytes=e,this.numBits=null==r?null==e?0:8*e.length:r,this.resultPoints=n,this.format=i,this.resultMetadata=null,this.timestamp=null==s?d.currentTimeMillis():s}getText(){return this.text}getRawBytes(){return this.rawBytes}getNumBits(){return this.numBits}getResultPoints(){return this.resultPoints}getBarcodeFormat(){return this.format}getResultMetadata(){return this.resultMetadata}putMetadata(t,e){null===this.resultMetadata&&(this.resultMetadata=new Map),this.resultMetadata.set(t,e)}putAllMetadata(t){null!==t&&(null===this.resultMetadata?this.resultMetadata=t:this.resultMetadata=new Map(t))}addResultPoints(t){const e=this.resultPoints;if(null===e)this.resultPoints=t;else if(null!==t&&t.length>0){const r=new Array(e.length+t.length);d.arraycopy(e,0,r,0,e.length),d.arraycopy(t,0,r,e.length,t.length),this.resultPoints=r}}getTimestamp(){return this.timestamp}toString(){return this.text}};var v;!function(t){t[t.AZTEC=0]="AZTEC",t[t.CODABAR=1]="CODABAR",t[t.CODE_39=2]="CODE_39",t[t.CODE_93=3]="CODE_93",t[t.CODE_128=4]="CODE_128",t[t.DATA_MATRIX=5]="DATA_MATRIX",t[t.EAN_8=6]="EAN_8",t[t.EAN_13=7]="EAN_13",t[t.ITF=8]="ITF",t[t.MAXICODE=9]="MAXICODE",t[t.PDF_417=10]="PDF_417",t[t.QR_CODE=11]="QR_CODE",t[t.RSS_14=12]="RSS_14",t[t.RSS_EXPANDED=13]="RSS_EXPANDED",t[t.UPC_A=14]="UPC_A",t[t.UPC_E=15]="UPC_E",t[t.UPC_EAN_EXTENSION=16]="UPC_EAN_EXTENSION",t[t.MICRO_QR_CODE=17]="MICRO_QR_CODE"}(v||(v={}));var k,x=v;!function(t){t[t.OTHER=0]="OTHER",t[t.ORIENTATION=1]="ORIENTATION",t[t.BYTE_SEGMENTS=2]="BYTE_SEGMENTS",t[t.ERROR_CORRECTION_LEVEL=3]="ERROR_CORRECTION_LEVEL",t[t.ISSUE_NUMBER=4]="ISSUE_NUMBER",t[t.SUGGESTED_PRICE=5]="SUGGESTED_PRICE",t[t.POSSIBLE_COUNTRY=6]="POSSIBLE_COUNTRY",t[t.UPC_EAN_EXTENSION=7]="UPC_EAN_EXTENSION",t[t.PDF417_EXTRA_METADATA=8]="PDF417_EXTRA_METADATA",t[t.STRUCTURED_APPEND_SEQUENCE=9]="STRUCTURED_APPEND_SEQUENCE",t[t.STRUCTURED_APPEND_PARITY=10]="STRUCTURED_APPEND_PARITY",t[t.ERRORS_CORRECTED=11]="ERRORS_CORRECTED"}(k||(k={}));var H,U=k;class V{constructor(t,e,r,n,i=-1,s=-1){this.rawBytes=t,this.text=e,this.byteSegments=r,this.ecLevel=n,this.structuredAppendSequenceNumber=i,this.structuredAppendParity=s,this.numBits=null==t?0:8*t.length}getRawBytes(){return this.rawBytes}getNumBits(){return this.numBits}setNumBits(t){this.numBits=t}getText(){return this.text}getByteSegments(){return this.byteSegments}getECLevel(){return this.ecLevel}getErrorsCorrected(){return this.errorsCorrected}setErrorsCorrected(t){this.errorsCorrected=t}getErasures(){return this.erasures}setErasures(t){this.erasures=t}getOther(){return this.other}setOther(t){this.other=t}hasStructuredAppend(){return this.structuredAppendParity>=0&&this.structuredAppendSequenceNumber>=0}getStructuredAppendParity(){return this.structuredAppendParity}getStructuredAppendSequenceNumber(){return this.structuredAppendSequenceNumber}}class X{exp(t){return this.expTable[t]}log(t){if(0===t)throw new a;return this.logTable[t]}static addOrSubtract(t,e){return t^e}}class W{constructor(t,e){if(0===e.length)throw new a;this.field=t;const r=e.length;if(r>1&&0===e[0]){let t=1;for(;tr.length){const t=e;e=r,r=t}let n=new Int32Array(r.length);const i=r.length-e.length;d.arraycopy(r,0,n,0,i);for(let t=i;t=t.getDegree()&&!n.isZero();){const i=n.getDegree()-t.getDegree(),o=e.multiply(n.getCoefficient(n.getDegree()),s),a=t.multiplyByMonomial(i,o),h=e.buildMonomial(i,o);r=r.addOrSubtract(h),n=n.addOrSubtract(a)}return[r,n]}toString(){let t="";for(let e=this.getDegree();e>=0;e--){let r=this.getCoefficient(e);if(0!==r){if(r<0?(t+=" - ",r=-r):t.length>0&&(t+=" + "),0===e||1!==r){const e=this.field.log(r);0===e?t+="1":1===e?t+="a":(t+="a^",t+=e)}0!==e&&(1===e?t+="x":(t+="x^",t+=e))}}return t}}class G extends s{}G.kind="ArithmeticException";class z extends X{constructor(t,e,r){super(),this.primitive=t,this.size=e,this.generatorBase=r;const n=new Int32Array(e);let i=1;for(let r=0;r=e&&(i^=t,i&=e-1);this.expTable=n;const s=new Int32Array(e);for(let t=0;t=(r/2|0);){let t=i,e=o;if(i=s,o=a,i.isZero())throw new Y("r_{i-1} was zero");s=t;let r=n.getZero();const h=i.getCoefficient(i.getDegree()),l=n.inverse(h);for(;s.getDegree()>=i.getDegree()&&!s.isZero();){const t=s.getDegree()-i.getDegree(),e=n.multiply(s.getCoefficient(s.getDegree()),l);r=r.addOrSubtract(n.buildMonomial(t,e)),s=s.addOrSubtract(i.multiplyByMonomial(t,e))}if(a=r.multiply(o).addOrSubtract(e),s.getDegree()>=i.getDegree())throw new Z("Division algorithm failed to reduce polynomial?")}const h=a.getCoefficient(0);if(0===h)throw new Y("sigmaTilde(0) was zero");const l=n.inverse(h);return[a.multiplyScalar(l),s.multiplyScalar(l)]}findErrorLocations(t){const e=t.getDegree();if(1===e)return Int32Array.from([t.getCoefficient(1)]);const r=new Int32Array(e);let n=0;const i=this.field;for(let s=1;s1,d,d+n-1),d+=n-1;else for(let t=n-1;t>=0;--t)c[d++]=!!(e&1<=8?t.readCode(e,r,8):t.readCode(e,r,n)<<8-n}static convertBoolArrayToByteArray(e){let r=new Uint8Array((e.length+7)/8);for(let n=0;n","?","[","]","{","}","CTRL_UL"],Q.DIGIT_TABLE=["CTRL_PS"," ","0","1","2","3","4","5","6","7","8","9",",",".","CTRL_UL","CTRL_US"];class q{constructor(){}static round(t){return isNaN(t)?0:t<=Number.MIN_SAFE_INTEGER?Number.MIN_SAFE_INTEGER:t>=Number.MAX_SAFE_INTEGER?Number.MAX_SAFE_INTEGER:t+(t<0?-.5:.5)|0}static distance(t,e,r,n){const i=t-r,s=e-n;return Math.sqrt(i*i+s*s)}static sum(t){let e=0;for(let r=0,n=t.length;r!==n;r++){e+=t[r]}return e}}class j{static floatToIntBits(t){return t}}j.MAX_VALUE=Number.MAX_SAFE_INTEGER;class J{constructor(t,e){this.x=t,this.y=e}getX(){return this.x}getY(){return this.y}equals(t){if(t instanceof J){const e=t;return this.x===e.x&&this.y===e.y}return!1}hashCode(){return 31*j.floatToIntBits(this.x)+j.floatToIntBits(this.y)}toString(){return"("+this.x+","+this.y+")"}static orderBestPatterns(t){const e=this.distance(t[0],t[1]),r=this.distance(t[1],t[2]),n=this.distance(t[0],t[2]);let i,s,o;if(r>=e&&r>=n?(s=t[0],i=t[1],o=t[2]):n>=r&&n>=e?(s=t[1],i=t[0],o=t[2]):(s=t[2],i=t[0],o=t[1]),this.crossProductZ(i,s,o)<0){const t=i;i=o,o=t}t[0]=i,t[1]=s,t[2]=o}static distance(t,e){return q.distance(t.x,t.y,e.x,e.y)}static crossProductZ(t,e,r){const n=e.x,i=e.y;return(r.x-n)*(t.y-i)-(r.y-i)*(t.x-n)}}class ${constructor(t,e){this.bits=t,this.points=e}getBits(){return this.bits}getPoints(){return this.points}}class tt extends ${constructor(t,e,r,n,i){super(t,e),this.compact=r,this.nbDatablocks=n,this.nbLayers=i}getNbLayers(){return this.nbLayers}getNbDatablocks(){return this.nbDatablocks}isCompact(){return this.compact}}class et{constructor(t,e,r,n){this.image=t,this.height=t.getHeight(),this.width=t.getWidth(),null==e&&(e=et.INIT_SIZE),null==r&&(r=t.getWidth()/2|0),null==n&&(n=t.getHeight()/2|0);const i=e/2|0;if(this.leftInit=r-i,this.rightInit=r+i,this.upInit=n-i,this.downInit=n+i,this.upInit<0||this.leftInit<0||this.downInit>=this.height||this.rightInit>=this.width)throw new N}detect(){let t=this.leftInit,e=this.rightInit,r=this.upInit,n=this.downInit,i=!1,s=!0,o=!1,a=!1,h=!1,l=!1,c=!1;const d=this.width,u=this.height;for(;s;){s=!1;let g=!0;for(;(g||!a)&&e=d){i=!0;break}let f=!0;for(;(f||!h)&&n=u){i=!0;break}let w=!0;for(;(w||!l)&&t>=0;)w=this.containsBlackPoint(r,n,t,!1),w?(t--,s=!0,l=!0):l||t--;if(t<0){i=!0;break}let C=!0;for(;(C||!c)&&r>=0;)C=this.containsBlackPoint(t,e,r,!0),C?(r--,s=!0,c=!0):c||r--;if(r<0){i=!0;break}s&&(o=!0)}if(!i&&o){const i=e-t;let s=null;for(let e=1;null===s&&er||o<-1||o>n)throw new N;i=!1,-1===s?(e[t]=0,i=!0):s===r&&(e[t]=r-1,i=!0),-1===o?(e[t+1]=0,i=!0):o===n&&(e[t+1]=n-1,i=!0)}i=!0;for(let t=e.length-2;t>=0&&i;t-=2){const s=Math.floor(e[t]),o=Math.floor(e[t+1]);if(s<-1||s>r||o<-1||o>n)throw new N;i=!1,-1===s?(e[t]=0,i=!0):s===r&&(e[t]=r-1,i=!0),-1===o?(e[t+1]=0,i=!0):o===n&&(e[t+1]=n-1,i=!0)}}}class nt{constructor(t,e,r,n,i,s,o,a,h){this.a11=t,this.a21=e,this.a31=r,this.a12=n,this.a22=i,this.a32=s,this.a13=o,this.a23=a,this.a33=h}static quadrilateralToQuadrilateral(t,e,r,n,i,s,o,a,h,l,c,d,u,g,f,w){const C=nt.quadrilateralToSquare(t,e,r,n,i,s,o,a);return nt.squareToQuadrilateral(h,l,c,d,u,g,f,w).times(C)}transformPoints(t){const e=t.length,r=this.a11,n=this.a12,i=this.a13,s=this.a21,o=this.a22,a=this.a23,h=this.a31,l=this.a32,c=this.a33;for(let d=0;d>1&127):(n<<=10,n+=(e>>2&992)+(e>>1&31))}let i=this.getCorrectedParameterData(n,this.compact);this.compact?(this.nbLayers=1+(i>>6),this.nbDataBlocks=1+(63&i)):(this.nbLayers=1+(i>>11),this.nbDataBlocks=1+(2047&i))}getRotation(t,e){let r=0;t.forEach((t,n,i)=>{r=(r<<3)+((t>>e-2<<1)+(1&t))}),r=((1&r)<<11)+(r>>1);for(let t=0;t<4;t++)if(w.bitCount(r^this.EXPECTED_CORNER_BITS[t])<=2)return t;throw new N}getCorrectedParameterData(t,e){let r,n;e?(r=7,n=2):(r=10,n=4);let i=r-n,s=new Int32Array(r);for(let e=r-1;e>=0;--e)s[e]=15&t,t>>=4;try{new K(z.AZTEC_PARAM).decode(s,i)}catch(t){throw new N}let o=0;for(let t=0;t2){let r=this.distancePoint(h,t)*this.nbCenterLayers/(this.distancePoint(i,e)*(this.nbCenterLayers+2));if(r<.75||r>1.25||!this.isWhiteOrBlackRectangle(t,o,a,h))break}e=t,r=o,n=a,i=h,s=!s}if(5!==this.nbCenterLayers&&7!==this.nbCenterLayers)throw new N;this.compact=5===this.nbCenterLayers;let o=new J(e.getX()+.5,e.getY()-.5),a=new J(r.getX()+.5,r.getY()+.5),h=new J(n.getX()-.5,n.getY()+.5),l=new J(i.getX()-.5,i.getY()-.5);return this.expandSquare([o,a,h,l],2*this.nbCenterLayers-3,2*this.nbCenterLayers)}getMatrixCenter(){let t,e,r,n;try{let i=new et(this.image).detect();t=i[0],e=i[1],r=i[2],n=i[3]}catch(i){let s=this.image.getWidth()/2,o=this.image.getHeight()/2;t=this.getFirstDifferent(new ot(s+7,o-7),!1,1,-1).toResultPoint(),e=this.getFirstDifferent(new ot(s+7,o+7),!1,1,1).toResultPoint(),r=this.getFirstDifferent(new ot(s-7,o+7),!1,-1,1).toResultPoint(),n=this.getFirstDifferent(new ot(s-7,o-7),!1,-1,-1).toResultPoint()}let i=q.round((t.getX()+n.getX()+e.getX()+r.getX())/4),s=q.round((t.getY()+n.getY()+e.getY()+r.getY())/4);try{let o=new et(this.image,15,i,s).detect();t=o[0],e=o[1],r=o[2],n=o[3]}catch(o){t=this.getFirstDifferent(new ot(i+7,s-7),!1,1,-1).toResultPoint(),e=this.getFirstDifferent(new ot(i+7,s+7),!1,1,1).toResultPoint(),r=this.getFirstDifferent(new ot(i-7,s+7),!1,-1,1).toResultPoint(),n=this.getFirstDifferent(new ot(i-7,s-7),!1,-1,-1).toResultPoint()}return i=q.round((t.getX()+n.getX()+e.getX()+r.getX())/4),s=q.round((t.getY()+n.getY()+e.getY()+r.getY())/4),new ot(i,s)}getMatrixCornerPoints(t){return this.expandSquare(t,2*this.nbCenterLayers,this.getDimension())}sampleGrid(t,e,r,n,i){let s=st.getInstance(),o=this.getDimension(),a=o/2-this.nbCenterLayers,h=o/2+this.nbCenterLayers;return s.sampleGrid(t,o,o,a,a,h,a,h,h,a,h,e.getX(),e.getY(),r.getX(),r.getY(),n.getX(),n.getY(),i.getX(),i.getY())}sampleLine(t,e,r){let n=0,i=this.distanceResultPoint(t,e),s=i/r,o=t.getX(),a=t.getY(),h=s*(e.getX()-t.getX())/i,l=s*(e.getY()-t.getY())/i;for(let t=0;t.1&&c<.9?0:c<=.1===h?1:-1}getFirstDifferent(t,e,r,n){let i=t.getX()+r,s=t.getY()+n;for(;this.isValid(i,s)&&this.image.get(i,s)===e;)i+=r,s+=n;for(i-=r,s-=n;this.isValid(i,s)&&this.image.get(i,s)===e;)i+=r;for(i-=r;this.isValid(i,s)&&this.image.get(i,s)===e;)s+=n;return s-=n,new ot(i,s)}expandSquare(t,e,r){let n=r/(2*e),i=t[0].getX()-t[2].getX(),s=t[0].getY()-t[2].getY(),o=(t[0].getX()+t[2].getX())/2,a=(t[0].getY()+t[2].getY())/2,h=new J(o+n*i,a+n*s),l=new J(o-n*i,a-n*s);return i=t[1].getX()-t[3].getX(),s=t[1].getY()-t[3].getY(),o=(t[1].getX()+t[3].getX())/2,a=(t[1].getY()+t[3].getY())/2,[h,new J(o+n*i,a+n*s),l,new J(o-n*i,a-n*s)]}isValid(t,e){return t>=0&&t0&&e{r.foundPossibleResultPoint(t)})}}reset(){}}class lt{decode(t,e){try{return this.doDecode(t,e)}catch(r){if(e&&!0===e.get(E.TRY_HARDER)&&t.isRotateSupported()){const r=t.rotateCounterClockwise(),n=this.doDecode(r,e),i=n.getResultMetadata();let s=270;null!==i&&!0===i.get(U.ORIENTATION)&&(s+=i.get(U.ORIENTATION)%360),n.putMetadata(U.ORIENTATION,s);const o=n.getResultPoints();if(null!==o){const t=r.getHeight();for(let e=0;e>(s?8:5));let a;a=s?n:25;const h=Math.trunc(n/2);for(let s=0;s=n)break;try{i=t.getBlackRow(l,i)}catch(t){continue}for(let t=0;t<2;t++){if(1===t&&(i.reverse(),e&&!0===e.get(E.NEED_RESULT_POINT_CALLBACK))){const t=new Map;e.forEach((e,r)=>t.set(r,e)),t.delete(E.NEED_RESULT_POINT_CALLBACK),e=t}try{const n=this.decodeRow(l,i,e);if(1===t){n.putMetadata(U.ORIENTATION,180);const t=n.getResultPoints();null!==t&&(t[0]=new J(r-t[0].getX()-1,t[0].getY()),t[1]=new J(r-t[1].getX()-1,t[1].getY()))}return n}catch(t){}}}throw new N}static recordPattern(t,e,r){const n=r.length;for(let t=0;t=i)throw new N;let s=!t.get(e),o=0,a=e;for(;a0&&n>=0;)t.get(--e)!==i&&(n--,i=!i);if(n>=0)throw new N;lt.recordPattern(t,e+1,r)}static patternMatchVariance(t,e,r){const n=t.length;let i=0,s=0;for(let r=0;rs?n-s:s-n;if(h>r)return Number.POSITIVE_INFINITY;a+=h}return a/i}}class ct extends lt{static findStartPattern(t){const e=t.getSize(),r=t.getNextSet(0);let n=0,i=Int32Array.from([0,0,0,0,0,0]),s=r,o=!1;for(let a=r;a=0&&t.isRange(Math.max(0,s-(a-s)/2),s,!1))return Int32Array.from([s,a,r]);s+=i[0]+i[1],i=i.slice(2,i.length),i[n-1]=0,i[n]=0,n--}else n++;i[n]=1,o=!o}throw new N}static decodeCode(t,e,r){lt.recordPattern(t,r,e);let n=ct.MAX_AVG_VARIANCE,i=-1;for(let t=0;t=0)return i;throw new N}decodeRow(t,e,r){const n=r&&!0===r.get(E.ASSUME_GS1),i=ct.findStartPattern(e),s=i[2];let o=0;const a=new Uint8Array(20);let h;switch(a[o++]=s,s){case ct.CODE_START_A:h=ct.CODE_CODE_A;break;case ct.CODE_START_B:h=ct.CODE_CODE_B;break;case ct.CODE_START_C:h=ct.CODE_CODE_C;break;default:throw new m}let c=!1,d=!1,u="",g=i[0],f=i[1];const w=Int32Array.from([0,0,0,0,0,0]);let C=0,A=0,I=s,_=0,S=!0,p=!1,T=!1;for(;!c;){const t=d;switch(d=!1,C=A,A=ct.decodeCode(e,w,f),a[o++]=A,A!==ct.CODE_STOP&&(S=!0),A!==ct.CODE_STOP&&(_++,I+=_*A),g=f,f+=w.reduce((t,e)=>t+e,0),A){case ct.CODE_START_A:case ct.CODE_START_B:case ct.CODE_START_C:throw new m}switch(h){case ct.CODE_CODE_A:if(A<64)u+=T===p?String.fromCharCode(" ".charCodeAt(0)+A):String.fromCharCode(" ".charCodeAt(0)+A+128),T=!1;else if(A<96)u+=T===p?String.fromCharCode(A-64):String.fromCharCode(A+64),T=!1;else switch(A!==ct.CODE_STOP&&(S=!1),A){case ct.CODE_FNC_1:n&&(0===u.length?u+="]C1":u+=String.fromCharCode(29));break;case ct.CODE_FNC_2:case ct.CODE_FNC_3:break;case ct.CODE_FNC_4_A:!p&&T?(p=!0,T=!1):p&&T?(p=!1,T=!1):T=!0;break;case ct.CODE_SHIFT:d=!0,h=ct.CODE_CODE_B;break;case ct.CODE_CODE_B:h=ct.CODE_CODE_B;break;case ct.CODE_CODE_C:h=ct.CODE_CODE_C;break;case ct.CODE_STOP:c=!0}break;case ct.CODE_CODE_B:if(A<96)u+=T===p?String.fromCharCode(" ".charCodeAt(0)+A):String.fromCharCode(" ".charCodeAt(0)+A+128),T=!1;else switch(A!==ct.CODE_STOP&&(S=!1),A){case ct.CODE_FNC_1:n&&(0===u.length?u+="]C1":u+=String.fromCharCode(29));break;case ct.CODE_FNC_2:case ct.CODE_FNC_3:break;case ct.CODE_FNC_4_B:!p&&T?(p=!0,T=!1):p&&T?(p=!1,T=!1):T=!0;break;case ct.CODE_SHIFT:d=!0,h=ct.CODE_CODE_A;break;case ct.CODE_CODE_A:h=ct.CODE_CODE_A;break;case ct.CODE_CODE_C:h=ct.CODE_CODE_C;break;case ct.CODE_STOP:c=!0}break;case ct.CODE_CODE_C:if(A<100)A<10&&(u+="0"),u+=A;else switch(A!==ct.CODE_STOP&&(S=!1),A){case ct.CODE_FNC_1:n&&(0===u.length?u+="]C1":u+=String.fromCharCode(29));break;case ct.CODE_CODE_A:h=ct.CODE_CODE_A;break;case ct.CODE_CODE_B:h=ct.CODE_CODE_B;break;case ct.CODE_STOP:c=!0}}t&&(h=h===ct.CODE_CODE_A?ct.CODE_CODE_B:ct.CODE_CODE_A)}const R=f-g;if(f=e.getNextUnset(f),!e.isRange(f,Math.min(e.getSize(),f+(f-g)/2),!1))throw new N;if(I-=_*C,I%103!==C)throw new l;const D=u.length;if(0===D)throw new N;D>0&&S&&(u=h===ct.CODE_CODE_C?u.substring(0,D-2):u.substring(0,D-1));const M=(i[1]+i[0])/2,y=g+R/2,O=a.length,b=new Uint8Array(O);for(let t=0;tn&&(i=e);n=i,e=0;let s=0,o=0;for(let i=0;in&&(o|=1<0;i++){let r=t[i];if(r>n&&(e--,2*r>=s))return-1}return o}}while(e>3);return-1}static patternToChar(t){for(let e=0;e="A"&&i<="Z"))throw new m;s=String.fromCharCode(i.charCodeAt(0)+32);break;case"$":if(!(i>="A"&&i<="Z"))throw new m;s=String.fromCharCode(i.charCodeAt(0)-64);break;case"%":if(i>="A"&&i<="E")s=String.fromCharCode(i.charCodeAt(0)-38);else if(i>="F"&&i<="J")s=String.fromCharCode(i.charCodeAt(0)-11);else if(i>="K"&&i<="O")s=String.fromCharCode(i.charCodeAt(0)+16);else if(i>="P"&&i<="T")s=String.fromCharCode(i.charCodeAt(0)+43);else if("U"===i)s="\0";else if("V"===i)s="@";else if("W"===i)s="`";else{if("X"!==i&&"Y"!==i&&"Z"!==i)throw new m;s=""}break;case"/":if(i>="A"&&i<="O")s=String.fromCharCode(i.charCodeAt(0)-32);else{if("Z"!==i)throw new m;s=":"}}r+=s,n++}else r+=e}return r}}dt.ALPHABET_STRING="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%",dt.CHARACTER_ENCODINGS=[52,289,97,352,49,304,112,37,292,100,265,73,328,25,280,88,13,268,76,28,259,67,322,19,274,82,7,262,70,22,385,193,448,145,400,208,133,388,196,168,162,138,42],dt.ASTERISK_ENCODING=148;class ut extends lt{constructor(){super(),this.decodeRowResult="",this.counters=new Int32Array(6)}decodeRow(t,e,r){let n,i,s=this.findAsteriskPattern(e),o=e.getNextSet(s[1]),a=e.getSize(),h=this.counters;h.fill(0),this.decodeRowResult="";do{ut.recordPattern(e,o,h);let t=this.toPattern(h);if(t<0)throw new N;n=this.patternToChar(t),this.decodeRowResult+=n,i=o;for(let t of h)o+=t;o=e.getNextSet(o)}while("*"!==n);this.decodeRowResult=this.decodeRowResult.substring(0,this.decodeRowResult.length-1);let l=0;for(let t of h)l+=t;if(o===a||!e.get(o))throw new N;if(this.decodeRowResult.length<2)throw new N;this.checkChecksums(this.decodeRowResult),this.decodeRowResult=this.decodeRowResult.substring(0,this.decodeRowResult.length-2);let c=this.decodeExtended(this.decodeRowResult),d=(s[1]+s[0])/2,u=i+l/2;return new F(c,null,0,[new J(d,t),new J(u,t)],x.CODE_93,(new Date).getTime())}findAsteriskPattern(t){let e=t.getSize(),r=t.getNextSet(0);this.counters.fill(0);let n=this.counters,i=r,s=!1,o=n.length,a=0;for(let h=r;h4)return-1;if(1&i)r<<=n;else for(let t=0;t="a"&&i<="d"){if(n>=e-1)throw new m;let s=t.charAt(n+1),o="\0";switch(i){case"d":if(!(s>="A"&&s<="Z"))throw new m;o=String.fromCharCode(s.charCodeAt(0)+32);break;case"a":if(!(s>="A"&&s<="Z"))throw new m;o=String.fromCharCode(s.charCodeAt(0)-64);break;case"b":if(s>="A"&&s<="E")o=String.fromCharCode(s.charCodeAt(0)-38);else if(s>="F"&&s<="J")o=String.fromCharCode(s.charCodeAt(0)-11);else if(s>="K"&&s<="O")o=String.fromCharCode(s.charCodeAt(0)+16);else if(s>="P"&&s<="T")o=String.fromCharCode(s.charCodeAt(0)+43);else if("U"===s)o="\0";else if("V"===s)o="@";else if("W"===s)o="`";else{if(!(s>="X"&&s<="Z"))throw new m;o=String.fromCharCode(127)}break;case"c":if(s>="A"&&s<="O")o=String.fromCharCode(s.charCodeAt(0)-32);else{if("Z"!==s)throw new m;o=":"}}r+=o,n++}else r+=i}return r}checkChecksums(t){let e=t.length;this.checkOneChecksum(t,e-2,20),this.checkOneChecksum(t,e-1,15)}checkOneChecksum(t,e,r){let n=1,i=0;for(let s=e-1;s>=0;s--)i+=n*ut.ALPHABET_STRING.indexOf(t.charAt(s)),++n>r&&(n=1);if(t.charAt(e)!==ut.ALPHABET_STRING[i%47])throw new l}}ut.ALPHABET_STRING="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd*",ut.CHARACTER_ENCODINGS=[276,328,324,322,296,292,290,336,274,266,424,420,418,404,402,394,360,356,354,308,282,344,332,326,300,278,436,434,428,422,406,410,364,358,310,314,302,468,466,458,366,374,430,294,474,470,306,350],ut.ASTERISK_ENCODING=ut.CHARACTER_ENCODINGS[47];class gt extends lt{constructor(){super(...arguments),this.narrowLineWidth=-1}decodeRow(t,e,r){let n=this.decodeStart(e),i=this.decodeEnd(e),s=new T;gt.decodeMiddle(e,n[1],i[0],s);let o=s.toString(),a=null;null!=r&&(a=r.get(E.ALLOWED_LENGTHS)),null==a&&(a=gt.DEFAULT_ALLOWED_LENGTHS);let h=o.length,l=!1,c=0;for(let t of a){if(h===t){l=!0;break}t>c&&(c=t)}if(!l&&h>c&&(l=!0),!l)throw new m;const d=[new J(n[1],t),new J(i[0],t)];return new F(o,null,0,d,x.ITF,(new Date).getTime())}static decodeMiddle(t,e,r,n){let i=new Int32Array(10),s=new Int32Array(5),o=new Int32Array(5);for(i.fill(0),s.fill(0),o.fill(0);e0&&n>=0&&!t.get(n);n--)r--;if(0!==r)throw new N}static skipWhiteSpace(t){const e=t.getSize(),r=t.getNextSet(0);if(r===e)throw new N;return r}decodeEnd(t){t.reverse();try{let e,r=gt.skipWhiteSpace(t);try{e=gt.findGuardPattern(t,r,gt.END_PATTERN_REVERSED[0])}catch(n){n instanceof N&&(e=gt.findGuardPattern(t,r,gt.END_PATTERN_REVERSED[1]))}this.validateQuietZone(t,e[0]);let n=e[0];return e[0]=t.getSize()-e[1],e[1]=t.getSize()-n,e}finally{t.reverse()}}static findGuardPattern(t,e,r){let n=r.length,i=new Int32Array(n),s=t.getSize(),o=!1,a=0,h=e;i.fill(0);for(let l=e;l=0)return r%10;throw new N}}gt.PATTERNS=[Int32Array.from([1,1,2,2,1]),Int32Array.from([2,1,1,1,2]),Int32Array.from([1,2,1,1,2]),Int32Array.from([2,2,1,1,1]),Int32Array.from([1,1,2,1,2]),Int32Array.from([2,1,2,1,1]),Int32Array.from([1,2,2,1,1]),Int32Array.from([1,1,1,2,2]),Int32Array.from([2,1,1,2,1]),Int32Array.from([1,2,1,2,1]),Int32Array.from([1,1,3,3,1]),Int32Array.from([3,1,1,1,3]),Int32Array.from([1,3,1,1,3]),Int32Array.from([3,3,1,1,1]),Int32Array.from([1,1,3,1,3]),Int32Array.from([3,1,3,1,1]),Int32Array.from([1,3,3,1,1]),Int32Array.from([1,1,1,3,3]),Int32Array.from([3,1,1,3,1]),Int32Array.from([1,3,1,3,1])],gt.MAX_AVG_VARIANCE=.38,gt.MAX_INDIVIDUAL_VARIANCE=.5,gt.DEFAULT_ALLOWED_LENGTHS=[6,8,10,12,14],gt.START_PATTERN=Int32Array.from([1,1,1,1]),gt.END_PATTERN_REVERSED=[Int32Array.from([1,1,2]),Int32Array.from([1,1,3])];class ft extends lt{constructor(){super(...arguments),this.decodeRowStringBuffer=""}static findStartGuardPattern(t){let e,r=!1,n=0,i=Int32Array.from([0,0,0]);for(;!r;){i=Int32Array.from([0,0,0]),e=ft.findGuardPattern(t,n,!1,this.START_END_PATTERN,i);let s=e[0];n=e[1];let o=s-(n-s);o>=0&&(r=t.isRange(o,s,!1))}return e}static checkChecksum(t){return ft.checkStandardUPCEANChecksum(t)}static checkStandardUPCEANChecksum(t){let e=t.length;if(0===e)return!1;let r=parseInt(t.charAt(e-1),10);return ft.getStandardUPCEANChecksum(t.substring(0,e-1))===r}static getStandardUPCEANChecksum(t){let e=t.length,r=0;for(let n=e-1;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new m;r+=e}r*=3;for(let n=e-2;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new m;r+=e}return(1e3-r)%10}static decodeEnd(t,e){return ft.findGuardPattern(t,e,!1,ft.START_END_PATTERN,new Int32Array(ft.START_END_PATTERN.length).fill(0))}static findGuardPatternWithoutCounters(t,e,r,n){return this.findGuardPattern(t,e,r,n,new Int32Array(n.length))}static findGuardPattern(t,e,r,n,i){let s=t.getSize(),o=0,a=e=r?t.getNextUnset(e):t.getNextSet(e),h=n.length,l=r;for(let r=e;r=0)return s;throw new N}}ft.MAX_AVG_VARIANCE=.48,ft.MAX_INDIVIDUAL_VARIANCE=.7,ft.START_END_PATTERN=Int32Array.from([1,1,1]),ft.MIDDLE_PATTERN=Int32Array.from([1,1,1,1,1]),ft.END_PATTERN=Int32Array.from([1,1,1,1,1,1]),ft.L_PATTERNS=[Int32Array.from([3,2,1,1]),Int32Array.from([2,2,2,1]),Int32Array.from([2,1,2,2]),Int32Array.from([1,4,1,1]),Int32Array.from([1,1,3,2]),Int32Array.from([1,2,3,1]),Int32Array.from([1,1,1,4]),Int32Array.from([1,3,1,2]),Int32Array.from([1,2,1,3]),Int32Array.from([3,1,1,2])];class wt{constructor(){this.CHECK_DIGIT_ENCODINGS=[24,20,18,17,12,6,3,10,9,5],this.decodeMiddleCounters=Int32Array.from([0,0,0,0]),this.decodeRowStringBuffer=""}decodeRow(t,e,r){let n=this.decodeRowStringBuffer,i=this.decodeMiddle(e,r,n),s=n.toString(),o=wt.parseExtensionString(s),a=[new J((r[0]+r[1])/2,t),new J(i,t)],h=new F(s,null,0,a,x.UPC_EAN_EXTENSION,(new Date).getTime());return null!=o&&h.putAllMetadata(o),h}decodeMiddle(t,e,r){let n=this.decodeMiddleCounters;n[0]=0,n[1]=0,n[2]=0,n[3]=0;let i=t.getSize(),s=e[1],o=0;for(let e=0;e<5&&s=10&&(o|=1<<4-e),4!==e&&(s=t.getNextSet(s),s=t.getNextUnset(s))}if(5!==r.length)throw new N;let a=this.determineCheckDigit(o);if(wt.extensionChecksum(r.toString())!==a)throw new N;return s}static extensionChecksum(t){let e=t.length,r=0;for(let n=e-2;n>=0;n-=2)r+=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);r*=3;for(let n=e-1;n>=0;n-=2)r+=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);return r*=3,r%10}determineCheckDigit(t){for(let e=0;e<10;e++)if(t===this.CHECK_DIGIT_ENCODINGS[e])return e;throw new N}static parseExtensionString(t){if(5!==t.length)return null;let e=wt.parseExtension5String(t);return null==e?null:new Map([[U.SUGGESTED_PRICE,e]])}static parseExtension5String(t){let e;switch(t.charAt(0)){case"0":e="£";break;case"5":e="$";break;case"9":switch(t){case"90000":return null;case"99991":return"0.00";case"99990":return"Used"}e="";break;default:e=""}let r=parseInt(t.substring(1)),n=r%100;return e+(r/100).toString()+"."+(n<10?"0"+n:n.toString())}}class Ct{constructor(){this.decodeMiddleCounters=Int32Array.from([0,0,0,0]),this.decodeRowStringBuffer=""}decodeRow(t,e,r){let n=this.decodeRowStringBuffer,i=this.decodeMiddle(e,r,n),s=n.toString(),o=Ct.parseExtensionString(s),a=[new J((r[0]+r[1])/2,t),new J(i,t)],h=new F(s,null,0,a,x.UPC_EAN_EXTENSION,(new Date).getTime());return null!=o&&h.putAllMetadata(o),h}decodeMiddle(t,e,r){let n=this.decodeMiddleCounters;n[0]=0,n[1]=0,n[2]=0,n[3]=0;let i=t.getSize(),s=e[1],o=0;for(let e=0;e<2&&s=10&&(o|=1<<1-e),1!==e&&(s=t.getNextSet(s),s=t.getNextUnset(s))}if(2!==r.length)throw new N;if(parseInt(r.toString())%4!==o)throw new N;return s}static parseExtensionString(t){return 2!==t.length?null:new Map([[U.ISSUE_NUMBER,parseInt(t)]])}}class At{static decodeRow(t,e,r){let n=ft.findGuardPattern(e,r,!1,this.EXTENSION_START_PATTERN,new Int32Array(this.EXTENSION_START_PATTERN.length).fill(0));try{return(new wt).decodeRow(t,e,n)}catch(r){return(new Ct).decodeRow(t,e,n)}}}At.EXTENSION_START_PATTERN=Int32Array.from([1,1,2]);class Et extends ft{constructor(){super(),this.decodeRowStringBuffer="",Et.L_AND_G_PATTERNS=Et.L_PATTERNS.map(t=>Int32Array.from(t));for(let t=10;t<20;t++){let e=Et.L_PATTERNS[t-10],r=new Int32Array(e.length);for(let t=0;t=e.getSize()||!e.isRange(c,d,!1))throw new N;let u=a.toString();if(u.length<8)throw new m;if(!Et.checkChecksum(u))throw new l;let g=(n[1]+n[0])/2,f=(h[1]+h[0])/2,w=this.getBarcodeFormat(),C=[new J(g,t),new J(f,t)],A=new F(u,null,0,C,w,(new Date).getTime()),I=0;try{let r=At.decodeRow(t,e,h[1]);A.putMetadata(U.UPC_EAN_EXTENSION,r.getText()),A.putAllMetadata(r.getResultMetadata()),A.addResultPoints(r.getResultPoints()),I=r.getText().length}catch(t){}let _=null==r?null:r.get(E.ALLOWED_EAN_EXTENSIONS);if(null!=_){let t=!1;for(let e in _)if(I.toString()===e){t=!0;break}if(!t)throw new N}return w===x.EAN_13||x.UPC_A,A}static checkChecksum(t){return Et.checkStandardUPCEANChecksum(t)}static checkStandardUPCEANChecksum(t){let e=t.length;if(0===e)return!1;let r=parseInt(t.charAt(e-1),10);return Et.getStandardUPCEANChecksum(t.substring(0,e-1))===r}static getStandardUPCEANChecksum(t){let e=t.length,r=0;for(let n=e-1;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new m;r+=e}r*=3;for(let n=e-2;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new m;r+=e}return(1e3-r)%10}static decodeEnd(t,e){return Et.findGuardPattern(t,e,!1,Et.START_END_PATTERN,new Int32Array(Et.START_END_PATTERN.length).fill(0))}}class mt extends Et{constructor(){super(),this.decodeMiddleCounters=Int32Array.from([0,0,0,0])}decodeMiddle(t,e,r){let n=this.decodeMiddleCounters;n[0]=0,n[1]=0,n[2]=0,n[3]=0;let i=t.getSize(),s=e[1],o=0;for(let e=0;e<6&&s=10&&(o|=1<<5-e)}r=mt.determineFirstDigit(r,o),s=Et.findGuardPattern(t,s,!0,Et.MIDDLE_PATTERN,new Int32Array(Et.MIDDLE_PATTERN.length).fill(0))[1];for(let e=0;e<6&&st);n[0]=0,n[1]=0,n[2]=0,n[3]=0;const i=t.getSize();let s=e[1],o=0;for(let e=0;e<6&&s=10&&(o|=1<<5-e)}return St.determineNumSysAndCheckDigit(new T(r),o),s}decodeEnd(t,e){return St.findGuardPatternWithoutCounters(t,e,!0,St.MIDDLE_END_PATTERN)}checkChecksum(t){return Et.checkChecksum(St.convertUPCEtoUPCA(t))}static determineNumSysAndCheckDigit(t,e){for(let r=0;r<=1;r++)for(let n=0;n<10;n++)if(e===this.NUMSYS_AND_CHECK_DIGIT_PATTERNS[r][n])return t.insert(0,"0"+r),void t.append("0"+n);throw N.getNotFoundInstance()}getBarcodeFormat(){return x.UPC_E}static convertUPCEtoUPCA(t){const e=t.slice(1,7).split("").map(t=>t.charCodeAt(0)),r=new T;r.append(t.charAt(0));let n=e[5];switch(n){case 0:case 1:case 2:r.appendChars(e,0,2),r.append(n),r.append("0000"),r.appendChars(e,2,3);break;case 3:r.appendChars(e,0,3),r.append("00000"),r.appendChars(e,3,2);break;case 4:r.appendChars(e,0,4),r.append("00000"),r.append(e[4]);break;default:r.appendChars(e,0,5),r.append("0000"),r.append(n)}return t.length>=8&&r.append(t.charAt(7)),r.toString()}}St.MIDDLE_END_PATTERN=Int32Array.from([1,1,1,1,1,1]),St.NUMSYS_AND_CHECK_DIGIT_PATTERNS=[Int32Array.from([56,52,50,49,44,38,35,42,41,37]),Int32Array.from([7,11,13,14,19,25,28,21,22,1])];class pt extends lt{constructor(t){super();let e=null==t?null:t.get(E.POSSIBLE_FORMATS),r=[];null!=e&&(e.indexOf(x.EAN_13)>-1&&r.push(new mt),e.indexOf(x.UPC_A)>-1&&r.push(new _t),e.indexOf(x.EAN_8)>-1&&r.push(new It),e.indexOf(x.UPC_E)>-1&&r.push(new St)),0===r.length&&(r.push(new mt),r.push(new _t),r.push(new It),r.push(new St)),this.readers=r}decodeRow(t,e,r){for(let n of this.readers)try{const i=n.decodeRow(t,e,r),s=i.getBarcodeFormat()===x.EAN_13&&"0"===i.getText().charAt(0),o=null==r?null:r.get(E.POSSIBLE_FORMATS),a=null==o||o.includes(x.UPC_A);if(s&&a){const t=i.getRawBytes(),e=new F(i.getText().substring(1),t,t?t.length:null,i.getResultPoints(),x.UPC_A);return e.putAllMetadata(i.getResultMetadata()),e}return i}catch(t){}throw new N}reset(){for(let t of this.readers)t.reset()}}class Tt extends lt{constructor(){super(...arguments),this.CODA_BAR_CHAR_SET={nnnnnww:"0",nnnnwwn:"1",nnnwnnw:"2",wwnnnnn:"3",nnwnnwn:"4",wnnnnwn:"5",nwnnnnw:"6",nwnnwnn:"7",nwwnnnn:"8",wnnwnnn:"9",nnnwwnn:"-",nnwwnnn:"$",wnnnwnw:":",wnwnnnw:"/",wnwnwnn:".",nnwwwww:"+",nnwwnwn:"A",nwnwnnw:"B",nnnwnww:"C",nnnwwwn:"D"}}decodeRow(t,e,r){let n=this.getValidRowData(e);if(!n)throw new N;let i=this.codaBarDecodeRow(n.row);if(!i)throw new N;return new F(i,null,0,[new J(n.left,t),new J(n.right,t)],x.CODABAR,(new Date).getTime())}getValidRowData(t){let e=t.toArray(),r=e.indexOf(!0);if(-1===r)return null;let n=e.lastIndexOf(!0);if(n<=r)return null;e=e.slice(r,n+1);let i=[],s=e[0],o=1;for(let t=1;t(t+e)/2,0));for(;t.length>0;){const n=t.splice(0,8).splice(0,7).map(t=>tn&&(n=e[i],r=i);t[r]++}static decrement(t,e){let r=0,n=e[0];for(let i=1;i=Rt.MIN_FINDER_PATTERN_RATIO&&r<=Rt.MAX_FINDER_PATTERN_RATIO){let e=Number.MAX_SAFE_INTEGER,r=Number.MIN_SAFE_INTEGER;for(let n of t)n>r&&(r=n),n=o-a-1&&(t-=Mt.combins(n-h-(o-a),o-a-2)),o-a-1>1){let r=0;for(let t=n-h-(o-a-2);t>e;t--)r+=Mt.combins(n-h-t-1,o-a-3);t-=r*(o-1-a)}else n-h>e&&t--;i+=t}n-=h}return i}static combins(t,e){let r=0,n=0;t-e>e?(n=e,r=t-e):(n=t-e,r=e);let i=1,s=1;for(let e=t;e>r;e--)i*=e,s<=n&&(i=Math.trunc(i/s),s++);for(;s<=n;)i=Math.trunc(i/s),s++;return i}}class yt{static buildBitArray(t){let e=2*t.length-1;null===t[t.length-1].getRightChar()&&(e-=1);let r=new C(12*e),n=0,i=t[0].getRightChar().getValue();for(let t=11;t>=0;--t)i&1<=0;--t)s&1<=0;--e)t&1<10||r<0||r>10)throw new m;this.firstDigit=e,this.secondDigit=r}getFirstDigit(){return this.firstDigit}getSecondDigit(){return this.secondDigit}getValue(){return 10*this.firstDigit+this.secondDigit}isFirstDigitFNC1(){return this.firstDigit===vt.FNC1}isSecondDigitFNC1(){return this.secondDigit===vt.FNC1}}vt.FNC1=10;class kt{static fixed(t,e){return r=>kt.processFixedAI(t,e,r)}static variable(t,e){return r=>kt.processVariableAI(t,e,r)}constructor(){}static parseFieldsInGeneralPurpose(t){if(!t)return null;if(t.length<2)throw new N;const e=t.substring(0,2),r=this.TWO_DIGIT_DATA_LENGTH.get(e);if(r)return r(t);if(t.length<3)throw new N;const n=t.substring(0,3),i=this.THREE_DIGIT_DATA_LENGTH.get(n);if(i)return i(t);const s=this.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.get(n);if(s)return s(t);if(t.length<4)throw new N;const o=t.substring(0,4),a=this.FOUR_DIGIT_DATA_LENGTH.get(o);if(a)return a(t);throw new N}static processFixedAI(t,e,r){if(r.length{const t=new Map;t.set("00",kt.fixed(2,18)),t.set("01",kt.fixed(2,14)),t.set("02",kt.fixed(2,14)),t.set("10",kt.variable(2,20)),t.set("11",kt.fixed(2,6)),t.set("12",kt.fixed(2,6)),t.set("13",kt.fixed(2,6)),t.set("15",kt.fixed(2,6)),t.set("16",kt.fixed(2,6)),t.set("17",kt.fixed(2,6)),t.set("20",kt.fixed(2,2)),t.set("21",kt.variable(2,20)),t.set("22",kt.variable(2,29)),t.set("30",kt.variable(2,8)),t.set("37",kt.variable(2,8));for(let e=90;e<=99;e++)t.set(String(e),kt.variable(2,30));return t})(),kt.THREE_DIGIT_DATA_LENGTH=new Map([["235",kt.variable(3,28)],["240",kt.variable(3,30)],["241",kt.variable(3,30)],["242",kt.variable(3,6)],["243",kt.variable(3,20)],["250",kt.variable(3,30)],["251",kt.variable(3,30)],["253",kt.variable(3,30)],["254",kt.variable(3,20)],["255",kt.variable(3,25)],["400",kt.variable(3,30)],["401",kt.variable(3,30)],["402",kt.fixed(3,17)],["403",kt.variable(3,30)],["410",kt.fixed(3,13)],["411",kt.fixed(3,13)],["412",kt.fixed(3,13)],["413",kt.fixed(3,13)],["414",kt.fixed(3,13)],["415",kt.fixed(3,13)],["416",kt.fixed(3,13)],["417",kt.fixed(3,13)],["420",kt.variable(3,20)],["421",kt.variable(3,15)],["422",kt.fixed(3,3)],["423",kt.variable(3,15)],["424",kt.fixed(3,3)],["425",kt.variable(3,15)],["426",kt.fixed(3,3)],["427",kt.variable(3,3)],["710",kt.variable(3,20)],["711",kt.variable(3,20)],["712",kt.variable(3,20)],["713",kt.variable(3,20)],["714",kt.variable(3,20)],["715",kt.variable(3,20)]]),kt.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH=(()=>{const t=new Map;for(let e=310;e<=316;e++)t.set(String(e),kt.fixed(4,6));for(let e=320;e<=337;e++)t.set(String(e),kt.fixed(4,6));for(let e=340;e<=357;e++)t.set(String(e),kt.fixed(4,6));for(let e=360;e<=369;e++)t.set(String(e),kt.fixed(4,6));return t.set("390",kt.variable(4,15)),t.set("391",kt.variable(4,18)),t.set("392",kt.variable(4,15)),t.set("393",kt.variable(4,18)),t.set("394",kt.fixed(4,4)),t.set("395",kt.fixed(4,6)),t.set("703",kt.variable(4,30)),t.set("723",kt.variable(4,30)),t})(),kt.FOUR_DIGIT_DATA_LENGTH=(()=>{const t=new Map;return t.set("4300",kt.variable(4,35)),t.set("4301",kt.variable(4,35)),t.set("4302",kt.variable(4,70)),t.set("4303",kt.variable(4,70)),t.set("4304",kt.variable(4,70)),t.set("4305",kt.variable(4,70)),t.set("4306",kt.variable(4,70)),t.set("4307",kt.fixed(4,2)),t.set("4308",kt.variable(4,30)),t.set("4309",kt.fixed(4,20)),t.set("4310",kt.variable(4,35)),t.set("4311",kt.variable(4,35)),t.set("4312",kt.variable(4,70)),t.set("4313",kt.variable(4,70)),t.set("4314",kt.variable(4,70)),t.set("4315",kt.variable(4,70)),t.set("4316",kt.variable(4,70)),t.set("4317",kt.fixed(4,2)),t.set("4318",kt.variable(4,20)),t.set("4319",kt.variable(4,30)),t.set("4320",kt.variable(4,35)),t.set("4321",kt.fixed(4,1)),t.set("4322",kt.fixed(4,1)),t.set("4323",kt.fixed(4,1)),t.set("4324",kt.fixed(4,10)),t.set("4325",kt.fixed(4,10)),t.set("4326",kt.fixed(4,6)),t.set("7001",kt.fixed(4,13)),t.set("7002",kt.variable(4,30)),t.set("7003",kt.fixed(4,10)),t.set("7004",kt.variable(4,4)),t.set("7005",kt.variable(4,12)),t.set("7006",kt.fixed(4,6)),t.set("7007",kt.variable(4,12)),t.set("7008",kt.variable(4,3)),t.set("7009",kt.variable(4,10)),t.set("7010",kt.variable(4,2)),t.set("7011",kt.variable(4,10)),t.set("7020",kt.variable(4,20)),t.set("7021",kt.variable(4,20)),t.set("7022",kt.variable(4,20)),t.set("7023",kt.variable(4,30)),t.set("7040",kt.fixed(4,4)),t.set("7240",kt.variable(4,20)),t.set("8001",kt.fixed(4,14)),t.set("8002",kt.variable(4,20)),t.set("8003",kt.variable(4,30)),t.set("8004",kt.variable(4,30)),t.set("8005",kt.fixed(4,6)),t.set("8006",kt.fixed(4,18)),t.set("8007",kt.variable(4,34)),t.set("8008",kt.variable(4,12)),t.set("8009",kt.variable(4,50)),t.set("8010",kt.variable(4,30)),t.set("8011",kt.variable(4,12)),t.set("8012",kt.variable(4,20)),t.set("8013",kt.variable(4,25)),t.set("8017",kt.fixed(4,18)),t.set("8018",kt.fixed(4,18)),t.set("8019",kt.variable(4,10)),t.set("8020",kt.variable(4,25)),t.set("8026",kt.fixed(4,18)),t.set("8100",kt.fixed(4,6)),t.set("8101",kt.fixed(4,10)),t.set("8102",kt.fixed(4,2)),t.set("8110",kt.variable(4,70)),t.set("8111",kt.fixed(4,4)),t.set("8112",kt.variable(4,70)),t.set("8200",kt.variable(4,70)),t})();class xt{constructor(t){this.current=new Bt,this.buffer=new T,this.information=t}decodeAllCodes(t,e){let r=e,n=null;for(;;){const e=this.decodeGeneralPurposeField(r,n),i=kt.parseFieldsInGeneralPurpose(e.getNewString());if(null!==i&&t.append(i),n=e.isRemaining()?""+e.getRemainingValue():null,r===e.getNewPosition())break;r=e.getNewPosition()}return t.toString()}isStillNumeric(t){if(t+7>this.information.getSize())return t+4<=this.information.getSize();for(let e=t;ethis.information.getSize()){const e=this.extractNumericValueFromBitArray(t,4);return new vt(this.information.getSize(),0===e?vt.FNC1:e-1,vt.FNC1)}const e=this.extractNumericValueFromBitArray(t,7),r=Math.trunc((e-8)/11);return new vt(t+7,r,(e-8)%11)}extractNumericValueFromBitArray(t,e){return xt.extractNumericValueFromBitArray(this.information,t,e)}static extractNumericValueFromBitArray(t,e,r){let n=0;for(let i=0;ithis.information.getSize())return!1;const e=this.extractNumericValueFromBitArray(t,5);if(e>=5&&e<16)return!0;if(t+7>this.information.getSize())return!1;const r=this.extractNumericValueFromBitArray(t,7);if(r>=64&&r<116)return!0;if(t+8>this.information.getSize())return!1;const n=this.extractNumericValueFromBitArray(t,8);return n>=232&&n<253}decodeIsoIec646(t){const e=this.extractNumericValueFromBitArray(t,5);if(15===e)return new Lt(t+5,Lt.FNC1);if(e>=5&&e<15)return new Lt(t+5,String.fromCharCode("0".charCodeAt(0)+e-5));const r=this.extractNumericValueFromBitArray(t,7);if(r>=64&&r<90)return new Lt(t+7,String.fromCharCode(r+1));if(r>=90&&r<116)return new Lt(t+7,String.fromCharCode(r+7));let n;switch(this.extractNumericValueFromBitArray(t,8)){case 232:n="!";break;case 233:n='"';break;case 234:n="%";break;case 235:n="&";break;case 236:n="'";break;case 237:n="(";break;case 238:n=")";break;case 239:n="*";break;case 240:n="+";break;case 241:n=",";break;case 242:n="-";break;case 243:n=".";break;case 244:n="/";break;case 245:n=":";break;case 246:n=";";break;case 247:n="<";break;case 248:n="=";break;case 249:n=">";break;case 250:n="?";break;case 251:n="_";break;case 252:n=" ";break;default:throw new m}return new Lt(t+8,n)}isStillAlpha(t){if(t+5>this.information.getSize())return!1;const e=this.extractNumericValueFromBitArray(t,5);if(e>=5&&e<16)return!0;if(t+6>this.information.getSize())return!1;const r=this.extractNumericValueFromBitArray(t,6);return r>=16&&r<63}decodeAlphanumeric(t){const e=this.extractNumericValueFromBitArray(t,5);if(15===e)return new Lt(t+5,Lt.FNC1);if(e>=5&&e<15)return new Lt(t+5,String.fromCharCode("0".charCodeAt(0)+e-5));let r,n=this.extractNumericValueFromBitArray(t,6);if(n>=32&&n<58)return new Lt(t+6,String.fromCharCode(n+33));switch(n){case 58:r="*";break;case 59:r=",";break;case 60:r="-";break;case 61:r=".";break;case 62:r="/";break;default:throw new Z("Decoding invalid alphanumeric value: "+n)}return new Lt(t+6,r)}isAlphaTo646ToAlphaLatch(t){if(t+1>this.information.getSize())return!1;for(let e=0;e<5&&e+tthis.information.getSize())return!1;for(let e=t;ethis.information.getSize())return!1;for(let e=0;e<4&&e+t{const n=e[r];return jt.equals(t,n)})}}class $t extends Rt{constructor(){super(...arguments),this.pairs=new Array($t.MAX_PAIRS),this.rows=new Array,this.startEnd=[0,0],this.startFromEven=!1}decodeRow(t,e,r){this.startFromEven=!1;try{return $t.constructResult(this.decodeRow2pairs(t,e))}catch(t){if(!(t instanceof N))throw t}return this.startFromEven=!0,$t.constructResult(this.decodeRow2pairs(t,e))}reset(){this.pairs.length=0,this.rows.length=0}decodeRow2pairs(t,e){this.pairs.length=0;let r=!1;for(;!r;)try{this.pairs.push(this.retrieveNextPair(e,this.pairs,t))}catch(t){if(!(t instanceof N))throw t;if(0===this.pairs.length)throw t;r=!0}if(this.checkChecksum()&&$t.isValidSequence(this.pairs,!0))return this.pairs;let n=this.rows.length>0;if(this.storeRow(t),n){let t=this.checkRowsBoolean(!1);if(null!==t)return t;if(t=this.checkRowsBoolean(!0),null!==t)return t}throw new N}checkRowsBoolean(t){if(this.rows.length>25)return this.rows.length=0,null;this.pairs.length=0,t&&this.rows.reverse();let e=null;try{e=this.checkRows(new Array,0)}catch(t){if(!(t instanceof N))throw t}return t&&this.rows.reverse(),e}checkRows(t,e){for(let r=e;rt){n=i.isEquivalent(this.pairs);break}r=i.isEquivalent(this.pairs),e++}n||r||$t.isPartialRow(this.pairs,this.rows)||(this.rows.splice(e,0,new Jt(this.pairs,t)),this.removePartialRows(this.pairs,this.rows))}removePartialRows(t,e){for(let r=e.length-1;r>=0;r--){const n=e[r];if(n.getPairs().length!==t.length){let i=!0;for(const e of n.getPairs())if(!t.some(t=>jt.equals(e,t))){i=!1;break}i&&e.splice(r,1)}}}static isPartialRow(t,e){for(const r of e){let e=!0;for(const n of t){let t=!1;for(const e of r.getPairs())if(jt.equals(n,e)){t=!0;break}if(!t){e=!1;break}}if(e)return!0}return!1}getRows(){return this.rows}static constructResult(t){const e=qt(yt.buildBitArray(t)).parseInformation(),r=t[0].getFinderPattern().getResultPoints(),n=t[t.length-1].getFinderPattern().getResultPoints(),i=[r[0],r[1],n[0],n[1]];return new F(e,null,null,i,x.RSS_EXPANDED,null)}checkChecksum(){const t=this.pairs[0],e=t.getLeftChar(),r=t.getRightChar();if(null===r)return!1;let n=r.getChecksumPortion(),i=2;for(let t=1;t0&&e[e.length-1].mustBeLast())throw new N;let h=null;try{h=this.decodeDataCharacter(t,i,n,!1)}catch(t){if(!(t instanceof N))throw t;h=null}return new jt(s,h,i)}findNextPair(t,e,r){const n=this.getDecodeFinderCounters();n[0]=0,n[1]=0,n[2]=0,n[3]=0;let i=t.getSize(),s=0;if(r>=0)s=r;else if(0===e.length)s=0;else{s=e[e.length-1].getFinderPattern().getStartEnd()[1]}let o=e.length%2!=0;this.startFromEven&&(o=!o);let a=!1;for(;s=0&&!t.get(e);)e--;e++,i=this.startEnd[0]-e,s=e,o=this.startEnd[1]}else s=this.startEnd[0],o=t.getNextUnset(this.startEnd[1]+1),i=o-this.startEnd[1];const a=this.getDecodeFinderCounters();d.arraycopy(a,0,a,1,a.length-1),a[0]=i;let h=0;try{h=this.parseFinderValue(a,$t.FINDER_PATTERNS)}catch(t){if(t instanceof N)return null;throw t}if(!$t.mayFollow(n,h))return null;if(n.length>0){const t=n[n.length-1],e=t.getFinderPattern().getStartEnd()[0],r=t.getFinderPattern().getStartEnd()[1],i=(r-e)/$t.FINDER_PATTERN_MODULES*$t.DATA_CHARACTER_MODULES,o=r+2*i*(1-$t.MAX_FINDER_PATTERN_DISTANCE_VARIANCE),a=r+2*i*(1+$t.MAX_FINDER_PATTERN_DISTANCE_VARIANCE);if(sa)return null}return new Dt(h,[s,o],s,o,e)}decodeDataCharacter(t,e,r,n){const i=this.getDataCharacterCounters();for(let t=0;t.3)throw new N;const a=this.getOddCounts(),h=this.getEvenCounts(),l=this.getOddRoundingErrors(),c=this.getEvenRoundingErrors();for(let t=0;t8){if(e>8.7)throw new N;r=8}const n=Math.trunc(t/2);1&t?(h[n]=r,c[n]=e-r):(a[n]=r,l[n]=e-r)}this.adjustOddEvenCounts(17);let d=4*e.getValue()+(r?0:2)+(n?0:1)-1,u=0,g=0;for(let t=a.length-1;t>=0;t--){if($t.isNotA1left(e,r,n)){const e=$t.WEIGHTS[d][2*t];g+=a[t]*e}u+=a[t]}let f=0;for(let t=h.length-1;t>=0;t--)if($t.isNotA1left(e,r,n)){const e=$t.WEIGHTS[d][2*t+1];f+=h[t]*e}let w=g+f;if(1&u||u>13||u<4)throw new N;const C=Math.trunc((13-u)/2),A=$t.SYMBOL_WIDEST[C],E=9-A,m=Mt.getRSSvalue(a,A,!0),I=Mt.getRSSvalue(h,E,!1),_=$t.EVEN_TOTAL_SUBSET[C],S=$t.GSUM[C];return new Nt(m*_+I+S,w)}static isNotA1left(t,e,r){return!(0===t.getValue()&&e&&r)}adjustOddEvenCounts(t){const e=q.sum(new Int32Array(this.getOddCounts())),r=q.sum(new Int32Array(this.getEvenCounts()));let n=!1,i=!1;e>13?i=!0:e<4&&(n=!0);let s=!1,o=!1;r>13?o=!0:r<4&&(s=!0);let a=e+r-t,h=!(1&~e),l=!(1&r);if(1===a)if(h){if(l)throw new N;i=!0}else{if(!l)throw new N;o=!0}else if(-1===a)if(h){if(l)throw new N;n=!0}else{if(!l)throw new N;s=!0}else{if(0!==a)throw new N;if(h){if(!l)throw new N;e1)for(let e of this.possibleRightPairs)if(e.getCount()>1&&ee.checkChecksum(t,e))return ee.constructResult(t,e);throw new N}static addOrTally(t,e){if(null===e)return;let r=!1;for(let n of t)if(n.getValue()===e.getValue()){n.incrementCount(),r=!0;break}r||t.push(e)}reset(){this.possibleLeftPairs.length=0,this.possibleRightPairs.length=0}static constructResult(t,e){const r=4537077*t.getValue()+e.getValue(),n=String(r),i=new T;for(let t=13-n.length;t>0;t--)i.append("0");i.append(n);let s=0;for(let t=0;t<13;t++){const e=i.charAt(t).charCodeAt(0)-"0".charCodeAt(0);s+=1&t?e:3*e}s=10-s%10,10===s&&(s=0),i.append(s.toString());const o=t.getFinderPattern().getResultPoints(),a=e.getFinderPattern().getResultPoints();return new F(i.toString(),null,0,[o[0],o[1],a[0],a[1]],x.RSS_14,(new Date).getTime())}static checkChecksum(t,e){const r=(t.getChecksumPortion()+16*e.getChecksumPortion())%79;let n=9*t.getFinderPattern().getValue()+e.getFinderPattern().getValue();return n>72&&n--,n>8&&n--,r===n}decodePair(t,e,r,n){try{const i=this.findFinderPattern(t,e),s=this.parseFoundFinderPattern(t,r,e,i),o=null==n?null:n.get(E.NEED_RESULT_POINT_CALLBACK);if(null!=o){let n=(i[0]+i[1]-1)/2;e&&(n=t.getSize()-1-n),o.foundPossibleResultPoint(new J(n,r))}const a=this.decodeDataCharacter(t,s,!0),h=this.decodeDataCharacter(t,s,!1);return new te(1597*a.getValue()+h.getValue(),a.getChecksumPortion()+4*h.getChecksumPortion(),s)}catch(t){if(t instanceof N)return null;throw t}}decodeDataCharacter(t,e,r){const n=this.getDataCharacterCounters();for(let t=0;t8&&(r=8);const i=Math.floor(t/2);1&t?(a[i]=r,l[i]=e-r):(o[i]=r,h[i]=e-r)}this.adjustOddEvenCounts(r,i);let c=0,d=0;for(let t=o.length-1;t>=0;t--)d*=9,d+=o[t],c+=o[t];let u=0,g=0;for(let t=a.length-1;t>=0;t--)u*=9,u+=a[t],g+=a[t];const f=d+3*u;if(r){if(1&c||c>12||c<4)throw new N;const t=(12-c)/2,e=ee.OUTSIDE_ODD_WIDEST[t],r=9-e,n=Mt.getRSSvalue(o,e,!1),i=Mt.getRSSvalue(a,r,!0),s=ee.OUTSIDE_EVEN_TOTAL_SUBSET[t],h=ee.OUTSIDE_GSUM[t];return new Nt(n*s+i+h,f)}{if(1&g||g>10||g<4)throw new N;const t=(10-g)/2,e=ee.INSIDE_ODD_WIDEST[t],r=9-e,n=Mt.getRSSvalue(o,e,!0),i=Mt.getRSSvalue(a,r,!1),s=ee.INSIDE_ODD_TOTAL_SUBSET[t],h=ee.INSIDE_GSUM[t];return new Nt(i*s+n+h,f)}}findFinderPattern(t,e){const r=this.getDecodeFinderCounters();r[0]=0,r[1]=0,r[2]=0,r[3]=0;const n=t.getSize();let i=!1,s=0;for(;s=0&&i!==t.get(s);)s--;s++;const o=n[0]-s,a=this.getDecodeFinderCounters(),h=new Int32Array(a.length);d.arraycopy(a,0,h,1,a.length-1),h[0]=o;const l=this.parseFinderValue(h,ee.FINDER_PATTERNS);let c=s,u=n[1];return r&&(c=t.getSize()-1-c,u=t.getSize()-1-u),new Dt(l,[s,n[1]],c,u,e)}adjustOddEvenCounts(t,e){const r=q.sum(new Int32Array(this.getOddCounts())),n=q.sum(new Int32Array(this.getEvenCounts()));let i=!1,s=!1,o=!1,a=!1;t?(r>12?s=!0:r<4&&(i=!0),n>12?a=!0:n<4&&(o=!0)):(r>11?s=!0:r<5&&(i=!0),n>10?a=!0:n<4&&(o=!0));const h=r+n-e,l=(1&r)==(t?1:0),c=!(1&~n);if(1===h)if(l){if(c)throw new N;s=!0}else{if(!c)throw new N;a=!0}else if(-1===h)if(l){if(c)throw new N;i=!0}else{if(!c)throw new N;o=!0}else{if(0!==h)throw new N;if(l){if(!c)throw new N;rt.reset())}}let ne=class{constructor(t,e,r){this.ecCodewords=t,this.ecBlocks=[e],r&&this.ecBlocks.push(r)}getECCodewords(){return this.ecCodewords}getECBlocks(){return this.ecBlocks}},ie=class{constructor(t,e){this.count=t,this.dataCodewords=e}getCount(){return this.count}getDataCodewords(){return this.dataCodewords}},se=class t{constructor(t,e,r,n,i,s){this.versionNumber=t,this.symbolSizeRows=e,this.symbolSizeColumns=r,this.dataRegionSizeRows=n,this.dataRegionSizeColumns=i,this.ecBlocks=s;let o=0;const a=s.getECCodewords(),h=s.getECBlocks();for(let t of h)o+=t.getCount()*(t.getDataCodewords()+a);this.totalCodewords=o}getVersionNumber(){return this.versionNumber}getSymbolSizeRows(){return this.symbolSizeRows}getSymbolSizeColumns(){return this.symbolSizeColumns}getDataRegionSizeRows(){return this.dataRegionSizeRows}getDataRegionSizeColumns(){return this.dataRegionSizeColumns}getTotalCodewords(){return this.totalCodewords}getECBlocks(){return this.ecBlocks}static getVersionForDimensions(e,r){if(1&e||1&r)throw new m;for(let n of t.VERSIONS)if(n.symbolSizeRows===e&&n.symbolSizeColumns===r)return n;throw new m}toString(){return""+this.versionNumber}static buildVersions(){return[new t(1,10,10,8,8,new ne(5,new ie(1,3))),new t(2,12,12,10,10,new ne(7,new ie(1,5))),new t(3,14,14,12,12,new ne(10,new ie(1,8))),new t(4,16,16,14,14,new ne(12,new ie(1,12))),new t(5,18,18,16,16,new ne(14,new ie(1,18))),new t(6,20,20,18,18,new ne(18,new ie(1,22))),new t(7,22,22,20,20,new ne(20,new ie(1,30))),new t(8,24,24,22,22,new ne(24,new ie(1,36))),new t(9,26,26,24,24,new ne(28,new ie(1,44))),new t(10,32,32,14,14,new ne(36,new ie(1,62))),new t(11,36,36,16,16,new ne(42,new ie(1,86))),new t(12,40,40,18,18,new ne(48,new ie(1,114))),new t(13,44,44,20,20,new ne(56,new ie(1,144))),new t(14,48,48,22,22,new ne(68,new ie(1,174))),new t(15,52,52,24,24,new ne(42,new ie(2,102))),new t(16,64,64,14,14,new ne(56,new ie(2,140))),new t(17,72,72,16,16,new ne(36,new ie(4,92))),new t(18,80,80,18,18,new ne(48,new ie(4,114))),new t(19,88,88,20,20,new ne(56,new ie(4,144))),new t(20,96,96,22,22,new ne(68,new ie(4,174))),new t(21,104,104,24,24,new ne(56,new ie(6,136))),new t(22,120,120,18,18,new ne(68,new ie(6,175))),new t(23,132,132,20,20,new ne(62,new ie(8,163))),new t(24,144,144,22,22,new ne(62,new ie(8,156),new ie(2,155))),new t(25,8,18,6,16,new ne(7,new ie(1,5))),new t(26,8,32,6,14,new ne(11,new ie(1,10))),new t(27,12,26,10,24,new ne(14,new ie(1,16))),new t(28,12,36,10,16,new ne(18,new ie(1,22))),new t(29,16,36,14,16,new ne(24,new ie(1,32))),new t(30,16,48,14,22,new ne(28,new ie(1,49)))]}};se.VERSIONS=se.buildVersions();let oe=class t{constructor(e){const r=e.getHeight();if(r<8||r>144||1&r)throw new m;this.version=t.readVersion(e),this.mappingBitMatrix=this.extractDataRegion(e),this.readMappingMatrix=new R(this.mappingBitMatrix.getWidth(),this.mappingBitMatrix.getHeight())}getVersion(){return this.version}static readVersion(t){const e=t.getHeight(),r=t.getWidth();return se.getVersionForDimensions(e,r)}readCodewords(){const t=new Int8Array(this.version.getTotalCodewords());let e=0,r=4,n=0;const i=this.mappingBitMatrix.getHeight(),s=this.mappingBitMatrix.getWidth();let o=!1,a=!1,h=!1,l=!1;do{if(r!==i||0!==n||o)if(r===i-2&&0===n&&3&s&&!a)t[e++]=255&this.readCorner2(i,s),r-=2,n+=2,a=!0;else if(r!==i+4||2!==n||7&s||h)if(r!==i-2||0!==n||4!=(7&s)||l){do{r=0&&!this.readMappingMatrix.get(n,r)&&(t[e++]=255&this.readUtah(r,n,i,s)),r-=2,n+=2}while(r>=0&&n=0&&n=0);r+=3,n+=1}else t[e++]=255&this.readCorner4(i,s),r-=2,n+=2,l=!0;else t[e++]=255&this.readCorner3(i,s),r-=2,n+=2,h=!0;else t[e++]=255&this.readCorner1(i,s),r-=2,n+=2,o=!0}while(r7?t-1:t;o[n].codewords[i]=e[d++]}if(d!==e.length)throw new a;return o}getNumDataCodewords(){return this.numDataCodewords}getCodewords(){return this.codewords}};class he{constructor(t){this.bytes=t,this.byteOffset=0,this.bitOffset=0}getBitOffset(){return this.bitOffset}getByteOffset(){return this.byteOffset}readBits(t){if(t<1||t>32||t>this.available())throw new a(""+t);let e=0,r=this.bitOffset,n=this.byteOffset;const i=this.bytes;if(r>0){const s=8-r,o=t>8-o<>a,t-=o,r+=o,8===r&&(r=0,n++)}if(t>0){for(;t>=8;)e=e<<8|255&i[n],n++,t-=8;if(t>0){const s=8-t,o=255>>s<>s,r+=t}}return this.bitOffset=r,this.byteOffset=n,e}available(){return 8*(this.bytes.length-this.byteOffset)-this.bitOffset}}var le;!function(t){t[t.PAD_ENCODE=0]="PAD_ENCODE",t[t.ASCII_ENCODE=1]="ASCII_ENCODE",t[t.C40_ENCODE=2]="C40_ENCODE",t[t.TEXT_ENCODE=3]="TEXT_ENCODE",t[t.ANSIX12_ENCODE=4]="ANSIX12_ENCODE",t[t.EDIFACT_ENCODE=5]="EDIFACT_ENCODE",t[t.BASE256_ENCODE=6]="BASE256_ENCODE"}(le||(le={}));let ce=class{static decode(t){const e=new he(t),r=new T,n=new T,i=new Array;let s=le.ASCII_ENCODE;do{if(s===le.ASCII_ENCODE)s=this.decodeAsciiSegment(e,r,n);else{switch(s){case le.C40_ENCODE:this.decodeC40Segment(e,r);break;case le.TEXT_ENCODE:this.decodeTextSegment(e,r);break;case le.ANSIX12_ENCODE:this.decodeAnsiX12Segment(e,r);break;case le.EDIFACT_ENCODE:this.decodeEdifactSegment(e,r);break;case le.BASE256_ENCODE:this.decodeBase256Segment(e,r,i);break;default:throw new m}s=le.ASCII_ENCODE}}while(s!==le.PAD_ENCODE&&e.available()>0);return n.length()>0&&r.append(n.toString()),new V(t,r.toString(),0===i.length?null:i,null)}static decodeAsciiSegment(t,e,r){let n=!1;do{let i=t.readBits(8);if(0===i)throw new m;if(i<=128)return n&&(i+=128),e.append(String.fromCharCode(i-1)),le.ASCII_ENCODE;if(129===i)return le.PAD_ENCODE;if(i<=229){const t=i-130;t<10&&e.append("0"),e.append(""+t)}else switch(i){case 230:return le.C40_ENCODE;case 231:return le.BASE256_ENCODE;case 232:e.append(String.fromCharCode(29));break;case 233:case 234:case 241:break;case 235:n=!0;break;case 236:e.append("[)>05"),r.insert(0,"");break;case 237:e.append("[)>06"),r.insert(0,"");break;case 238:return le.ANSIX12_ENCODE;case 239:return le.TEXT_ENCODE;case 240:return le.EDIFACT_ENCODE;default:if(254!==i||0!==t.available())throw new m}}while(t.available()>0);return le.ASCII_ENCODE}static decodeC40Segment(t,e){let r=!1;const n=[];let i=0;do{if(8===t.available())return;const s=t.readBits(8);if(254===s)return;this.parseTwoBytes(s,t.readBits(8),n);for(let t=0;t<3;t++){const s=n[t];switch(i){case 0:if(s<3)i=s+1;else{if(!(s0)}static decodeTextSegment(t,e){let r=!1,n=[],i=0;do{if(8===t.available())return;const s=t.readBits(8);if(254===s)return;this.parseTwoBytes(s,t.readBits(8),n);for(let t=0;t<3;t++){const s=n[t];switch(i){case 0:if(s<3)i=s+1;else{if(!(s0)}static decodeAnsiX12Segment(t,e){const r=[];do{if(8===t.available())return;const n=t.readBits(8);if(254===n)return;this.parseTwoBytes(n,t.readBits(8),r);for(let t=0;t<3;t++){const n=r[t];switch(n){case 0:e.append("\r");break;case 1:e.append("*");break;case 2:e.append(">");break;case 3:e.append(" ");break;default:if(n<14)e.append(String.fromCharCode(n+44));else{if(!(n<40))throw new m;e.append(String.fromCharCode(n+51))}}}}while(t.available()>0)}static parseTwoBytes(t,e,r){let n=(t<<8)+e-1,i=Math.floor(n/1600);r[0]=i,n-=1600*i,i=Math.floor(n/40),r[1]=i,r[2]=n-40*i}static decodeEdifactSegment(t,e){do{if(t.available()<=16)return;for(let r=0;r<4;r++){let r=t.readBits(6);if(31===r){const e=8-t.getBitOffset();return void(8!==e&&t.readBits(e))}32&r||(r|=64),e.append(String.fromCharCode(r))}}while(t.available()>0)}static decodeBase256Segment(t,e,r){let n=1+t.getByteOffset();const i=this.unrandomize255State(t.readBits(8),n++);let s;if(s=0===i?t.available()/8|0:i<250?i:250*(i-249)+this.unrandomize255State(t.readBits(8),n++),s<0)throw new m;const o=new Uint8Array(s);for(let e=0;e=0?r:r+256}};ce.C40_BASIC_SET_CHARS=["*","*","*"," ","0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"],ce.C40_SHIFT2_SET_CHARS=["!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/",":",";","<","=",">","?","@","[","\\","]","^","_"],ce.TEXT_BASIC_SET_CHARS=["*","*","*"," ","0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"],ce.TEXT_SHIFT2_SET_CHARS=ce.C40_SHIFT2_SET_CHARS,ce.TEXT_SHIFT3_SET_CHARS=["`","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","{","|","}","~",String.fromCharCode(127)];let de=class{constructor(){this.rsDecoder=new K(z.DATA_MATRIX_FIELD_256)}decode(t){const e=new oe(t),r=e.getVersion(),n=e.readCodewords(),i=ae.getDataBlocks(n,r);let s=0;for(let t of i)s+=t.getNumDataCodewords();const o=new Uint8Array(s),a=i.length;for(let t=0;to&&(l=o,c[0]=e,c[1]=r,c[2]=n,c[3]=i),l>a&&(l=a,c[0]=r,c[1]=n,c[2]=i,c[3]=e),l>h&&(c[0]=n,c[1]=i,c[2]=e,c[3]=r),c}detectSolid2(e){let r=e[0],n=e[1],i=e[2],s=e[3],o=this.transitionsBetween(r,s),a=t.shiftPoint(n,i,4*(o+1)),h=t.shiftPoint(i,n,4*(o+1));return this.transitionsBetween(a,r)this.transitionsBetween(h,d)+this.transitionsBetween(l,d)?c:d:c:this.isValid(d)?d:null}shiftToModuleCenter(e){let r=e[0],n=e[1],i=e[2],s=e[3],o=this.transitionsBetween(r,s)+1,a=this.transitionsBetween(i,s)+1,h=t.shiftPoint(r,n,4*a),l=t.shiftPoint(i,n,4*o);o=this.transitionsBetween(h,s)+1,a=this.transitionsBetween(l,s)+1,1&~o||(o+=1),1&~a||(a+=1);let c,d,u=(r.getX()+n.getX()+i.getX()+s.getX())/4,g=(r.getY()+n.getY()+i.getY()+s.getY())/4;return r=t.moveAway(r,u,g),n=t.moveAway(n,u,g),i=t.moveAway(i,u,g),s=t.moveAway(s,u,g),h=t.shiftPoint(r,n,4*a),h=t.shiftPoint(h,s,4*o),c=t.shiftPoint(n,r,4*a),c=t.shiftPoint(c,i,4*o),l=t.shiftPoint(i,s,4*a),l=t.shiftPoint(l,n,4*o),d=t.shiftPoint(s,i,4*a),d=t.shiftPoint(d,r,4*o),[h,c,l,d]}isValid(t){return t.getX()>=0&&t.getX()0&&t.getY()Math.abs(i-r);if(o){let t=r;r=n,n=t,t=i,i=s,s=t}let a=Math.abs(i-r),h=Math.abs(s-n),l=-a/2,c=n0){if(e===s)break;e+=c,l-=a}}return u}};class ge{constructor(){this.decoder=new de}decode(t,e=null){let r,n;if(null!=e&&e.has(E.PURE_BARCODE)){const e=ge.extractPureBits(t.getBlackMatrix());r=this.decoder.decode(e),n=ge.NO_POINTS}else{const e=new ue(t.getBlackMatrix()).detect();r=this.decoder.decode(e.getBits()),n=e.getPoints()}const i=r.getRawBytes(),s=new F(r.getText(),i,8*i.length,n,x.DATA_MATRIX,d.currentTimeMillis()),o=r.getByteSegments();null!=o&&s.putMetadata(U.BYTE_SEGMENTS,o);const a=r.getECLevel();return null!=a&&s.putMetadata(U.ERROR_CORRECTION_LEVEL,a),s}reset(){}static extractPureBits(t){const e=t.getTopLeftOnBit(),r=t.getBottomRightOnBit();if(null==e||null==r)throw new N;const n=this.moduleSize(e,t);let i=e[1];const s=r[1];let o=e[0];const a=(r[0]-o+1)/n,h=(s-i+1)/n;if(a<=0||h<=0)throw new N;const l=n/2;i+=l,o+=l;const c=new R(a,h);for(let e=0;e=Ce.FOR_BITS.size)throw new a;return Ce.FOR_BITS.get(t)}}Ce.FOR_BITS=new Map,Ce.FOR_VALUE=new Map,Ce.L=new Ce(fe.L,"L",1),Ce.M=new Ce(fe.M,"M",0),Ce.Q=new Ce(fe.Q,"Q",3),Ce.H=new Ce(fe.H,"H",2);class Ae{constructor(t){this.errorCorrectionLevel=Ce.forBits(t>>3&3),this.dataMask=7&t}static numBitsDiffering(t,e){return w.bitCount(t^e)}static decodeFormatInformation(t,e){const r=Ae.doDecodeFormatInformation(t,e);return null!==r?r:Ae.doDecodeFormatInformation(t^Ae.FORMAT_INFO_MASK_QR,e^Ae.FORMAT_INFO_MASK_QR)}static doDecodeFormatInformation(t,e){let r=Number.MAX_SAFE_INTEGER,n=0;for(const i of Ae.FORMAT_INFO_DECODE_LOOKUP){const s=i[0];if(s===t||s===e)return new Ae(i[1]);let o=Ae.numBitsDiffering(t,s);o40)throw new a;return Ie.VERSIONS[t-1]}static decodeVersionInformation(t){let e=Number.MAX_SAFE_INTEGER,r=0;for(let n=0;n6&&(e.setRegion(t-11,0,3,6),e.setRegion(0,t-11,6,3)),e}toString(){return""+this.versionNumber}}Ie.VERSION_DECODE_INFO=Int32Array.from([31892,34236,39577,42195,48118,51042,55367,58893,63784,68472,70749,76311,79154,84390,87683,92361,96236,102084,102881,110507,110734,117786,119615,126325,127568,133589,136944,141498,145311,150283,152622,158308,161089,167017]),Ie.VERSIONS=[new Ie(1,new Int32Array(0),new Ee(7,new me(1,19)),new Ee(10,new me(1,16)),new Ee(13,new me(1,13)),new Ee(17,new me(1,9))),new Ie(2,Int32Array.from([6,18]),new Ee(10,new me(1,34)),new Ee(16,new me(1,28)),new Ee(22,new me(1,22)),new Ee(28,new me(1,16))),new Ie(3,Int32Array.from([6,22]),new Ee(15,new me(1,55)),new Ee(26,new me(1,44)),new Ee(18,new me(2,17)),new Ee(22,new me(2,13))),new Ie(4,Int32Array.from([6,26]),new Ee(20,new me(1,80)),new Ee(18,new me(2,32)),new Ee(26,new me(2,24)),new Ee(16,new me(4,9))),new Ie(5,Int32Array.from([6,30]),new Ee(26,new me(1,108)),new Ee(24,new me(2,43)),new Ee(18,new me(2,15),new me(2,16)),new Ee(22,new me(2,11),new me(2,12))),new Ie(6,Int32Array.from([6,34]),new Ee(18,new me(2,68)),new Ee(16,new me(4,27)),new Ee(24,new me(4,19)),new Ee(28,new me(4,15))),new Ie(7,Int32Array.from([6,22,38]),new Ee(20,new me(2,78)),new Ee(18,new me(4,31)),new Ee(18,new me(2,14),new me(4,15)),new Ee(26,new me(4,13),new me(1,14))),new Ie(8,Int32Array.from([6,24,42]),new Ee(24,new me(2,97)),new Ee(22,new me(2,38),new me(2,39)),new Ee(22,new me(4,18),new me(2,19)),new Ee(26,new me(4,14),new me(2,15))),new Ie(9,Int32Array.from([6,26,46]),new Ee(30,new me(2,116)),new Ee(22,new me(3,36),new me(2,37)),new Ee(20,new me(4,16),new me(4,17)),new Ee(24,new me(4,12),new me(4,13))),new Ie(10,Int32Array.from([6,28,50]),new Ee(18,new me(2,68),new me(2,69)),new Ee(26,new me(4,43),new me(1,44)),new Ee(24,new me(6,19),new me(2,20)),new Ee(28,new me(6,15),new me(2,16))),new Ie(11,Int32Array.from([6,30,54]),new Ee(20,new me(4,81)),new Ee(30,new me(1,50),new me(4,51)),new Ee(28,new me(4,22),new me(4,23)),new Ee(24,new me(3,12),new me(8,13))),new Ie(12,Int32Array.from([6,32,58]),new Ee(24,new me(2,92),new me(2,93)),new Ee(22,new me(6,36),new me(2,37)),new Ee(26,new me(4,20),new me(6,21)),new Ee(28,new me(7,14),new me(4,15))),new Ie(13,Int32Array.from([6,34,62]),new Ee(26,new me(4,107)),new Ee(22,new me(8,37),new me(1,38)),new Ee(24,new me(8,20),new me(4,21)),new Ee(22,new me(12,11),new me(4,12))),new Ie(14,Int32Array.from([6,26,46,66]),new Ee(30,new me(3,115),new me(1,116)),new Ee(24,new me(4,40),new me(5,41)),new Ee(20,new me(11,16),new me(5,17)),new Ee(24,new me(11,12),new me(5,13))),new Ie(15,Int32Array.from([6,26,48,70]),new Ee(22,new me(5,87),new me(1,88)),new Ee(24,new me(5,41),new me(5,42)),new Ee(30,new me(5,24),new me(7,25)),new Ee(24,new me(11,12),new me(7,13))),new Ie(16,Int32Array.from([6,26,50,74]),new Ee(24,new me(5,98),new me(1,99)),new Ee(28,new me(7,45),new me(3,46)),new Ee(24,new me(15,19),new me(2,20)),new Ee(30,new me(3,15),new me(13,16))),new Ie(17,Int32Array.from([6,30,54,78]),new Ee(28,new me(1,107),new me(5,108)),new Ee(28,new me(10,46),new me(1,47)),new Ee(28,new me(1,22),new me(15,23)),new Ee(28,new me(2,14),new me(17,15))),new Ie(18,Int32Array.from([6,30,56,82]),new Ee(30,new me(5,120),new me(1,121)),new Ee(26,new me(9,43),new me(4,44)),new Ee(28,new me(17,22),new me(1,23)),new Ee(28,new me(2,14),new me(19,15))),new Ie(19,Int32Array.from([6,30,58,86]),new Ee(28,new me(3,113),new me(4,114)),new Ee(26,new me(3,44),new me(11,45)),new Ee(26,new me(17,21),new me(4,22)),new Ee(26,new me(9,13),new me(16,14))),new Ie(20,Int32Array.from([6,34,62,90]),new Ee(28,new me(3,107),new me(5,108)),new Ee(26,new me(3,41),new me(13,42)),new Ee(30,new me(15,24),new me(5,25)),new Ee(28,new me(15,15),new me(10,16))),new Ie(21,Int32Array.from([6,28,50,72,94]),new Ee(28,new me(4,116),new me(4,117)),new Ee(26,new me(17,42)),new Ee(28,new me(17,22),new me(6,23)),new Ee(30,new me(19,16),new me(6,17))),new Ie(22,Int32Array.from([6,26,50,74,98]),new Ee(28,new me(2,111),new me(7,112)),new Ee(28,new me(17,46)),new Ee(30,new me(7,24),new me(16,25)),new Ee(24,new me(34,13))),new Ie(23,Int32Array.from([6,30,54,78,102]),new Ee(30,new me(4,121),new me(5,122)),new Ee(28,new me(4,47),new me(14,48)),new Ee(30,new me(11,24),new me(14,25)),new Ee(30,new me(16,15),new me(14,16))),new Ie(24,Int32Array.from([6,28,54,80,106]),new Ee(30,new me(6,117),new me(4,118)),new Ee(28,new me(6,45),new me(14,46)),new Ee(30,new me(11,24),new me(16,25)),new Ee(30,new me(30,16),new me(2,17))),new Ie(25,Int32Array.from([6,32,58,84,110]),new Ee(26,new me(8,106),new me(4,107)),new Ee(28,new me(8,47),new me(13,48)),new Ee(30,new me(7,24),new me(22,25)),new Ee(30,new me(22,15),new me(13,16))),new Ie(26,Int32Array.from([6,30,58,86,114]),new Ee(28,new me(10,114),new me(2,115)),new Ee(28,new me(19,46),new me(4,47)),new Ee(28,new me(28,22),new me(6,23)),new Ee(30,new me(33,16),new me(4,17))),new Ie(27,Int32Array.from([6,34,62,90,118]),new Ee(30,new me(8,122),new me(4,123)),new Ee(28,new me(22,45),new me(3,46)),new Ee(30,new me(8,23),new me(26,24)),new Ee(30,new me(12,15),new me(28,16))),new Ie(28,Int32Array.from([6,26,50,74,98,122]),new Ee(30,new me(3,117),new me(10,118)),new Ee(28,new me(3,45),new me(23,46)),new Ee(30,new me(4,24),new me(31,25)),new Ee(30,new me(11,15),new me(31,16))),new Ie(29,Int32Array.from([6,30,54,78,102,126]),new Ee(30,new me(7,116),new me(7,117)),new Ee(28,new me(21,45),new me(7,46)),new Ee(30,new me(1,23),new me(37,24)),new Ee(30,new me(19,15),new me(26,16))),new Ie(30,Int32Array.from([6,26,52,78,104,130]),new Ee(30,new me(5,115),new me(10,116)),new Ee(28,new me(19,47),new me(10,48)),new Ee(30,new me(15,24),new me(25,25)),new Ee(30,new me(23,15),new me(25,16))),new Ie(31,Int32Array.from([6,30,56,82,108,134]),new Ee(30,new me(13,115),new me(3,116)),new Ee(28,new me(2,46),new me(29,47)),new Ee(30,new me(42,24),new me(1,25)),new Ee(30,new me(23,15),new me(28,16))),new Ie(32,Int32Array.from([6,34,60,86,112,138]),new Ee(30,new me(17,115)),new Ee(28,new me(10,46),new me(23,47)),new Ee(30,new me(10,24),new me(35,25)),new Ee(30,new me(19,15),new me(35,16))),new Ie(33,Int32Array.from([6,30,58,86,114,142]),new Ee(30,new me(17,115),new me(1,116)),new Ee(28,new me(14,46),new me(21,47)),new Ee(30,new me(29,24),new me(19,25)),new Ee(30,new me(11,15),new me(46,16))),new Ie(34,Int32Array.from([6,34,62,90,118,146]),new Ee(30,new me(13,115),new me(6,116)),new Ee(28,new me(14,46),new me(23,47)),new Ee(30,new me(44,24),new me(7,25)),new Ee(30,new me(59,16),new me(1,17))),new Ie(35,Int32Array.from([6,30,54,78,102,126,150]),new Ee(30,new me(12,121),new me(7,122)),new Ee(28,new me(12,47),new me(26,48)),new Ee(30,new me(39,24),new me(14,25)),new Ee(30,new me(22,15),new me(41,16))),new Ie(36,Int32Array.from([6,24,50,76,102,128,154]),new Ee(30,new me(6,121),new me(14,122)),new Ee(28,new me(6,47),new me(34,48)),new Ee(30,new me(46,24),new me(10,25)),new Ee(30,new me(2,15),new me(64,16))),new Ie(37,Int32Array.from([6,28,54,80,106,132,158]),new Ee(30,new me(17,122),new me(4,123)),new Ee(28,new me(29,46),new me(14,47)),new Ee(30,new me(49,24),new me(10,25)),new Ee(30,new me(24,15),new me(46,16))),new Ie(38,Int32Array.from([6,32,58,84,110,136,162]),new Ee(30,new me(4,122),new me(18,123)),new Ee(28,new me(13,46),new me(32,47)),new Ee(30,new me(48,24),new me(14,25)),new Ee(30,new me(42,15),new me(32,16))),new Ie(39,Int32Array.from([6,26,54,82,110,138,166]),new Ee(30,new me(20,117),new me(4,118)),new Ee(28,new me(40,47),new me(7,48)),new Ee(30,new me(43,24),new me(22,25)),new Ee(30,new me(10,15),new me(67,16))),new Ie(40,Int32Array.from([6,30,58,86,114,142,170]),new Ee(30,new me(19,118),new me(6,119)),new Ee(28,new me(18,47),new me(31,48)),new Ee(30,new me(34,24),new me(34,25)),new Ee(30,new me(20,15),new me(61,16)))],function(t){t[t.DATA_MASK_000=0]="DATA_MASK_000",t[t.DATA_MASK_001=1]="DATA_MASK_001",t[t.DATA_MASK_010=2]="DATA_MASK_010",t[t.DATA_MASK_011=3]="DATA_MASK_011",t[t.DATA_MASK_100=4]="DATA_MASK_100",t[t.DATA_MASK_101=5]="DATA_MASK_101",t[t.DATA_MASK_110=6]="DATA_MASK_110",t[t.DATA_MASK_111=7]="DATA_MASK_111"}(we||(we={}));class _e{constructor(t,e){this.value=t,this.isMasked=e}unmaskBitMatrix(t,e){for(let r=0;r!(t+e&1))],[we.DATA_MASK_001,new _e(we.DATA_MASK_001,(t,e)=>!(1&t))],[we.DATA_MASK_010,new _e(we.DATA_MASK_010,(t,e)=>e%3==0)],[we.DATA_MASK_011,new _e(we.DATA_MASK_011,(t,e)=>(t+e)%3==0)],[we.DATA_MASK_100,new _e(we.DATA_MASK_100,(t,e)=>!(Math.floor(t/2)+Math.floor(e/3)&1))],[we.DATA_MASK_101,new _e(we.DATA_MASK_101,(t,e)=>t*e%6==0)],[we.DATA_MASK_110,new _e(we.DATA_MASK_110,(t,e)=>t*e%6<3)],[we.DATA_MASK_111,new _e(we.DATA_MASK_111,(t,e)=>!(t+e+t*e%3&1))]]);let Se=class{constructor(t){const e=t.getHeight();if(e<21||1!=(3&e))throw new m;this.bitMatrix=t}readFormatInformation(){if(null!==this.parsedFormatInfo&&void 0!==this.parsedFormatInfo)return this.parsedFormatInfo;let t=0;for(let e=0;e<6;e++)t=this.copyBit(e,8,t);t=this.copyBit(7,8,t),t=this.copyBit(8,8,t),t=this.copyBit(8,7,t);for(let e=5;e>=0;e--)t=this.copyBit(8,e,t);const e=this.bitMatrix.getHeight();let r=0;const n=e-7;for(let t=e-1;t>=n;t--)r=this.copyBit(8,t,r);for(let t=e-8;t=0;e--)for(let i=t-9;i>=n;i--)r=this.copyBit(i,e,r);let i=Ie.decodeVersionInformation(r);if(null!==i&&i.getDimensionForVersion()===t)return this.parsedVersion=i,i;r=0;for(let e=5;e>=0;e--)for(let i=t-9;i>=n;i--)r=this.copyBit(e,i,r);if(i=Ie.decodeVersionInformation(r),null!==i&&i.getDimensionForVersion()===t)return this.parsedVersion=i,i;throw new m}copyBit(t,e,r){return(this.isMirror?this.bitMatrix.get(e,t):this.bitMatrix.get(t,e))?r<<1|1:r<<1}readCodewords(){const t=this.readFormatInformation(),e=this.readVersion(),r=_e.values.get(t.getDataMask()),n=this.bitMatrix.getHeight();r.unmaskBitMatrix(this.bitMatrix,n);const i=e.buildFunctionPattern();let s=!0;const o=new Uint8Array(e.getTotalCodewords());let a=0,h=0,l=0;for(let t=n-1;t>0;t-=2){6===t&&t--;for(let e=0;e=0;){if(o[c].codewords.length===l)break;c--}c++;const d=l-n.getECCodewordsPerBlock();let u=0;for(let e=0;et.available())throw new m;const n=new Uint8Array(2*r);let i=0;for(;r>0;){const e=t.readBits(13);let s=e/96<<8&4294967295|e%96;s+=s<959?41377:42657,n[i]=s>>8&255,n[i+1]=255&s,i+=2,r--}try{e.append(S.decode(n,p.GB2312))}catch(t){throw new m(t)}}static decodeKanjiSegment(t,e,r){if(13*r>t.available())throw new m;const n=new Uint8Array(2*r);let i=0;for(;r>0;){const e=t.readBits(13);let s=e/192<<8&4294967295|e%192;s+=s<7936?33088:49472,n[i]=s>>8,n[i+1]=s,i+=2,r--}try{e.append(S.decode(n,p.SHIFT_JIS))}catch(t){throw new m(t)}}static decodeByteSegment(t,e,r,n,i,s){if(8*r>t.available())throw new m;const o=new Uint8Array(r);for(let e=0;e=t.ALPHANUMERIC_CHARS.length)throw new m;return t.ALPHANUMERIC_CHARS[e]}static decodeAlphanumericSegment(e,r,n,i){const s=r.length();for(;n>1;){if(e.available()<11)throw new m;const i=e.readBits(11);r.append(t.toAlphaNumericChar(Math.floor(i/45))),r.append(t.toAlphaNumericChar(i%45)),n-=2}if(1===n){if(e.available()<6)throw new m;r.append(t.toAlphaNumericChar(e.readBits(6)))}if(i)for(let t=s;t=3;){if(e.available()<10)throw new m;const i=e.readBits(10);if(i>=1e3)throw new m;r.append(t.toAlphaNumericChar(Math.floor(i/100))),r.append(t.toAlphaNumericChar(Math.floor(i/10)%10)),r.append(t.toAlphaNumericChar(i%10)),n-=3}if(2===n){if(e.available()<7)throw new m;const n=e.readBits(7);if(n>=100)throw new m;r.append(t.toAlphaNumericChar(Math.floor(n/10))),r.append(t.toAlphaNumericChar(n%10))}else if(1===n){if(e.available()<4)throw new m;const n=e.readBits(4);if(n>=10)throw new m;r.append(t.toAlphaNumericChar(n))}}static parseECIValue(t){const e=t.readBits(8);if(!(128&e))return 127&e;if(128==(192&e)){return(63&e)<<8&4294967295|t.readBits(8)}if(192==(224&e)){return(31&e)<<16&4294967295|t.readBits(16)}throw new m}};Ne.ALPHANUMERIC_CHARS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",Ne.GB2312_SUBSET=1;class De{constructor(t){this.mirrored=t}isMirrored(){return this.mirrored}applyMirroredCorrection(t){if(!this.mirrored||null===t||t.length<3)return;const e=t[0];t[0]=t[2],t[2]=e}}let Me=class{constructor(){this.rsDecoder=new K(z.QR_CODE_FIELD_256)}decodeBooleanArray(t,e){return this.decodeBitMatrix(R.parseFromBooleanArray(t),e)}decodeBitMatrix(t,e){const r=new Se(t);let n=null;try{return this.decodeBitMatrixParser(r,e)}catch(t){n=t}try{r.remask(),r.setMirror(!0),r.readVersion(),r.readFormatInformation(),r.mirror();const t=this.decodeBitMatrixParser(r,e);return t.setOther(new De(!0)),t}catch(t){if(null!==n)throw n;throw t}}decodeBitMatrixParser(t,e){const r=t.readVersion(),n=t.readFormatInformation().getErrorCorrectionLevel(),i=t.readCodewords(),s=pe.getDataBlocks(i,r,n);let o=0;for(const t of s)o+=t.getNumDataCodewords();const a=new Uint8Array(o);let h=0;for(const t of s){const e=t.getCodewords(),r=t.getNumDataCodewords();this.correctErrors(e,r);for(let t=0;t=r)return!1;return!0}crossCheckVertical(t,e,r,n){const i=this.image,s=i.getHeight(),o=this.crossCheckStateCount;o[0]=0,o[1]=0,o[2]=0;let a=t;for(;a>=0&&i.get(e,a)&&o[1]<=r;)o[1]++,a--;if(a<0||o[1]>r)return NaN;for(;a>=0&&!i.get(e,a)&&o[0]<=r;)o[0]++,a--;if(o[0]>r)return NaN;for(a=t+1;ar)return NaN;for(;ar)return NaN;const h=o[0]+o[1]+o[2];return 5*Math.abs(h-n)>=2*n?NaN:this.foundPatternCross(o)?Oe.centerFromEnd(o,a):NaN}handlePossibleCenter(t,e,r){const n=t[0]+t[1]+t[2],i=Oe.centerFromEnd(t,r),s=this.crossCheckVertical(e,i,2*t[1],n);if(!isNaN(s)){const e=(t[0]+t[1]+t[2])/3;for(const t of this.possibleCenters)if(t.aboutEquals(e,s,i))return t.combineEstimate(s,i,e);const r=new ye(i,s,e);this.possibleCenters.push(r),null!==this.resultPointCallback&&void 0!==this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(r)}return null}}class be extends J{constructor(t,e,r,n){super(t,e),this.estimatedModuleSize=r,this.count=n,void 0===n&&(this.count=1)}getEstimatedModuleSize(){return this.estimatedModuleSize}getCount(){return this.count}aboutEquals(t,e,r){if(Math.abs(e-this.getY())<=t&&Math.abs(r-this.getX())<=t){const e=Math.abs(t-this.estimatedModuleSize);return e<=1||e<=this.estimatedModuleSize}return!1}combineEstimate(t,e,r){const n=this.count+1,i=(this.count*this.getX()+e)/n,s=(this.count*this.getY()+t)/n,o=(this.count*this.estimatedModuleSize+r)/n;return new be(i,s,o,n)}}class Be{constructor(t){this.bottomLeft=t[0],this.topLeft=t[1],this.topRight=t[2]}getBottomLeft(){return this.bottomLeft}getTopLeft(){return this.topLeft}getTopRight(){return this.topRight}}class Pe{constructor(t,e){this.image=t,this.resultPointCallback=e,this.possibleCenters=[],this.crossCheckStateCount=new Int32Array(5),this.resultPointCallback=e}getImage(){return this.image}getPossibleCenters(){return this.possibleCenters}find(t){const e=null!=t&&void 0!==t.get(E.TRY_HARDER),r=null!=t&&void 0!==t.get(E.PURE_BARCODE),n=this.image,i=n.getHeight(),s=n.getWidth();let o=Math.floor(3*i/(4*Pe.MAX_MODULES));(oh[2]&&(t+=e-h[2]-o,i=s-1)}e=0,h.fill(0)}else h[0]=h[2],h[1]=h[3],h[2]=h[4],h[3]=1,h[4]=0,e=3;else h[++e]++;if(Pe.foundPatternCross(h)){!0===this.handlePossibleCenter(h,t,s,r)&&(o=h[0],this.hasSkipped&&(a=this.haveMultiplyConfirmedCenters()))}}const l=this.selectBestPatterns();return J.orderBestPatterns(l),new Be(l)}static centerFromEnd(t,e){return e-t[4]-t[3]-t[2]/2}static foundPatternCross(t){let e=0;for(let r=0;r<5;r++){const n=t[r];if(0===n)return!1;e+=n}if(e<7)return!1;const r=e/7,n=r/2;return Math.abs(r-t[0])=s&&e>=s&&o.get(e-s,t-s);)i[2]++,s++;if(t=s&&e>=s&&!o.get(e-s,t-s)&&i[1]<=r;)i[1]++,s++;if(tr)return!1;for(;t>=s&&e>=s&&o.get(e-s,t-s)&&i[0]<=r;)i[0]++,s++;if(i[0]>r)return!1;const a=o.getHeight(),h=o.getWidth();for(s=1;t+s=a||e+s>=h)return!1;for(;t+s=a||e+s>=h||i[3]>=r)return!1;for(;t+s=r)return!1;const l=i[0]+i[1]+i[2]+i[3]+i[4];return Math.abs(l-n)<2*n&&Pe.foundPatternCross(i)}crossCheckVertical(t,e,r,n){const i=this.image,s=i.getHeight(),o=this.getCrossCheckStateCount();let a=t;for(;a>=0&&i.get(e,a);)o[2]++,a--;if(a<0)return NaN;for(;a>=0&&!i.get(e,a)&&o[1]<=r;)o[1]++,a--;if(a<0||o[1]>r)return NaN;for(;a>=0&&i.get(e,a)&&o[0]<=r;)o[0]++,a--;if(o[0]>r)return NaN;for(a=t+1;a=r)return NaN;for(;a=r)return NaN;const h=o[0]+o[1]+o[2]+o[3]+o[4];return 5*Math.abs(h-n)>=2*n?NaN:Pe.foundPatternCross(o)?Pe.centerFromEnd(o,a):NaN}crossCheckHorizontal(t,e,r,n){const i=this.image,s=i.getWidth(),o=this.getCrossCheckStateCount();let a=t;for(;a>=0&&i.get(a,e);)o[2]++,a--;if(a<0)return NaN;for(;a>=0&&!i.get(a,e)&&o[1]<=r;)o[1]++,a--;if(a<0||o[1]>r)return NaN;for(;a>=0&&i.get(a,e)&&o[0]<=r;)o[0]++,a--;if(o[0]>r)return NaN;for(a=t+1;a=r)return NaN;for(;a=r)return NaN;const h=o[0]+o[1]+o[2]+o[3]+o[4];return 5*Math.abs(h-n)>=n?NaN:Pe.foundPatternCross(o)?Pe.centerFromEnd(o,a):NaN}handlePossibleCenter(t,e,r,n){const i=t[0]+t[1]+t[2]+t[3]+t[4];let s=Pe.centerFromEnd(t,r),o=this.crossCheckVertical(e,Math.floor(s),t[2],i);if(!isNaN(o)&&(s=this.crossCheckHorizontal(Math.floor(s),Math.floor(o),t[2],i),!isNaN(s)&&(!n||this.crossCheckDiagonal(Math.floor(o),Math.floor(s),t[2],i)))){const t=i/7;let e=!1;const r=this.possibleCenters;for(let n=0,i=r.length;n=Pe.CENTER_QUORUM){if(null!=t)return this.hasSkipped=!0,Math.floor((Math.abs(t.getX()-e.getX())-Math.abs(t.getY()-e.getY()))/2);t=e}return 0}haveMultiplyConfirmedCenters(){let t=0,e=0;const r=this.possibleCenters.length;for(const r of this.possibleCenters)r.getCount()>=Pe.CENTER_QUORUM&&(t++,e+=r.getEstimatedModuleSize());if(t<3)return!1;const n=e/r;let i=0;for(const t of this.possibleCenters)i+=Math.abs(t.getEstimatedModuleSize()-n);return i<=.05*e}selectBestPatterns(){const t=this.possibleCenters.length;if(t<3)throw new N;const e=this.possibleCenters;let r;if(t>3){let n=0,i=0;for(const t of this.possibleCenters){const e=t.getEstimatedModuleSize();n+=e,i+=e*e}r=n/t;let s=Math.sqrt(i/t-r*r);e.sort((t,e)=>{const n=Math.abs(e.getEstimatedModuleSize()-r),i=Math.abs(t.getEstimatedModuleSize()-r);return ni?1:0});const o=Math.max(.2*r,s);for(let t=0;t3;t++){const n=e[t];Math.abs(n.getEstimatedModuleSize()-r)>o&&(e.splice(t,1),t--)}}if(e.length>3){let t=0;for(const r of e)t+=r.getEstimatedModuleSize();r=t/e.length,e.sort((t,e)=>{if(e.getCount()===t.getCount()){const n=Math.abs(e.getEstimatedModuleSize()-r),i=Math.abs(t.getEstimatedModuleSize()-r);return ni?-1:0}return e.getCount()-t.getCount()}),e.splice(3)}return[e[0],e[1],e[2]]}}Pe.CENTER_QUORUM=2,Pe.MIN_SKIP=3,Pe.MAX_MODULES=57;let Le=class t{constructor(t){this.image=t}getImage(){return this.image}getResultPointCallback(){return this.resultPointCallback}detect(t){this.resultPointCallback=null==t?null:t.get(E.NEED_RESULT_POINT_CALLBACK);const e=new Pe(this.image,this.resultPointCallback).find(t);return this.processFinderPatternInfo(e)}processFinderPatternInfo(e){const r=e.getTopLeft(),n=e.getTopRight(),i=e.getBottomLeft(),s=this.calculateModuleSize(r,n,i);if(s<1)throw new N("No pattern found in proccess finder.");const o=t.computeDimension(r,n,i,s),a=Ie.getProvisionalVersionForDimension(o),h=a.getDimensionForVersion()-7;let l=null;if(a.getAlignmentPatternCenters().length>0){const t=n.getX()-r.getX()+i.getX(),e=n.getY()-r.getY()+i.getY(),o=1-3/h,a=Math.floor(r.getX()+o*(t-r.getX())),c=Math.floor(r.getY()+o*(e-r.getY()));for(let t=4;t<=16;t<<=1)try{l=this.findAlignmentInRegion(s,a,c,t);break}catch(t){if(!(t instanceof N))throw t}}const c=t.createTransform(r,n,i,l,o),d=t.sampleGrid(this.image,c,o);let u;return u=null===l?[i,r,n]:[i,r,n,l],new $(d,u)}static createTransform(t,e,r,n,i){const s=i-3.5;let o,a,h,l;return null!==n?(o=n.getX(),a=n.getY(),h=s-3,l=h):(o=e.getX()-t.getX()+r.getX(),a=e.getY()-t.getY()+r.getY(),h=s,l=s),nt.quadrilateralToQuadrilateral(3.5,3.5,s,3.5,h,l,3.5,s,t.getX(),t.getY(),e.getX(),e.getY(),o,a,r.getX(),r.getY())}static sampleGrid(t,e,r){return st.getInstance().sampleGridWithTransform(t,r,r,e)}static computeDimension(t,e,r,n){const i=q.round(J.distance(t,e)/n),s=q.round(J.distance(t,r)/n);let o=Math.floor((i+s)/2)+7;switch(3&o){case 0:o++;break;case 2:o--;break;case 3:throw new N("Dimensions could be not found.")}return o}calculateModuleSize(t,e,r){return(this.calculateModuleSizeOneWay(t,e)+this.calculateModuleSizeOneWay(t,r))/2}calculateModuleSizeOneWay(t,e){const r=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(t.getX()),Math.floor(t.getY()),Math.floor(e.getX()),Math.floor(e.getY())),n=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(e.getX()),Math.floor(e.getY()),Math.floor(t.getX()),Math.floor(t.getY()));return isNaN(r)?n/7:isNaN(n)?r/7:(r+n)/14}sizeOfBlackWhiteBlackRunBothWays(t,e,r,n){let i=this.sizeOfBlackWhiteBlackRun(t,e,r,n),s=1,o=t-(r-t);o<0?(s=t/(t-o),o=0):o>=this.image.getWidth()&&(s=(this.image.getWidth()-1-t)/(o-t),o=this.image.getWidth()-1);let a=Math.floor(e-(n-e)*s);return s=1,a<0?(s=e/(e-a),a=0):a>=this.image.getHeight()&&(s=(this.image.getHeight()-1-e)/(a-e),a=this.image.getHeight()-1),o=Math.floor(t+(o-t)*s),i+=this.sizeOfBlackWhiteBlackRun(t,e,o,a),i-1}sizeOfBlackWhiteBlackRun(t,e,r,n){const i=Math.abs(n-e)>Math.abs(r-t);if(i){let i=t;t=e,e=i,i=r,r=n,n=i}const s=Math.abs(r-t),o=Math.abs(n-e);let a=-s/2;const h=t0){if(u===n)break;u+=l,a-=s}}return 2===c?q.distance(r+h,n,t,e):NaN}findAlignmentInRegion(t,e,r,n){const i=Math.floor(n*t),s=Math.max(0,e-i),o=Math.min(this.image.getWidth()-1,e+i);if(o-s<3*t)throw new N("Alignment top exceeds estimated module size.");const a=Math.max(0,r-i),h=Math.min(this.image.getHeight()-1,r+i);if(h-a<3*t)throw new N("Alignment bottom exceeds estimated module size.");return new Oe(this.image,s,a,o-s,h-a,t,this.resultPointCallback).find()}};class Fe{constructor(){this.decoder=new Me}getDecoder(){return this.decoder}decode(t,e){let r,n;if(null!=e&&void 0!==e.get(E.PURE_BARCODE)){const i=Fe.extractPureBits(t.getBlackMatrix());r=this.decoder.decodeBitMatrix(i,e),n=Fe.NO_POINTS}else{const i=new Le(t.getBlackMatrix()).detect(e);r=this.decoder.decodeBitMatrix(i.getBits(),e),n=i.getPoints()}r.getOther()instanceof De&&r.getOther().applyMirroredCorrection(n);const i=new F(r.getText(),r.getRawBytes(),void 0,n,x.QR_CODE,void 0),s=r.getByteSegments();null!==s&&i.putMetadata(U.BYTE_SEGMENTS,s);const o=r.getECLevel();return null!==o&&i.putMetadata(U.ERROR_CORRECTION_LEVEL,o),r.hasStructuredAppend()&&(i.putMetadata(U.STRUCTURED_APPEND_SEQUENCE,r.getStructuredAppendSequenceNumber()),i.putMetadata(U.STRUCTURED_APPEND_PARITY,r.getStructuredAppendParity())),i}reset(){}static extractPureBits(t){const e=t.getTopLeftOnBit(),r=t.getBottomRightOnBit();if(null===e||null===r)throw new N;const n=this.moduleSize(e,t);let i=e[1],s=r[1],o=e[0],a=r[0];if(o>=a||i>=s)throw new N;if(s-i!==a-o&&(a=o+(s-i),a>=t.getWidth()))throw new N;const h=Math.round((a-o+1)/n),l=Math.round((s-i+1)/n);if(h<=0||l<=0)throw new N;if(l!==h)throw new N;const c=Math.floor(n/2);i+=c,o+=c;const d=o+Math.floor((h-1)*n)-a;if(d>0){if(d>c)throw new N;o-=d}const u=i+Math.floor((l-1)*n)-s;if(u>0){if(u>c)throw new N;i-=u}const g=new R(h,l);for(let e=0;e>2&7,this.dataMask=3&t}static computeBCHFormatWord(t){let e=t<<10;for(let t=4;t>=0;t--)e>>t+10&1&&(e^=ve.BCH_GENERATOR<9&&(e.setRegion(9,0,t-9,1),e.setRegion(0,9,1,t-9)),e}static getVersionForIndicator(t){if(t<0||t>7)throw new m;const[e]=ke.VERSION_INFO[t];return new ke(e,t,ke.EC_BLOCKS[t])}static getVersionForDimension(t){switch(t){case 11:return ke.getVersionForIndicator(0);case 13:return ke.getVersionForIndicator(1);case 15:return ke.getVersionForIndicator(3);case 17:return ke.getVersionForIndicator(5);default:throw new m}}toString(){return"M"+this.versionNumber}}ke.VERSION_INFO=[[1,null],[2,"L"],[2,"M"],[3,"L"],[3,"M"],[4,"L"],[4,"M"],[4,"Q"]],ke.EC_BLOCKS=[new Ee(2,new me(1,3)),new Ee(5,new me(1,5)),new Ee(6,new me(1,4)),new Ee(6,new me(1,11)),new Ee(8,new me(1,9)),new Ee(8,new me(1,16)),new Ee(10,new me(1,14)),new Ee(14,new me(1,10))],ke.MODE_INDICATOR_BITS=[0,1,2,3];class xe{constructor(t,e){this.maskIndex=t,this.isMasked=e}static forIndex(t){if(t<0||t>=xe.MASKS.length)throw new Error("Invalid Micro QR mask index: "+t);return xe.MASKS[t]}unmaskBitMatrix(t,e){for(let r=0;r!(1&t)),new xe(1,(t,e)=>(Math.floor(t/2)+Math.floor(e/3))%2==0),new xe(2,(t,e)=>{const r=t*e;return((1&r)+r%3)%2==0}),new xe(3,(t,e)=>((t+e&1)+t*e%3)%2==0)];class He{constructor(t){this.bitMatrix=t,this.parsedFormatInfo=null,this.parsedVersion=null;const e=t.getHeight();if(e<11||e>17||e%2!=1)throw new m}readFormatInformation(){if(null!==this.parsedFormatInfo)return this.parsedFormatInfo;let t=0;for(let e=1;e<=8;e++)t=this.copyBit(e,8,t);for(let e=7;e>=1;e--)t=this.copyBit(8,e,t);const e=ve.decodeFormatInformation(t);if(null!==e)return this.parsedFormatInfo=e,this.parsedVersion=ke.getVersionForIndicator(e.getVersionIndicator()),e;throw new m}copyBit(t,e,r){return this.bitMatrix.get(t,e)?r<<1|1:r<<1}readCodewords(){const t=this.readFormatInformation(),e=this.parsedVersion,r=xe.forIndex(t.getDataMask()),n=this.bitMatrix.getHeight();r.unmaskBitMatrix(this.bitMatrix,n);const i=e.buildFunctionPattern(),s=e.getNumDataCodewords(),o=1===e.getVersionNumber()||3===e.getVersionNumber();let a=!0;const h=new Uint8Array(e.getTotalCodewords());let l=0,c=0,d=0;for(let t=n-1;t>0;t-=2){for(let e=0;e=3;){if(t.available()<10)throw new m;const r=t.readBits(10);if(r>=1e3)throw new m;e.append(Ue.toChar(Math.floor(r/100))),e.append(Ue.toChar(Math.floor(r/10)%10)),e.append(Ue.toChar(r%10)),n-=3}if(2===n){if(t.available()<7)throw new m;const r=t.readBits(7);if(r>=100)throw new m;e.append(Ue.toChar(Math.floor(r/10))),e.append(Ue.toChar(r%10))}else if(1===n){if(t.available()<4)throw new m;const r=t.readBits(4);if(r>=10)throw new m;e.append(Ue.toChar(r))}}static decodeAlphanumeric(t,e,r){let n=r;for(;n>1;){if(t.available()<11)throw new m;const r=t.readBits(11);e.append(Ue.toAlphaNum(Math.floor(r/45))),e.append(Ue.toAlphaNum(r%45)),n-=2}if(1===n){if(t.available()<6)throw new m;e.append(Ue.toAlphaNum(t.readBits(6)))}}static decodeByte(t,e,r,n,i){if(8*n>t.available())throw new m;const s=new Uint8Array(n);for(let e=0;et.available())throw new m;const n=new Uint8Array(2*r);let i=0;for(let e=0;e>8&255,n[i++]=255&r}try{e.append(S.decode(n,p.SHIFT_JIS))}catch(t){throw new m}}static toChar(t){if(t>=Ue.ALPHANUMERIC_CHARS.length)throw new m;return Ue.ALPHANUMERIC_CHARS[t]}static toAlphaNum(t){if(t>=Ue.ALPHANUMERIC_CHARS.length)throw new m;return Ue.ALPHANUMERIC_CHARS[t]}}Ue.ALPHANUMERIC_CHARS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",Ue.MODE_NUMERIC=0,Ue.MODE_ALPHA=1,Ue.MODE_BYTE=2,Ue.MODE_KANJI=3;class Ve{constructor(){this.rsDecoder=new K(z.QR_CODE_FIELD_256)}decodeBitMatrix(t,e){const r=new He(t),n=r.readFormatInformation(),i=ke.getVersionForIndicator(n.getVersionIndicator()),s=r.readCodewords(),o=i.getNumDataCodewords();return i.getNumECCodewords(),1===i.getVersionNumber()||this.correctErrors(s,o),Ue.decode(s.subarray(0,o),i,null!=e?e:null)}correctErrors(t,e){const r=new Int32Array(t);try{this.rsDecoder.decode(r,t.length-e)}catch(t){throw new l}for(let n=0;ne.getCount()-t.getCount()),o[0]}foundPatternCross(t){let e=0;for(let r=0;r<5;r++){const n=t[r];if(0===n)return!1;e+=n}if(e<7)return!1;const r=e/7,n=r/2;return Math.abs(r-t[0])=0&&i.get(e,a);)o[2]++,a--;if(a<0)return NaN;for(;a>=0&&!i.get(e,a)&&o[1]<=n;)o[1]++,a--;if(a<0||o[1]>n)return NaN;for(;a>=0&&i.get(e,a)&&o[0]<=n;)o[0]++,a--;if(o[0]>n)return NaN;for(a=t+1;a=n)return NaN;for(;a=n)return NaN;const h=o[0]+o[1]+o[2]+o[3]+o[4];return 5*Math.abs(h-n)>=2*n?NaN:this.foundPatternCross(o)?this.centerFromEnd(o,a):NaN}processFinderPattern(t){const e=t.getX(),r=t.getY(),n=t.getEstimatedModuleSize();if(n<1)throw new N("Module size too small.");const i=this.determineDimension(e,r,n);if(null===i)throw new N("Cannot determine Micro QR symbol dimension.");const{dim:s,orientation:o}=i,a=(s-7)*n,h=e+[a,0,-a,0][o],l=r+[0,a,0,-a][o],c=e+[0,-a,0,a][o],d=r+[a,0,-a,0][o],u=We.createTransform(e,r,h,l,c,d,s),g=We.sampleGrid(this.image,u,s),f=[new J(e,r),new J(h,l),new J(c,d)];return new $(g,f)}determineDimension(t,e,r){const n=[[5,-3,1,0,-3,5,0,1],[3,5,0,1,-5,-3,-1,0],[-5,3,-1,0,3,-5,0,-1],[-3,-5,0,-1,5,3,1,0]];let i=null;for(let s=0;s<4;s++){const[o,a,h,l,c,d,u,g]=n[s],f=this.probeTimingLine(t+o*r,e+a*r,h,l,r),w=this.probeTimingLine(t+c*r,e+d*r,u,g,r);if(null!==f&&null!==w){const t=this.snapDimension(f,w);if(null!==t)return{dim:t,orientation:s}}else if(null===i&&(null!==f||null!==w)){const t=this.snapDimension(f,w);null!==t&&(i={dim:t,orientation:s})}}return i}snapDimension(t,e){if(null===t)return e;if(null===e)return t;if(t===e)return t;const r=Math.round((t+e)/2);return[11,13,15,17].reduce((t,e)=>Math.abs(e-r)=this.image.getWidth()||l<0||l>=this.image.getHeight())break;const c=a%2==0;if(this.image.get(h,l)!==c)break;c&&s++}if(s<2)return null;const o=8+2*s-1;if(11===o||13===o||15===o||17===o)return o;const a=[11,13,15,17].reduce((t,e)=>Math.abs(e-o)=0&&this.bitMatrix.get(i,n)&&(t[Math.floor(r/6)]|=1<<5-r%6)}}return t}}ze.BITNR=[[121,120,127,126,133,132,139,138,145,144,151,150,157,156,163,162,169,168,175,174,181,180,187,186,193,192,199,198,-2,-2],[123,122,129,128,135,134,141,140,147,146,153,152,159,158,165,164,171,170,177,176,183,182,189,188,195,194,201,200,816,-3],[125,124,131,130,137,136,143,142,149,148,155,154,161,160,167,166,173,172,179,178,185,184,191,190,197,196,203,202,818,817],[283,282,277,276,271,270,265,264,259,258,253,252,247,246,241,240,235,234,229,228,223,222,217,216,211,210,205,204,819,-3],[285,284,279,278,273,272,267,266,261,260,255,254,249,248,243,242,237,236,231,230,225,224,219,218,213,212,207,206,821,820],[287,286,281,280,275,274,269,268,263,262,257,256,251,250,245,244,239,238,233,232,227,226,221,220,215,214,209,208,822,-3],[289,288,295,294,301,300,307,306,313,312,319,318,325,324,331,330,337,336,343,342,349,348,355,354,361,360,367,366,824,823],[291,290,297,296,303,302,309,308,315,314,321,320,327,326,333,332,339,338,345,344,351,350,357,356,363,362,369,368,825,-3],[293,292,299,298,305,304,311,310,317,316,323,322,329,328,335,334,341,340,347,346,353,352,359,358,365,364,371,370,827,826],[409,408,403,402,397,396,391,390,79,78,-2,-2,13,12,37,36,2,-1,44,43,109,108,385,384,379,378,373,372,828,-3],[411,410,405,404,399,398,393,392,81,80,40,-2,15,14,39,38,3,-1,-1,45,111,110,387,386,381,380,375,374,830,829],[413,412,407,406,401,400,395,394,83,82,41,-3,-3,-3,-3,-3,5,4,47,46,113,112,389,388,383,382,377,376,831,-3],[415,414,421,420,427,426,103,102,55,54,16,-3,-3,-3,-3,-3,-3,-3,20,19,85,84,433,432,439,438,445,444,833,832],[417,416,423,422,429,428,105,104,57,56,-3,-3,-3,-3,-3,-3,-3,-3,22,21,87,86,435,434,441,440,447,446,834,-3],[419,418,425,424,431,430,107,106,59,58,-3,-3,-3,-3,-3,-3,-3,-3,-3,23,89,88,437,436,443,442,449,448,836,835],[481,480,475,474,469,468,48,-2,30,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,0,53,52,463,462,457,456,451,450,837,-3],[483,482,477,476,471,470,49,-1,-2,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-2,-1,465,464,459,458,453,452,839,838],[485,484,479,478,473,472,51,50,31,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,1,-2,42,467,466,461,460,455,454,840,-3],[487,486,493,492,499,498,97,96,61,60,-3,-3,-3,-3,-3,-3,-3,-3,-3,26,91,90,505,504,511,510,517,516,842,841],[489,488,495,494,501,500,99,98,63,62,-3,-3,-3,-3,-3,-3,-3,-3,28,27,93,92,507,506,513,512,519,518,843,-3],[491,490,497,496,503,502,101,100,65,64,17,-3,-3,-3,-3,-3,-3,-3,18,29,95,94,509,508,515,514,521,520,845,844],[559,558,553,552,547,546,541,540,73,72,32,-3,-3,-3,-3,-3,-3,10,67,66,115,114,535,534,529,528,523,522,846,-3],[561,560,555,554,549,548,543,542,75,74,-2,-1,7,6,35,34,11,-2,69,68,117,116,537,536,531,530,525,524,848,847],[563,562,557,556,551,550,545,544,77,76,-2,33,9,8,25,24,-1,-2,71,70,119,118,539,538,533,532,527,526,849,-3],[565,564,571,570,577,576,583,582,589,588,595,594,601,600,607,606,613,612,619,618,625,624,631,630,637,636,643,642,851,850],[567,566,573,572,579,578,585,584,591,590,597,596,603,602,609,608,615,614,621,620,627,626,633,632,639,638,645,644,852,-3],[569,568,575,574,581,580,587,586,593,592,599,598,605,604,611,610,617,616,623,622,629,628,635,634,641,640,647,646,854,853],[727,726,721,720,715,714,709,708,703,702,697,696,691,690,685,684,679,678,673,672,667,666,661,660,655,654,649,648,855,-3],[729,728,723,722,717,716,711,710,705,704,699,698,693,692,687,686,681,680,675,674,669,668,663,662,657,656,651,650,857,856],[731,730,725,724,719,718,713,712,707,706,701,700,695,694,689,688,683,682,677,676,671,670,665,664,659,658,653,652,858,-3],[733,732,739,738,745,744,751,750,757,756,763,762,769,768,775,774,781,780,787,786,793,792,799,798,805,804,811,810,860,859],[735,734,741,740,747,746,753,752,759,758,765,764,771,770,777,776,783,782,789,788,795,794,801,800,807,806,813,812,861,-3],[737,736,743,742,749,748,755,754,761,760,767,766,773,772,779,778,785,784,791,790,797,796,803,802,809,808,815,814,863,862]];let Ye=class t{constructor(){}static decode(e,r){const n=[];switch(r){case 2:case 3:{let i;if(2===r){const r=t.getPostCode2(e),n=t.getPostCode2Length(e);if(n>10)throw m.getFormatInstance();i=String(r).padStart(n,"0")}else i=t.getPostCode3(e);const s=String(t.getCountry(e)).padStart(3,"0"),o=String(t.getServiceClass(e)).padStart(3,"0"),a=t.getMessage(e,10,84);n.push(a),n.join("").startsWith("[)>"+t.RS+"01"+t.GS)?(n.splice(0,n.length),n.push(a.substring(0,9)),n.push(i+t.GS+s+t.GS+o+t.GS),n.push(a.substring(9))):(n.splice(0,n.length),n.push(i+t.GS+s+t.GS+o+t.GS),n.push(a));break}case 4:n.push(t.getMessage(e,1,93));break;case 5:n.push(t.getMessage(e,1,77))}return new V(e,n.join(""),null,String(r))}static getBit(t,e){return t--,e[Math.floor(t/6)]&1<<5-t%6?1:0}static getInt(e,r){let n=0;for(let i=0;i0&&i[i.length-1]===t.PAD;)i.pop();return i.join("")}};Ye.SHIFTA="￰",Ye.SHIFTB="￱",Ye.SHIFTC="￲",Ye.SHIFTD="￳",Ye.SHIFTE="￴",Ye.TWOSHIFTA="￵",Ye.THREESHIFTA="￶",Ye.LATCHA="￷",Ye.LATCHB="￸",Ye.LOCK="",Ye.ECI="",Ye.NS="",Ye.PAD="",Ye.FS="",Ye.GS="",Ye.RS="",Ye.COUNTRY_BYTES=[53,54,43,44,45,46,47,48,37,38],Ye.SERVICE_CLASS_BYTES=[55,56,57,58,59,60,49,50,51,52],Ye.POSTCODE_2_LENGTH_BYTES=[39,40,41,42,31,32],Ye.POSTCODE_2_BYTES=[33,34,35,36,25,26,27,28,29,30,19,20,21,22,23,24,13,14,15,16,17,18,7,8,9,10,11,12,1,2],Ye.POSTCODE_3_BYTES=[[39,40,41,42,31,32],[33,34,35,36,25,26],[27,28,29,30,19,20],[21,22,23,24,13,14],[15,16,17,18,7,8],[9,10,11,12,1,2]],Ye.SETS=["\rABCDEFGHIJKLMNOPQRSTUVWXYZ"+Ye.ECI+Ye.FS+Ye.GS+Ye.RS+Ye.NS+" "+Ye.PAD+"\"#$%&'()*+,-./0123456789:"+Ye.SHIFTB+Ye.SHIFTC+Ye.SHIFTD+Ye.SHIFTE+Ye.LATCHB,"`abcdefghijklmnopqrstuvwxyz"+Ye.ECI+Ye.FS+Ye.GS+Ye.RS+Ye.NS+"{"+Ye.PAD+"}~;<=>?[\\]^_ ,./:@!|"+Ye.PAD+Ye.TWOSHIFTA+Ye.THREESHIFTA+Ye.PAD+Ye.SHIFTA+Ye.SHIFTC+Ye.SHIFTD+Ye.SHIFTE+Ye.LATCHA,"ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚ"+Ye.ECI+Ye.FS+Ye.GS+Ye.RS+Ye.NS+"ÛÜÝÞߪ¬±²³µ¹º¼½¾€‚ƒ„…†‡ˆ‰"+Ye.LATCHA+" "+Ye.LOCK+Ye.SHIFTD+Ye.SHIFTE+Ye.LATCHB,"àáâãäåæçèéêëìíîïðñòóôõö÷øùú"+Ye.ECI+Ye.FS+Ye.GS+Ye.RS+Ye.NS+"ûüýþÿ¡¨«¯°´·¸»¿Š‹ŒŽ‘’“”"+Ye.LATCHA+" "+Ye.SHIFTC+Ye.LOCK+Ye.SHIFTE+Ye.LATCHB,"\0\b\t\n\v\f\r"+Ye.ECI+Ye.PAD+Ye.PAD+""+Ye.NS+Ye.FS+Ye.GS+Ye.RS+"Ÿ ¢£¤¥¦§©­®¶•–—˜™š›œž"+Ye.LATCHA+" "+Ye.SHIFTC+Ye.SHIFTD+Ye.LOCK+Ye.LATCHB];class Ze{constructor(){this.rsDecoder=new K(z.MAXICODE_FIELD_64)}decode(t,e){const r=new ze(t).readCodewords();let n=this.correctErrors(r,0,10,10,Ze.ALL);const i=15&r[0];let s;switch(i){case 2:case 3:case 4:n+=this.correctErrors(r,20,84,40,Ze.EVEN),n+=this.correctErrors(r,20,84,40,Ze.ODD),s=new Uint8Array(94);break;case 5:n+=this.correctErrors(r,20,68,56,Ze.EVEN),n+=this.correctErrors(r,20,68,56,Ze.ODD),s=new Uint8Array(78);break;default:throw m.getFormatInstance()}for(let t=0;t<10;t++)s[t]=r[t];for(let t=0;t0;){const o=je.findGuardPattern(t,i,--n,r,!1,s,h);if(null==o){n++;break}e=o}o[0]=new J(e[0],n),o[1]=new J(e[1],n),a=!0;break}}let l=n+1;if(a){let n=0,i=Int32Array.from([Math.trunc(o[0].getX()),Math.trunc(o[1].getX())]);for(;lje.SKIPPED_ROW_COUNT_MAX)break;n++}}l-=n+1,o[2]=new J(i[0],l),o[3]=new J(i[1],l)}return l-n0&&h++s?n-s:s-n;if(h>r)return 1/0;a+=h}return a/i}}je.INDEXES_START_PATTERN=Int32Array.from([0,4,1,5]),je.INDEXES_STOP_PATTERN=Int32Array.from([6,2,7,3]),je.MAX_AVG_VARIANCE=.42,je.MAX_INDIVIDUAL_VARIANCE=.8,je.START_PATTERN=Int32Array.from([8,1,1,1,1,1,1,3]),je.STOP_PATTERN=Int32Array.from([7,1,1,3,1,1,1,2,1]),je.MAX_PIXEL_DRIFT=3,je.MAX_PATTERN_DRIFT=5,je.SKIPPED_ROW_COUNT_MAX=25,je.ROW_STEP=5,je.BARCODE_MIN_HEIGHT=10;class Je{constructor(t,e){if(0===e.length)throw new a;this.field=t;let r=e.length;if(r>1&&0===e[0]){let t=1;for(;tr.length){let t=e;e=r,r=t}let n=new Int32Array(r.length),i=r.length-e.length;d.arraycopy(r,0,n,0,i);for(let t=i;t=0;e--){let r=this.getCoefficient(e);0!==r&&(r<0?(t.append(" - "),r=-r):t.length()>0&&t.append(" + "),0!==e&&1===r||t.append(r),0!==e&&(1===e?t.append("x"):(t.append("x^"),t.append(e))))}return t.toString()}}class $e{add(t,e){return(t+e)%this.modulus}subtract(t,e){return(this.modulus+t-e)%this.modulus}exp(t){return this.expTable[t]}log(t){if(0===t)throw new a;return this.logTable[t]}inverse(t){if(0===t)throw new G;return this.expTable[this.modulus-this.logTable[t]-1]}multiply(t,e){return 0===t||0===e?0:this.expTable[(this.logTable[t]+this.logTable[e])%(this.modulus-1)]}getSize(){return this.modulus}equals(t){return t===this}}class tr extends $e{constructor(t,e){super(),this.modulus=t,this.expTable=new Int32Array(t),this.logTable=new Int32Array(t);let r=1;for(let n=0;n0;t--){let r=n.evaluateAt(this.field.exp(t));i[e-t]=r,0!==r&&(s=!0)}if(!s)return 0;let o=this.field.getOne();if(null!=r)for(const e of r){let r=this.field.exp(t.length-1-e),n=new Je(this.field,new Int32Array([this.field.subtract(0,r),1]));o=o.multiply(n)}let a=new Je(this.field,i),h=this.runEuclideanAlgorithm(this.field.buildMonomial(e,1),a,e),c=h[0],d=h[1],u=this.findErrorLocations(c),g=this.findErrorMagnitudes(d,c,u);for(let e=0;e=Math.round(r/2);){let t=n,e=s;if(n=i,s=o,n.isZero())throw l.getChecksumInstance();i=t;let r=this.field.getZero(),a=n.getCoefficient(n.getDegree()),h=this.field.inverse(a);for(;i.getDegree()>=n.getDegree()&&!i.isZero();){let t=i.getDegree()-n.getDegree(),e=this.field.multiply(i.getCoefficient(i.getDegree()),h);r=r.add(this.field.buildMonomial(t,e)),i=i.subtract(n.multiplyByMonomial(t,e))}o=r.multiply(s).subtract(e).negative()}let a=o.getCoefficient(0);if(0===a)throw l.getChecksumInstance();let h=this.field.inverse(a);return[o.multiply(h),i.multiply(h)]}findErrorLocations(t){let e=t.getDegree(),r=new Int32Array(e),n=0;for(let i=1;i0){let e=r?this.topLeft:this.topRight,i=Math.trunc(e.getY()-t);i<0&&(i=0);let o=new J(e.getX(),i);r?n=o:s=o}if(e>0){let t=r?this.bottomLeft:this.bottomRight,n=Math.trunc(t.getY()+e);n>=this.image.getHeight()&&(n=this.image.getHeight()-1);let s=new J(t.getX(),n);r?i=s:o=s}return new rr(this.image,n,i,s,o)}getMinX(){return this.minX}getMaxX(){return this.maxX}getMinY(){return this.minY}getMaxY(){return this.maxY}getTopLeft(){return this.topLeft}getTopRight(){return this.topRight}getBottomLeft(){return this.bottomLeft}getBottomRight(){return this.bottomRight}}class nr{constructor(t,e,r,n){this.columnCount=t,this.errorCorrectionLevel=n,this.rowCountUpperPart=e,this.rowCountLowerPart=r,this.rowCount=e+r}getColumnCount(){return this.columnCount}getErrorCorrectionLevel(){return this.errorCorrectionLevel}getRowCount(){return this.rowCount}getRowCountUpperPart(){return this.rowCountUpperPart}getRowCountLowerPart(){return this.rowCountLowerPart}}class ir{constructor(){this.buffer=""}static form(t,e){let r=-1;return t.replace(/%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g,function(t,n,i,s,o,a){if("%%"===t)return"%";if(void 0===e[++r])return;t=s?parseInt(s.substr(1)):void 0;let h,l=o?parseInt(o.substr(1)):void 0;switch(a){case"s":h=e[r];break;case"c":h=e[r][0];break;case"f":h=parseFloat(e[r]).toFixed(t);break;case"p":h=parseFloat(e[r]).toPrecision(t);break;case"e":h=parseFloat(e[r]).toExponential(t);break;case"x":h=parseInt(e[r]).toString(l||16);break;case"d":h=parseFloat(parseInt(e[r],l||10).toPrecision(t)).toFixed(0)}h="object"==typeof h?JSON.stringify(h):(+h).toString(l);let c=parseInt(i),d=i&&i[0]+""=="0"?"0":" ";for(;h.length=0&&(e=this.codewords[n],null!=e))return e;if(n=this.imageRowToCodewordIndex(t)+r,nr,getValue:()=>n};i.getValue()>t?(t=i.getValue(),e=[],e.push(i.getKey())):i.getValue()===t&&e.push(i.getKey())}return Qe.toIntArray(e)}getConfidence(t){return this.values.get(t)}}class ar extends sr{constructor(t,e){super(t),this._isLeft=e}setRowNumbers(){for(let t of this.getCodewords())null!=t&&t.setRowNumberAsRowIndicatorColumn()}adjustCompleteIndicatorColumnRowNumbers(t){let e=this.getCodewords();this.setRowNumbers(),this.removeIncorrectCodewords(e,t);let r=this.getBoundingBox(),n=this._isLeft?r.getTopLeft():r.getTopRight(),i=this._isLeft?r.getBottomLeft():r.getBottomRight(),s=this.imageRowToCodewordIndex(Math.trunc(n.getY())),o=this.imageRowToCodewordIndex(Math.trunc(i.getY())),a=-1,h=1,l=0;for(let r=s;r=t.getRowCount()||i>r)e[r]=null;else{let t;t=h>2?(h-2)*i:i;let s=t>=r;for(let n=1;n<=t&&!s;n++)s=null!=e[r-n];s?e[r]=null:(a=n.getRowNumber(),l=1)}}}getRowHeights(){let t=this.getBarcodeMetadata();if(null==t)return null;this.adjustIncompleteIndicatorColumnRowNumbers(t);let e=new Int32Array(t.getRowCount());for(let t of this.getCodewords())if(null!=t){let r=t.getRowNumber();if(r>=e.length)continue;e[r]++}return e}adjustIncompleteIndicatorColumnRowNumbers(t){let e=this.getBoundingBox(),r=this._isLeft?e.getTopLeft():e.getTopRight(),n=this._isLeft?e.getBottomLeft():e.getBottomRight(),i=this.imageRowToCodewordIndex(Math.trunc(r.getY())),s=this.imageRowToCodewordIndex(Math.trunc(n.getY())),o=this.getCodewords(),a=-1;for(let e=i;e=t.getRowCount()?o[e]=null:a=r.getRowNumber())}}getBarcodeMetadata(){let t=this.getCodewords(),e=new or,r=new or,n=new or,i=new or;for(let s of t){if(null==s)continue;s.setRowNumberAsRowIndicatorColumn();let t=s.getValue()%30,o=s.getRowNumber();switch(this._isLeft||(o+=2),o%3){case 0:r.setValue(3*t+1);break;case 1:i.setValue(t/3),n.setValue(t%3);break;case 2:e.setValue(t+1)}}if(0===e.getValue().length||0===r.getValue().length||0===n.getValue().length||0===i.getValue().length||e.getValue()[0]<1||r.getValue()[0]+n.getValue()[0]Qe.MAX_ROWS_IN_BARCODE)return null;let s=new nr(e.getValue()[0],r.getValue()[0],n.getValue()[0],i.getValue()[0]);return this.removeIncorrectCodewords(t,s),s}removeIncorrectCodewords(t,e){for(let r=0;re.getRowCount())t[r]=null;else switch(this._isLeft||(s+=2),s%3){case 0:3*i+1!==e.getRowCountUpperPart()&&(t[r]=null);break;case 1:Math.trunc(i/3)===e.getErrorCorrectionLevel()&&i%3===e.getRowCountLowerPart()||(t[r]=null);break;case 2:i+1!==e.getColumnCount()&&(t[r]=null)}}}isLeft(){return this._isLeft}toString(){return"IsLeft: "+this._isLeft+"\n"+super.toString()}}class hr{constructor(t,e){this.ADJUST_ROW_NUMBER_SKIP=2,this.barcodeMetadata=t,this.barcodeColumnCount=t.getColumnCount(),this.boundingBox=e,this.detectionResultColumns=new Array(this.barcodeColumnCount+2)}getDetectionResultColumns(){this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[0]),this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[this.barcodeColumnCount+1]);let t,e=Qe.MAX_CODEWORDS_IN_BARCODE;do{t=e,e=this.adjustRowNumbersAndGetCount()}while(e>0&&e0&&i0&&(o[0]=r[e-1],o[4]=i[e-1],o[5]=s[e-1]),e>1&&(o[8]=r[e-2],o[10]=i[e-2],o[11]=s[e-2]),e>=1;r=1&e,cr.RATIOS_TABLE[t]||(cr.RATIOS_TABLE[t]=new Array(Qe.BARS_IN_MODULE)),cr.RATIOS_TABLE[t][Qe.BARS_IN_MODULE-n-1]=Math.fround(i/Qe.MODULES_IN_CODEWORD)}}this.bSymbolTableReady=!0}static getDecodedValue(t){let e=cr.getDecodedCodewordValue(cr.sampleBitCounts(t));return-1!==e?e:cr.getClosestDecodedValue(t)}static sampleBitCounts(t){let e=q.sum(t),r=new Int32Array(Qe.BARS_IN_MODULE),n=0,i=0;for(let s=0;s1)for(let n=0;n=n)break}enew Array(Qe.BARS_IN_MODULE));class dr{constructor(){this.segmentCount=-1,this.fileSize=-1,this.timestamp=-1,this.checksum=-1}getSegmentIndex(){return this.segmentIndex}setSegmentIndex(t){this.segmentIndex=t}getFileId(){return this.fileId}setFileId(t){this.fileId=t}getOptionalData(){return this.optionalData}setOptionalData(t){this.optionalData=t}isLastSegment(){return this.lastSegment}setLastSegment(t){this.lastSegment=t}getSegmentCount(){return this.segmentCount}setSegmentCount(t){this.segmentCount=t}getSender(){return this.sender||null}setSender(t){this.sender=t}getAddressee(){return this.addressee||null}setAddressee(t){this.addressee=t}getFileName(){return this.fileName}setFileName(t){this.fileName=t}getFileSize(){return this.fileSize}setFileSize(t){this.fileSize=t}getChecksum(){return this.checksum}setChecksum(t){this.checksum=t}getTimestamp(){return this.timestamp}setTimestamp(t){this.timestamp=t}}class ur{static parseLong(t,e=void 0){return parseInt(t,e)}}class gr extends s{}gr.kind="NullPointerException";class fr{writeBytes(t){this.writeBytesOffset(t,0,t.length)}writeBytesOffset(t,e,r){if(null==t)throw new gr;if(e<0||e>t.length||r<0||e+r>t.length||e+r<0)throw new u;if(0!==r)for(let n=0;n0&&this.grow(t)}grow(t){let e=this.buf.length<<1;if(e-t<0&&(e=t),e<0){if(t<0)throw new wr;e=w.MAX_VALUE}this.buf=f.copyOfUint8Array(this.buf,e)}write(t){this.ensureCapacity(this.count+1),this.buf[this.count]=t,this.count+=1}writeBytesOffset(t,e,r){if(e<0||e>t.length||r<0||e+r-t.length>0)throw new u;this.ensureCapacity(this.count+r),d.arraycopy(t,e,this.buf,this.count,r),this.count+=r}writeTo(t){t.writeBytesOffset(this.buf,0,this.count)}reset(){this.count=0}toByteArray(){return f.copyOfUint8Array(this.buf,this.count)}size(){return this.count}toString(t){return t?"string"==typeof t?this.toString_string(t):this.toString_number(t):this.toString_void()}toString_void(){return new String(this.buf).toString()}toString_string(t){return new String(this.buf).toString()}toString_number(t){return new String(this.buf).toString()}close(){}}var Ar;function Er(){if("undefined"!=typeof window)return window.BigInt||null;if("undefined"!=typeof globalThis)return globalThis.BigInt||null;if("undefined"!=typeof self)return self.BigInt||null;throw new Error("Can't search globals for BigInt!")}let mr;function Ir(t){if(void 0===mr&&(mr=Er()),null===mr)throw new Error("BigInt is not supported!");return mr(t)}!function(t){t[t.ALPHA=0]="ALPHA",t[t.LOWER=1]="LOWER",t[t.MIXED=2]="MIXED",t[t.PUNCT=3]="PUNCT",t[t.ALPHA_SHIFT=4]="ALPHA_SHIFT",t[t.PUNCT_SHIFT=5]="PUNCT_SHIFT"}(Ar||(Ar={}));class _r{static decode(t,e){let r=new T(""),n=I.ISO8859_1;r.enableDecoding(n);let i=1,s=t[i++],o=new dr;for(;it[0])throw m.getFormatInstance();let n=new Int32Array(_r.NUMBER_OF_SEQUENCE_CODEWORDS);for(let r=0;r<_r.NUMBER_OF_SEQUENCE_CODEWORDS;r++,e++)n[r]=t[e];r.setSegmentIndex(w.parseInt(_r.decodeBase900toBase10(n,_r.NUMBER_OF_SEQUENCE_CODEWORDS)));let i=new T;e=_r.textCompaction(t,e,i),r.setFileId(i.toString());let s=-1;for(t[e]===_r.BEGIN_MACRO_PDF417_OPTIONAL_FIELD&&(s=e+1);e0){for(let t=0;t<6;++t)s.write(Number(Ir(a)>>Ir(8*(5-t))));a=0,o=0}}n===e[0]&&r<_r.TEXT_COMPACTION_MODE_LATCH&&(t[o++]=r);for(let e=0;e0){for(let t=0;t<6;++t)s.write(Number(Ir(a)>>Ir(8*(5-t))));a=0,o=0}}}return i.append(S.decode(s.toByteArray(),r)),n}static numericCompaction(t,e,r){let n=0,i=!1,s=new Int32Array(_r.MAX_NUMERIC_CODEWORDS);for(;e0&&(r.append(_r.decodeBase900toBase10(s,n)),n=0)}return e}static decodeBase900toBase10(t,e){let r=Ir(0);for(let n=0;n@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'",_r.MIXED_CHARS="0123456789&\r\t,:#-.$/+%*=^",_r.EXP900=Er()?function(){let t=[];t[0]=Ir(1);let e=Ir(900);t[1]=e;for(let r=2;r<16;r++)t[r]=t[r-1]*e;return t}():[],_r.NUMBER_OF_SEQUENCE_CODEWORDS=2;class Sr{constructor(){}static decode(t,e,r,n,i,s,o){let a,h=new rr(t,e,r,n,i),l=null,c=null;for(let r=!0;;r=!1){if(null!=e&&(l=Sr.getRowIndicatorColumn(t,h,e,!0,s,o)),null!=n&&(c=Sr.getRowIndicatorColumn(t,h,n,!1,s,o)),a=Sr.merge(l,c),null==a)throw N.getNotFoundInstance();let i=a.getBoundingBox();if(!r||null==i||!(i.getMinY()h.getMaxY()))break;h=i}a.setBoundingBox(h);let d=a.getBarcodeColumnCount()+1;a.setDetectionResultColumn(0,l),a.setDetectionResultColumn(d,c);let u=null!=l;for(let e=1;e<=d;e++){let r,n=u?e:d-e;if(void 0!==a.getDetectionResultColumn(n))continue;r=0===n||n===d?new ar(h,0===n):new sr(h),a.setDetectionResultColumn(n,r);let i=-1,l=i;for(let e=h.getMinY();e<=h.getMaxY();e++){if(i=Sr.getStartColumn(a,n,e,u),i<0||i>h.getMaxX()){if(-1===l)continue;i=l}let c=Sr.detectCodeword(t,h.getMinX(),h.getMaxX(),u,i,e,s,o);null!=c&&(r.setCodeword(e,c),l=i,s=Math.min(s,c.getWidth()),o=Math.max(o,c.getWidth()))}}return Sr.createDecoderResult(a)}static merge(t,e){if(null==t&&null==e)return null;let r=Sr.getBarcodeMetadata(t,e);if(null==r)return null;let n=rr.merge(Sr.adjustBoundingBox(t),Sr.adjustBoundingBox(e));return new hr(r,n)}static adjustBoundingBox(t){if(null==t)return null;let e=t.getRowHeights();if(null==e)return null;let r=Sr.getMax(e),n=0;for(let t of e)if(n+=r-t,t>0)break;let i=t.getCodewords();for(let t=0;n>0&&null==i[t];t++)n--;let s=0;for(let t=e.length-1;t>=0&&(s+=r-e[t],!(e[t]>0));t--);for(let t=i.length-1;s>0&&null==i[t];t--)s--;return t.getBoundingBox().addMissingRows(n,s,t.isLeft())}static getMax(t){let e=-1;for(let r of t)e=Math.max(e,r);return e}static getBarcodeMetadata(t,e){let r,n;return null==t||null==(r=t.getBarcodeMetadata())?null==e?null:e.getBarcodeMetadata():null==e||null==(n=e.getBarcodeMetadata())?r:r.getColumnCount()!==n.getColumnCount()&&r.getErrorCorrectionLevel()!==n.getErrorCorrectionLevel()&&r.getRowCount()!==n.getRowCount()?null:r}static getRowIndicatorColumn(t,e,r,n,i,s){let o=new ar(e,n);for(let a=0;a<2;a++){let h=0===a?1:-1,l=Math.trunc(Math.trunc(r.getX()));for(let a=Math.trunc(Math.trunc(r.getY()));a<=e.getMaxY()&&a>=e.getMinY();a+=h){let e=Sr.detectCodeword(t,0,t.getWidth(),n,l,a,i,s);null!=e&&(o.setCodeword(a,e),l=n?e.getStartX():e.getEndX())}}return o}static adjustCodewordCount(t,e){let r=e[0][1],n=r.getValue(),i=t.getBarcodeColumnCount()*t.getBarcodeRowCount()-Sr.getNumberOfECCodeWords(t.getBarcodeECLevel());if(0===n.length){if(i<1||i>Qe.MAX_CODEWORDS_IN_BARCODE)throw N.getNotFoundInstance();r.setValue(i)}else n[0]!==i&&r.setValue(i)}static createDecoderResult(t){let e=Sr.createBarcodeMatrix(t);Sr.adjustCodewordCount(t,e);let r=new Array,n=new Int32Array(t.getBarcodeRowCount()*t.getBarcodeColumnCount()),i=[],s=new Array;for(let o=0;o0;){for(let t=0;tnew Array(t.getBarcodeColumnCount()+2));for(let t=0;t=0){if(n>=e.length)continue;e[n][r].setValue(t.getValue())}}r++}return e}static isValidBarcodeColumn(t,e){return e>=0&&e<=t.getBarcodeColumnCount()+1}static getStartColumn(t,e,r,n){let i=n?1:-1,s=null;if(Sr.isValidBarcodeColumn(t,e-i)&&(s=t.getDetectionResultColumn(e-i).getCodeword(r)),null!=s)return n?s.getEndX():s.getStartX();if(s=t.getDetectionResultColumn(e).getCodewordNearby(r),null!=s)return n?s.getStartX():s.getEndX();if(Sr.isValidBarcodeColumn(t,e-i)&&(s=t.getDetectionResultColumn(e-i).getCodewordNearby(r)),null!=s)return n?s.getEndX():s.getStartX();let o=0;for(;Sr.isValidBarcodeColumn(t,e-i);){e-=i;for(let r of t.getDetectionResultColumn(e).getCodewords())if(null!=r)return(n?r.getEndX():r.getStartX())+i*o*(r.getEndX()-r.getStartX());o++}return n?t.getBoundingBox().getMinX():t.getBoundingBox().getMaxX()}static detectCodeword(t,e,r,n,i,s,o,a){i=Sr.adjustCodewordStartColumn(t,e,r,n,i,s);let h,l=Sr.getModuleBitCount(t,e,r,n,i,s);if(null==l)return null;let c=q.sum(l);if(n)h=i+c;else{for(let t=0;t=e)&&h=e:oSr.CODEWORD_SKEW_SIZE)return i;o+=a}a=-a,n=!n}return o}static checkCodewordSkew(t,e,r){return e-Sr.CODEWORD_SKEW_SIZE<=t&&t<=r+Sr.CODEWORD_SKEW_SIZE}static decodeCodewords(t,e,r){if(0===t.length)throw m.getFormatInstance();let n=1<r/2+Sr.MAX_ERRORS||r<0||r>Sr.MAX_EC_CODEWORDS)throw l.getChecksumInstance();return Sr.errorCorrection.decode(t,r,e)}static verifyCodewordCount(t,e){if(t.length<4)throw m.getFormatInstance();let r=t[0];if(r>t.length)throw m.getFormatInstance();if(0===r){if(!(e>=1;return e}static getCodewordBucketNumber(t){return t instanceof Int32Array?this.getCodewordBucketNumber_Int32Array(t):this.getCodewordBucketNumber_number(t)}static getCodewordBucketNumber_number(t){return Sr.getCodewordBucketNumber(Sr.getBitCountForCodeword(t))}static getCodewordBucketNumber_Int32Array(t){return(t[0]-t[2]+t[4]-t[6]+9)%9}static toString(t){let e=new ir;for(let r=0;rt)}static getMaxWidth(t,e){return null==t||null==e?0:Math.trunc(Math.abs(t.getX()-e.getX()))}static getMinWidth(t,e){return null==t||null==e?w.MAX_VALUE:Math.trunc(Math.abs(t.getX()-e.getX()))}static getMaxCodewordWidth(t){return Math.floor(Math.max(Math.max(pr.getMaxWidth(t[0],t[4]),pr.getMaxWidth(t[6],t[2])*Qe.MODULES_IN_CODEWORD/Qe.MODULES_IN_STOP_PATTERN),Math.max(pr.getMaxWidth(t[1],t[5]),pr.getMaxWidth(t[7],t[3])*Qe.MODULES_IN_CODEWORD/Qe.MODULES_IN_STOP_PATTERN)))}static getMinCodewordWidth(t){return Math.floor(Math.min(Math.min(pr.getMinWidth(t[0],t[4]),pr.getMinWidth(t[6],t[2])*Qe.MODULES_IN_CODEWORD/Qe.MODULES_IN_STOP_PATTERN),Math.min(pr.getMinWidth(t[1],t[5]),pr.getMinWidth(t[7],t[3])*Qe.MODULES_IN_CODEWORD/Qe.MODULES_IN_STOP_PATTERN)))}reset(){}}class Tr extends s{}Tr.kind="ReaderException";class Rr{decode(t,e){return this.hints!==e&&this.setHints(e),this.decodeInternal(t)}decodeWithState(t){return null!==this.readers&&void 0!==this.readers||this.setHints(null),this.decodeInternal(t)}setHints(t){this.hints=t;const e=null!=t&&void 0!==t.get(E.TRY_HARDER),r=null==t?null:t.get(E.POSSIBLE_FORMATS),n=new Array;if(null!=r){const i=r.some(t=>t===x.UPC_A||t===x.UPC_E||t===x.EAN_13||t===x.EAN_8||t===x.CODABAR||t===x.CODE_39||t===x.CODE_93||t===x.CODE_128||t===x.ITF||t===x.RSS_14||t===x.RSS_EXPANDED);i&&!e&&n.push(new re(t)),r.includes(x.QR_CODE)&&n.push(new Fe),r.includes(x.MICRO_QR_CODE)&&n.push(new Ge),r.includes(x.DATA_MATRIX)&&n.push(new ge),r.includes(x.AZTEC)&&n.push(new ht),r.includes(x.PDF_417)&&n.push(new pr),r.includes(x.MAXICODE)&&n.push(new Ke),i&&e&&n.push(new re(t))}0===n.length&&(e||n.push(new re(t)),n.push(new Fe),n.push(new Ge),n.push(new ge),n.push(new ht),n.push(new pr),n.push(new Ke),e&&n.push(new re(t))),this.readers=n}reset(){if(null!==this.readers)for(const t of this.readers)t.reset()}decodeInternal(t){if(null===this.readers)throw new Tr("No readers where selected, nothing can be read.");for(const e of this.readers)try{return e.decode(t,this.hints)}catch(t){if(t instanceof Tr)continue;console.warn("MultiFormatReader: non-ReaderException from reader:",t);continue}throw new N("No MultiFormat Readers were able to detect the code.")}}var Nr;!function(t){t[t.ERROR_CORRECTION=0]="ERROR_CORRECTION",t[t.CHARACTER_SET=1]="CHARACTER_SET",t[t.DATA_MATRIX_SHAPE=2]="DATA_MATRIX_SHAPE",t[t.DATA_MATRIX_COMPACT=3]="DATA_MATRIX_COMPACT",t[t.MIN_SIZE=4]="MIN_SIZE",t[t.MAX_SIZE=5]="MAX_SIZE",t[t.MARGIN=6]="MARGIN",t[t.PDF417_COMPACT=7]="PDF417_COMPACT",t[t.PDF417_COMPACTION=8]="PDF417_COMPACTION",t[t.PDF417_DIMENSIONS=9]="PDF417_DIMENSIONS",t[t.AZTEC_LAYERS=10]="AZTEC_LAYERS",t[t.QR_VERSION=11]="QR_VERSION",t[t.GS1_FORMAT=12]="GS1_FORMAT",t[t.FORCE_C40=13]="FORCE_C40"}(Nr||(Nr={}));var Dr=Nr;class Mr{constructor(t){this.field=t,this.cachedGenerators=[],this.cachedGenerators.push(new W(t,Int32Array.from([1])))}buildGenerator(t){const e=this.cachedGenerators;if(t>=e.length){let r=e[e.length-1];const n=this.field;for(let i=e.length;i<=t;i++){const t=r.multiply(new W(n,Int32Array.from([1,n.exp(i-1+n.getGeneratorBase())])));e.push(t),r=t}}return e[t]}encode(t,e){if(0===e)throw new a("No error correction bytes");const r=t.length-e;if(r<=0)throw new a("No data bytes provided");const n=this.buildGenerator(e),i=new Int32Array(r);d.arraycopy(t,0,i,0,r);let s=new W(this.field,i);s=s.multiplyByMonomial(e,1);const o=s.divide(n)[1].getCoefficients(),h=e-o.length;for(let e=0;e=5&&(r+=yr.N1+(n-5)),n=1,o=i)}n>=5&&(r+=yr.N1+(n-5))}return r}}yr.N1=3,yr.N2=3,yr.N3=40,yr.N4=10;class Or{constructor(t,e){this.width=t,this.height=e;const r=new Array(e);for(let n=0;n!==e;n++)r[n]=new Uint8Array(t);this.bytes=r}getHeight(){return this.height}getWidth(){return this.width}get(t,e){return this.bytes[e][t]}getArray(){return this.bytes}setNumber(t,e,r){this.bytes[e][t]=r}setBoolean(t,e,r){this.bytes[e][t]=r?1:0}clear(t){for(const e of this.bytes)f.fill(e,t)}equals(t){if(!(t instanceof Or))return!1;const e=t;if(this.width!==e.width)return!1;if(this.height!==e.height)return!1;for(let t=0,r=this.height;t>\n"),t.toString()}setMode(t){this.mode=t}setECLevel(t){this.ecLevel=t}setVersion(t){this.version=t}setMaskPattern(t){this.maskPattern=t}setMatrix(t){this.matrix=t}static isValidMaskPattern(t){return t>=0&&t0;){for(6===s&&(s-=1);o>=0&&o=r;)t^=e<=0)for(let t=0;t!==r;t++){const r=n[t];r>=0&&Pr.isEmpty(e.get(r,i))&&Pr.embedPositionAdjustmentPattern(r-2,i-2,e)}}}}Pr.POSITION_DETECTION_PATTERN=Array.from([Int32Array.from([1,1,1,1,1,1,1]),Int32Array.from([1,0,0,0,0,0,1]),Int32Array.from([1,0,1,1,1,0,1]),Int32Array.from([1,0,1,1,1,0,1]),Int32Array.from([1,0,1,1,1,0,1]),Int32Array.from([1,0,0,0,0,0,1]),Int32Array.from([1,1,1,1,1,1,1])]),Pr.POSITION_ADJUSTMENT_PATTERN=Array.from([Int32Array.from([1,1,1,1,1]),Int32Array.from([1,0,0,0,1]),Int32Array.from([1,0,1,0,1]),Int32Array.from([1,0,0,0,1]),Int32Array.from([1,1,1,1,1])]),Pr.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE=Array.from([Int32Array.from([-1,-1,-1,-1,-1,-1,-1]),Int32Array.from([6,18,-1,-1,-1,-1,-1]),Int32Array.from([6,22,-1,-1,-1,-1,-1]),Int32Array.from([6,26,-1,-1,-1,-1,-1]),Int32Array.from([6,30,-1,-1,-1,-1,-1]),Int32Array.from([6,34,-1,-1,-1,-1,-1]),Int32Array.from([6,22,38,-1,-1,-1,-1]),Int32Array.from([6,24,42,-1,-1,-1,-1]),Int32Array.from([6,26,46,-1,-1,-1,-1]),Int32Array.from([6,28,50,-1,-1,-1,-1]),Int32Array.from([6,30,54,-1,-1,-1,-1]),Int32Array.from([6,32,58,-1,-1,-1,-1]),Int32Array.from([6,34,62,-1,-1,-1,-1]),Int32Array.from([6,26,46,66,-1,-1,-1]),Int32Array.from([6,26,48,70,-1,-1,-1]),Int32Array.from([6,26,50,74,-1,-1,-1]),Int32Array.from([6,30,54,78,-1,-1,-1]),Int32Array.from([6,30,56,82,-1,-1,-1]),Int32Array.from([6,30,58,86,-1,-1,-1]),Int32Array.from([6,34,62,90,-1,-1,-1]),Int32Array.from([6,28,50,72,94,-1,-1]),Int32Array.from([6,26,50,74,98,-1,-1]),Int32Array.from([6,30,54,78,102,-1,-1]),Int32Array.from([6,28,54,80,106,-1,-1]),Int32Array.from([6,32,58,84,110,-1,-1]),Int32Array.from([6,30,58,86,114,-1,-1]),Int32Array.from([6,34,62,90,118,-1,-1]),Int32Array.from([6,26,50,74,98,122,-1]),Int32Array.from([6,30,54,78,102,126,-1]),Int32Array.from([6,26,52,78,104,130,-1]),Int32Array.from([6,30,56,82,108,134,-1]),Int32Array.from([6,34,60,86,112,138,-1]),Int32Array.from([6,30,58,86,114,142,-1]),Int32Array.from([6,34,62,90,118,146,-1]),Int32Array.from([6,30,54,78,102,126,150]),Int32Array.from([6,24,50,76,102,128,154]),Int32Array.from([6,28,54,80,106,132,158]),Int32Array.from([6,32,58,84,110,136,162]),Int32Array.from([6,26,54,82,110,138,166]),Int32Array.from([6,30,58,86,114,142,170])]),Pr.TYPE_INFO_COORDINATES=Array.from([Int32Array.from([8,0]),Int32Array.from([8,1]),Int32Array.from([8,2]),Int32Array.from([8,3]),Int32Array.from([8,4]),Int32Array.from([8,5]),Int32Array.from([8,7]),Int32Array.from([8,8]),Int32Array.from([7,8]),Int32Array.from([5,8]),Int32Array.from([4,8]),Int32Array.from([3,8]),Int32Array.from([2,8]),Int32Array.from([1,8]),Int32Array.from([0,8])]),Pr.VERSION_INFO_POLY=7973,Pr.TYPE_INFO_POLY=1335,Pr.TYPE_INFO_MASK_PATTERN=21522;class Lr{constructor(t,e){this.dataBytes=t,this.errorCorrectionBytes=e}getDataBytes(){return this.dataBytes}getErrorCorrectionBytes(){return this.errorCorrectionBytes}}let Fr=class t{constructor(){}static calculateMaskPenalty(t){return yr.applyMaskPenaltyRule1(t)+yr.applyMaskPenaltyRule2(t)+yr.applyMaskPenaltyRule3(t)+yr.applyMaskPenaltyRule4(t)}static encode(e,r,n=null){let i=t.DEFAULT_BYTE_MODE_ENCODING;const s=null!==n&&void 0!==n.get(Dr.CHARACTER_SET);s&&(i=n.get(Dr.CHARACTER_SET).toString());const o=this.chooseMode(e,i),a=new C;if(o===Re.BYTE&&(s||t.DEFAULT_BYTE_MODE_ENCODING!==i)){const t=I.getCharacterSetECIByName(i);void 0!==t&&this.appendECI(t,a)}this.appendModeInfo(o,a);const h=new C;let l;if(this.appendBytes(e,o,h,i),null!==n&&void 0!==n.get(Dr.QR_VERSION)){const t=Number.parseInt(n.get(Dr.QR_VERSION).toString(),10);l=Ie.getVersionForNumber(t);const e=this.calculateBitsNeeded(o,a,h,l);if(!this.willFit(e,l,r))throw new Br("Data too big for requested version")}else l=this.recommendVersion(r,o,a,h);const c=new C;c.appendBitArray(a);const d=o===Re.BYTE?h.getSizeInBytes():e.length;this.appendLengthInfo(d,l,o,c),c.appendBitArray(h);const u=l.getECBlocksForLevel(r),g=l.getTotalCodewords()-u.getTotalECCodewords();this.terminateBits(g,c);const f=this.interleaveWithECBytes(c,l.getTotalCodewords(),g,u.getNumBlocks()),w=new br;w.setECLevel(r),w.setMode(o),w.setVersion(l);const A=l.getDimensionForVersion(),E=new Or(A,A),m=this.chooseMaskPattern(f,r,l,E);return w.setMaskPattern(m),Pr.buildMatrix(f,r,l,m,E),w.setMatrix(E),w}static recommendVersion(t,e,r,n){const i=this.calculateBitsNeeded(e,r,n,Ie.getVersionForNumber(1)),s=this.chooseVersion(i,t),o=this.calculateBitsNeeded(e,r,n,s);return this.chooseVersion(o,t)}static calculateBitsNeeded(t,e,r,n){return e.getSize()+t.getCharacterCountBits(n)+r.getSize()}static getAlphanumericCode(e){return e159)&&(r<224||r>235))return!1}return!0}static chooseMaskPattern(t,e,r,n){let i=Number.MAX_SAFE_INTEGER,s=-1;for(let o=0;o=(t+7)/8}static terminateBits(t,e){const r=8*t;if(e.getSize()>r)throw new Br("data bits cannot fit in the QR Code"+e.getSize()+" > "+r);for(let t=0;t<4&&e.getSize()0)for(let t=n;t<8;t++)e.appendBit(!1);const i=t-e.getSizeInBytes();for(let t=0;t=r)throw new Br("Block ID too large");const o=t%r,a=r-o,h=Math.floor(t/r),l=h+1,c=Math.floor(e/r),d=c+1,u=h-c,g=l-d;if(u!==g)throw new Br("EC bytes mismatch");if(r!==a+o)throw new Br("RS blocks mismatch");if(t!==(c+u)*a+(d+g)*o)throw new Br("Total bytes mismatch");n=1<=0&&r<=9}static appendNumericBytes(e,r){const n=e.length;let i=0;for(;i=33088&&n<=40956?i=n-33088:n>=57408&&n<=60351&&(i=n-49472),-1===i)throw new Br("Invalid byte sequence");const s=192*(i>>8)+(255&i);e.appendBits(s,13)}}static appendECI(t,e){e.appendBits(Re.ECI.getBits(),4),e.appendBits(t.getValue(),8)}};Fr.ALPHANUMERIC_TABLE=Int32Array.from([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,36,-1,-1,-1,37,38,-1,-1,-1,-1,39,40,-1,41,42,43,0,1,2,3,4,5,6,7,8,9,44,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1]),Fr.DEFAULT_BYTE_MODE_ENCODING=I.UTF8.getName();class vr{write(t,e,r,n=null){if(0===t.length)throw new a("Found empty contents");if(e<0||r<0)throw new a("Requested dimensions are too small: "+e+"x"+r);let i=Ce.L,s=vr.QUIET_ZONE_SIZE;null!==n&&(void 0!==n.get(Dr.ERROR_CORRECTION)&&(i=Ce.fromString(n.get(Dr.ERROR_CORRECTION).toString())),void 0!==n.get(Dr.MARGIN)&&(s=Number.parseInt(n.get(Dr.MARGIN).toString(),10)));const o=Fr.encode(t,i,n);return this.renderResult(o,e,r,s)}writeToDom(t,e,r,n,i=null){"string"==typeof t&&(t=document.querySelector(t));const s=this.write(e,r,n,i);t&&t.appendChild(s)}renderResult(t,e,r,n){const i=t.getMatrix();if(null===i)throw new Z;const s=i.getWidth(),o=i.getHeight(),a=s+2*n,h=o+2*n,l=Math.max(e,a),c=Math.max(r,h),d=Math.min(Math.floor(l/a),Math.floor(c/h)),u=Math.floor((l-s*d)/2),g=Math.floor((c-o*d)/2),f=this.createSVGElement(l,c);for(let t=0,e=g;te||i+o>r)throw new a("Crop rectangle does not fit within image data.");h&&this.reverseHorizontal(s,o)}getRow(t,e){if(t<0||t>=this.getHeight())throw new a("Requested row is outside the image: "+t);const r=this.getWidth();(null==e||e.length>16&255,s=r>>7&510,o=255&r;i[e]=(n+s+o)/4&255}this.luminances=i}else this.luminances=t;if(void 0===n&&(this.dataWidth=e),void 0===i&&(this.dataHeight=r),void 0===s&&(this.left=0),void 0===o&&(this.top=0),this.left+e>this.dataWidth||this.top+r>this.dataHeight)throw new a("Crop rectangle does not fit within image data.")}getRow(t,e){if(t<0||t>=this.getHeight())throw new a("Requested row is outside the image: "+t);const r=this.getWidth();(null==e||e.length=0&&this.noBit(r,e)&&this.utah(e,r,t++),e-=2,r+=2}while(e>=0&&r=0&&r=0);e+=3,r++}while(e{let r=1;for(let n=0;n<255;n++)e[n]=r,t[r]=n,r*=2,r>=256&&(r^=301);return{LOG:t,ALOG:e}})([],[]);var Zr;t.DataMatrixSymbolShapeHint=void 0,(Zr=t.DataMatrixSymbolShapeHint||(t.DataMatrixSymbolShapeHint={}))[Zr.FORCE_NONE=0]="FORCE_NONE",Zr[Zr.FORCE_SQUARE=1]="FORCE_SQUARE",Zr[Zr.FORCE_RECTANGLE=2]="FORCE_RECTANGLE";const Kr="[)>05",Qr="[)>06",qr="";class jr{static encodeECC200(t,e){if(t.length!==e.getDataCapacity())throw new Error("The number of codewords does not match the selected symbol");const r=new T;r.append(t);const n=e.getInterleavedBlockCount();if(1===n){const n=this.createECCBlock(t,e.getErrorCodewords());r.append(n)}else{const i=[];for(let t=0;t0;t--)0!==s&&0!==n[t]?i[t]=i[t-1]^Yr[(zr[s]+zr[n[t]])%255]:i[t]=i[t-1];0!==s&&0!==n[0]?i[0]=Yr[(zr[s]+zr[n[0]])%255]:i[0]=0}const s=[];for(let t=0;tString.fromCharCode(t)).join("")}}class Jr{getEncodingMode(){return 0}encode(t){if(hn.determineConsecutiveDigitCount(t.getMessage(),t.pos)>=2)t.writeCodeword(this.encodeASCIIDigits(t.getMessage().charCodeAt(t.pos),t.getMessage().charCodeAt(t.pos+1))),t.pos+=2;else{const e=t.getCurrentChar(),r=hn.lookAheadTest(t.getMessage(),t.pos,this.getEncodingMode());if(r!==this.getEncodingMode())switch(r){case 5:return t.writeCodeword(231),void t.signalEncoderChange(5);case 1:return t.writeCodeword(230),void t.signalEncoderChange(1);case 3:t.writeCodeword(238),t.signalEncoderChange(3);break;case 2:t.writeCodeword(239),t.signalEncoderChange(2);break;case 4:t.writeCodeword(240),t.signalEncoderChange(4);break;default:throw new Error("Illegal mode: "+r)}else hn.isExtendedASCII(e)?(t.writeCodeword(235),t.writeCodeword(e-128+1),t.pos++):(t.writeCodeword(e+1),t.pos++)}}encodeASCIIDigits(t,e){if(hn.isDigit(t)&&hn.isDigit(e)){return 10*(t-48)+(e-48)+130}throw new Error("not digits: "+t+e)}}class $r{getEncodingMode(){return 5}encode(t){const e=new T;for(e.append(0);t.hasMoreCharacters();){const r=t.getCurrentChar();e.append(r),t.pos++;if(hn.lookAheadTest(t.getMessage(),t.pos,this.getEncodingMode())!==this.getEncodingMode()){t.signalEncoderChange(0);break}}const r=e.length()-1,n=t.getCodewordCount()+r+1;t.updateSymbolInfo(n);const i=t.getSymbolInfo().getDataCapacity()-n>0;if(t.hasMoreCharacters()||i)if(r<=249)e.setCharAt(0,p.getCharAt(r));else{if(!(r<=1555))throw new Error("Message length not in valid ranges: "+r);e.setCharAt(0,p.getCharAt(Math.floor(r/250)+249)),e.insert(1,p.getCharAt(r%250))}for(let r=0,n=e.length();r3||1!==o))&&(t.pos=n)}e.length()>0&&t.writeCodeword(230),this.handleEOD(t,e)}encode(t){const e=new T;for(;t.hasMoreCharacters();){const r=t.getCurrentChar();t.pos++;let n=this.encodeChar(r,e);const i=2*Math.floor(e.length()/3),s=t.getCodewordCount()+i;t.updateSymbolInfo(s);const o=t.getSymbolInfo().getDataCapacity()-s;if(!t.hasMoreCharacters()){const r=new T;for(e.length()%3==2&&2!==o&&(n=this.backtrackOneCharacter(t,e,r,n));e.length()%3==1&&(n>3||1!==o);)n=this.backtrackOneCharacter(t,e,r,n);break}if(e.length()%3==0){if(hn.lookAheadTest(t.getMessage(),t.pos,this.getEncodingMode())!==this.getEncodingMode()){t.signalEncoderChange(0);break}}}this.handleEOD(t,e)}backtrackOneCharacter(t,e,r,n){const i=e.length(),s=e.toString().substring(0,i-n);e.setLengthToZero(),e.append(s),t.pos--;const o=t.getCurrentChar();return n=this.encodeChar(o,r),t.resetSymbolInfo(),n}writeNextTriplet(t,e){t.writeCodewords(this.encodeToCodewords(e.toString()));const r=e.toString().substring(3);e.setLengthToZero(),e.append(r)}handleEOD(t,e){const r=Math.floor(e.length()/3*2),n=e.length()%3,i=t.getCodewordCount()+r;t.updateSymbolInfo(i);const s=t.getSymbolInfo().getDataCapacity()-i;if(2===n){for(e.append("\0");e.length()>=3;)this.writeNextTriplet(t,e);t.hasMoreCharacters()&&t.writeCodeword(254)}else if(1===s&&1===n){for(;e.length()>=3;)this.writeNextTriplet(t,e);t.hasMoreCharacters()&&t.writeCodeword(254),t.pos--}else{if(0!==n)throw new Error("Unexpected case. Please report!");for(;e.length()>=3;)this.writeNextTriplet(t,e);(s>0||t.hasMoreCharacters())&&t.writeCodeword(254)}t.signalEncoderChange(0)}encodeChar(t,e){if(t===" ".charCodeAt(0))return e.append(3),1;if(t>="0".charCodeAt(0)&&t<="9".charCodeAt(0))return e.append(t-48+4),1;if(t>="A".charCodeAt(0)&&t<="Z".charCodeAt(0))return e.append(t-65+14),1;if(t<" ".charCodeAt(0))return e.append(0),e.append(t),2;if(t<="/".charCodeAt(0))return e.append(1),e.append(t-33),2;if(t<="@".charCodeAt(0))return e.append(1),e.append(t-58+15),2;if(t<="_".charCodeAt(0))return e.append(1),e.append(t-91+22),2;if(t<=127)return e.append(2),e.append(t-96),2;e.append("1");let r=2;return r+=this.encodeChar(t-128,e),r}encodeToCodewords(t){const e=1600*t.charCodeAt(0)+40*t.charCodeAt(1)+t.charCodeAt(2)+1,r=e/256,n=e%256,i=new T;return i.append(r),i.append(n),i.toString()}}class en{getEncodingMode(){return 4}encode(t){const e=new T;for(;t.hasMoreCharacters();){const r=t.getCurrentChar();this.encodeChar(r,e),t.pos++;if(e.length()>=4){t.writeCodewords(this.encodeToCodewords(e.toString()));const r=e.toString().substring(4);e.setLengthToZero(),e.append(r);if(hn.lookAheadTest(t.getMessage(),t.pos,this.getEncodingMode())!==this.getEncodingMode()){t.signalEncoderChange(0);break}}}e.append(p.getCharAt(31)),this.handleEOD(t,e)}handleEOD(t,e){try{const r=e.length();if(0===r)return;if(1===r){t.updateSymbolInfo();let e=t.getSymbolInfo().getDataCapacity()-t.getCodewordCount();const r=t.getRemainingCharacters();if(r>e&&(t.updateSymbolInfo(t.getCodewordCount()+1),e=t.getSymbolInfo().getDataCapacity()-t.getCodewordCount()),r<=e&&e<=2)return}if(r>4)throw new Error("Count must not exceed 4");const n=r-1,i=this.encodeToCodewords(e.toString());let s=!t.hasMoreCharacters()&&n<=2;if(n<=2){t.updateSymbolInfo(t.getCodewordCount()+n);t.getSymbolInfo().getDataCapacity()-t.getCodewordCount()>=3&&(s=!1,t.updateSymbolInfo(t.getCodewordCount()+i.length))}s?(t.resetSymbolInfo(),t.pos-=n):t.writeCodewords(i)}finally{t.signalEncoderChange(0)}}encodeChar(t,e){t>=" ".charCodeAt(0)&&t<="?".charCodeAt(0)?e.append(t):t>="@".charCodeAt(0)&&t<="^".charCodeAt(0)?e.append(p.getCharAt(t-64)):hn.illegalCharacter(p.getCharAt(t))}encodeToCodewords(t){const e=t.length;if(0===e)throw new Error("StringBuilder must not be empty");const r=(t.charAt(0).charCodeAt(0)<<18)+((e>=2?t.charAt(1).charCodeAt(0):0)<<12)+((e>=3?t.charAt(2).charCodeAt(0):0)<<6)+(e>=4?t.charAt(3).charCodeAt(0):0),n=r>>16&255,i=r>>8&255,s=255&r,o=new T;return o.append(n),e>=2&&o.append(i),e>=3&&o.append(s),o.toString()}}class rn{constructor(t,e,r,n,i,s,o=0,a=0){this.rectangular=t,this.dataCapacity=e,this.errorCodewords=r,this.matrixWidth=n,this.matrixHeight=i,this.dataRegions=s,this.rsBlockData=o,this.rsBlockError=a}static lookup(t,e=0,r=null,n=null,i=!0){for(const i of nn)if((1!==e||!i.rectangular)&&(2!==e||i.rectangular)&&(null==r||!(i.getSymbolWidth()n.getWidth()||i.getSymbolHeight()>n.getHeight()))&&t<=i.dataCapacity)return i;if(i)throw new Error("Can't find a symbol arrangement that matches the message. Data codewords: "+t);return null}getHorizontalDataRegions(){switch(this.dataRegions){case 1:return 1;case 2:case 4:return 2;case 16:return 4;case 36:return 6;default:throw new Error("Cannot handle this number of data regions")}}getVerticalDataRegions(){switch(this.dataRegions){case 1:case 2:return 1;case 4:return 2;case 16:return 4;case 36:return 6;default:throw new Error("Cannot handle this number of data regions")}}getSymbolDataWidth(){return this.getHorizontalDataRegions()*this.matrixWidth}getSymbolDataHeight(){return this.getVerticalDataRegions()*this.matrixHeight}getSymbolWidth(){return this.getSymbolDataWidth()+2*this.getHorizontalDataRegions()}getSymbolHeight(){return this.getSymbolDataHeight()+2*this.getVerticalDataRegions()}getCodewordCount(){return this.dataCapacity+this.errorCodewords}getInterleavedBlockCount(){return this.rsBlockData?this.dataCapacity/this.rsBlockData:1}getDataCapacity(){return this.dataCapacity}getErrorCodewords(){return this.errorCodewords}getDataLengthForInterleavedBlock(t){return this.rsBlockData}getErrorLengthForInterleavedBlock(t){return this.rsBlockError}}const nn=[new rn(!1,3,5,8,8,1),new rn(!1,5,7,10,10,1),new rn(!0,5,7,16,6,1),new rn(!1,8,10,12,12,1),new rn(!0,10,11,14,6,2),new rn(!1,12,12,14,14,1),new rn(!0,16,14,24,10,1),new rn(!1,18,14,16,16,1),new rn(!1,22,18,18,18,1),new rn(!0,22,18,16,10,2),new rn(!1,30,20,20,20,1),new rn(!0,32,24,16,14,2),new rn(!1,36,24,22,22,1),new rn(!1,44,28,24,24,1),new rn(!0,49,28,22,14,2),new rn(!1,62,36,14,14,4),new rn(!1,86,42,16,16,4),new rn(!1,114,48,18,18,4),new rn(!1,144,56,20,20,4),new rn(!1,174,68,22,22,4),new rn(!1,204,84,24,24,4,102,42),new rn(!1,280,112,14,14,16,140,56),new rn(!1,368,144,16,16,16,92,36),new rn(!1,456,192,18,18,16,114,48),new rn(!1,576,224,20,20,16,144,56),new rn(!1,696,272,22,22,16,174,68),new rn(!1,816,336,24,24,16,136,56),new rn(!1,1050,408,18,18,36,175,68),new rn(!1,1304,496,20,20,36,163,62),new class extends rn{constructor(){super(!1,1558,620,22,22,36,-1,62)}getInterleavedBlockCount(){return 10}getDataLengthForInterleavedBlock(t){return t<=8?156:155}}];class sn{constructor(t){this.msg=t,this.pos=0,this.skipAtEnd=0;const e=t.split("").map(t=>t.charCodeAt(0)),r=new T;for(let n=0,i=e.length;nthis.symbolInfo.getDataCapacity())&&(this.symbolInfo=rn.lookup(t,this.shape,this.minSize,this.maxSize,!0))}resetSymbolInfo(){this.symbolInfo=null}}class on extends tn{getEncodingMode(){return 3}encode(t){const e=new T;for(;t.hasMoreCharacters();){const r=t.getCurrentChar();t.pos++,this.encodeChar(r,e);if(e.length()%3==0){this.writeNextTriplet(t,e);if(hn.lookAheadTest(t.getMessage(),t.pos,this.getEncodingMode())!==this.getEncodingMode()){t.signalEncoderChange(0);break}}}this.handleEOD(t,e)}encodeChar(t,e){switch(t){case 13:e.append(0);break;case"*".charCodeAt(0):e.append(1);break;case">".charCodeAt(0):e.append(2);break;case" ".charCodeAt(0):e.append(3);break;default:t>="0".charCodeAt(0)&&t<="9".charCodeAt(0)?e.append(t-48+4):t>="A".charCodeAt(0)&&t<="Z".charCodeAt(0)?e.append(t-65+14):hn.illegalCharacter(p.getCharAt(t))}return 1}handleEOD(t,e){t.updateSymbolInfo();const r=t.getSymbolInfo().getDataCapacity()-t.getCodewordCount(),n=e.length();t.pos-=n,(t.getRemainingCharacters()>1||r>1||t.getRemainingCharacters()!==r)&&t.writeCodeword(254),t.getNewEncoding()<0&&t.signalEncoderChange(0)}}let an=class extends tn{getEncodingMode(){return 2}encodeChar(t,e){if(t===" ".charCodeAt(0))return e.append(3),1;if(t>="0".charCodeAt(0)&&t<="9".charCodeAt(0))return e.append(t-48+4),1;if(t>="a".charCodeAt(0)&&t<="z".charCodeAt(0))return e.append(t-97+14),1;if(t<" ".charCodeAt(0))return e.append(0),e.append(t),2;if(t<="/".charCodeAt(0))return e.append(1),e.append(t-33),2;if(t<="@".charCodeAt(0))return e.append(1),e.append(t-58+15),2;if(t>="[".charCodeAt(0)&&t<="_".charCodeAt(0))return e.append(1),e.append(t-91+22),2;if(t==="`".charCodeAt(0))return e.append(2),e.append(0),2;if(t<="Z".charCodeAt(0))return e.append(2),e.append(t-65+1),2;if(t<=127)return e.append(2),e.append(t-123+27),2;e.append("1");let r=2;return r+=this.encodeChar(t-128,e),r}},hn=class{static randomize253State(t){const e=129+(149*t%253+1);return e<=254?e:e-254}static encodeHighLevel(t,e=0,r=null,n=null,i=!1){const s=new tn,o=[new Jr,s,new an,new on,new en,new $r],a=new sn(t);a.setSymbolShape(e),a.setSizeConstraints(r,n),t.startsWith(Kr)&&t.endsWith(qr)?(a.writeCodeword(236),a.setSkipAtEnd(2),a.pos+=7):t.startsWith(Qr)&&t.endsWith(qr)&&(a.writeCodeword(237),a.setSkipAtEnd(2),a.pos+=7);let h=0;for(i&&(s.encodeMaximal(a),h=a.getNewEncoding(),a.resetEncoderSignal());a.hasMoreCharacters();)o[h].encode(a),a.getNewEncoding()>=0&&(h=a.getNewEncoding(),a.resetEncoderSignal());const l=a.getCodewordCount();a.updateSymbolInfo();const c=a.getSymbolInfo().getDataCapacity();l=t.length)return r;let n;0===r?n=[0,1,1,1,1,1.25]:(n=[1,2,2,2,2,2.25],n[r]=0);let i=0;const s=new Uint8Array(6),o=[];for(;;){if(e+i===t.length){f.fill(s,0),f.fill(o,0);const t=this.findMinimums(n,o,w.MAX_VALUE,s),e=this.getMinimumCount(s);if(o[0]===t)return 0;if(1===e){if(s[5]>0)return 5;if(s[4]>0)return 4;if(s[2]>0)return 2;if(s[3]>0)return 3}return 1}const r=t.charCodeAt(e+i);if(i++,this.isDigit(r)?n[0]+=.5:this.isExtendedASCII(r)?(n[0]=Math.ceil(n[0]),n[0]+=2):(n[0]=Math.ceil(n[0]),n[0]++),this.isNativeC40(r)?n[1]+=2/3:this.isExtendedASCII(r)?n[1]+=8/3:n[1]+=4/3,this.isNativeText(r)?n[2]+=2/3:this.isExtendedASCII(r)?n[2]+=8/3:n[2]+=4/3,this.isNativeX12(r)?n[3]+=2/3:this.isExtendedASCII(r)?n[3]+=13/3:n[3]+=10/3,this.isNativeEDIFACT(r)?n[4]+=3/4:this.isExtendedASCII(r)?n[4]+=4.25:n[4]+=3.25,this.isSpecialB256(r)?n[5]+=4:n[5]++,i>=4){if(f.fill(s,0),f.fill(o,0),this.findMinimums(n,o,w.MAX_VALUE,s),o[0]s&&(r=s,f.fill(n,0)),r===s&&(n[i]=n[i]+1)}return r}static getMinimumCount(t){let e=0;for(let r=0;r<6;r++)e+=t[r];return e||0}static isDigit(t){return t>="0".charCodeAt(0)&&t<="9".charCodeAt(0)}static isExtendedASCII(t){return t>=128&&t<=255}static isNativeC40(t){return t===" ".charCodeAt(0)||t>="0".charCodeAt(0)&&t<="9".charCodeAt(0)||t>="A".charCodeAt(0)&&t<="Z".charCodeAt(0)}static isNativeText(t){return t===" ".charCodeAt(0)||t>="0".charCodeAt(0)&&t<="9".charCodeAt(0)||t>="a".charCodeAt(0)&&t<="z".charCodeAt(0)}static isNativeX12(t){return this.isX12TermSep(t)||t===" ".charCodeAt(0)||t>="0".charCodeAt(0)&&t<="9".charCodeAt(0)||t>="A".charCodeAt(0)&&t<="Z".charCodeAt(0)}static isX12TermSep(t){return 13===t||t==="*".charCodeAt(0)||t===">".charCodeAt(0)}static isNativeEDIFACT(t){return t>=" ".charCodeAt(0)&&t<="^".charCodeAt(0)}static isSpecialB256(t){return!1}static determineConsecutiveDigitCount(t,e=0){const r=t.length;let n=e;for(;nnew ln(Ur.forName(t))),this.encoders=[];const n=[];n.push(new ln(Vr.ISO_8859_1));let i=null!=e&&e.name.startsWith("UTF");for(let e=0;e=this.bytes.length)return!1;for(let r=0;r=this.length())throw new Error(""+t);if(this.isECI(t))throw new Error("value at "+t+" is not a character but an ECI");return this.isFNC1(t)?this.fnc1:this.bytes[t]}subSequence(t,e){if(t<0||t>e||e>this.length())throw new Error(""+t);const r=new T;for(let n=t;n=this.length())throw new Error(""+t);return this.bytes[t]>255&&this.bytes[t]<=999}isFNC1(t){if(t<0||t>=this.length())throw new Error(""+t);return 1e3===this.bytes[t]}getECIValue(t){if(t<0||t>=this.length())throw new Error(""+t);if(!this.isECI(t))throw new Error("value at "+t+" is not an ECI but a character");return this.bytes[t]-256}addEdge(t,e,r){(null==t[e][r.encoderIndex]||t[e][r.encoderIndex].cachedTotalSize>r.cachedTotalSize)&&(t[e][r.encoderIndex]=r)}addEdges(t,e,r,n,i,s){const o=t.charAt(n).charCodeAt(0);let a=0,h=e.length();e.getPriorityEncoderIndex()>=0&&(o===s||e.canEncode(o,e.getPriorityEncoderIndex()))&&(a=e.getPriorityEncoderIndex(),h=a+1);for(let t=a;t=0;e--)a.unshift(255&t[e])}(null===h.previous?0:h.previous.encoderIndex)!==h.encoderIndex&&a.unshift(256+e.getECIValue(h.encoderIndex)),h=h.previous}const l=[];for(let t=0;t","?","@","[","\\","]","^","_"];class wn{static isExtendedASCII(t,e){return t!==e&&t>=128&&t<=255}static isInC40Shift1Set(t){return t<=31}static isInC40Shift2Set(t,e){for(const e of fn)if(e.charCodeAt(0)===t)return!0;return t===e}static isInTextShift1Set(t){return this.isInC40Shift1Set(t)}static isInTextShift2Set(t,e){return this.isInC40Shift2Set(t,e)}static encodeHighLevel(t,e=null,r=-1,n=0){let i=0;return t.startsWith(Kr)&&t.endsWith(qr)?(i=5,t=t.substring(7,t.length-2)):t.startsWith(Qr)&&t.endsWith(qr)&&(i=6,t=t.substring(7,t.length-2)),decodeURIComponent(escape(String.fromCharCode(...this.encode(t,e,r,n,i))))}static encode(t,e,r,n,i){return this.encodeMinimally(new En(t,e,r,n,i)).getBytes()}static addEdge(t,e){const r=e.fromPosition+e.characterLength;(null===t[r][e.getEndMode()]||t[r][e.getEndMode()].cachedTotalSize>e.cachedTotalSize)&&(t[r][e.getEndMode()]=e)}static getNumberOfC40Words(t,e,r,n){let i=0;for(let s=e;s=128&&(r&&hn.isNativeC40(t-128)||!r&&hn.isNativeText(t-128))?i+=3:i+=4}else i+=2;if(i%3==0||(i-2)%3==0&&s+1===t.length())return n[0]=s-e+1,Math.ceil(i/3)}return n[0]=0,0}static addEdges(t,e,r,n){if(t.isECI(r))return void this.addEdge(e,new An(t,gn.ASCII,r,1,n));const i=t.charAt(r);if(null===n||n.getEndMode()!==gn.EDF){hn.isDigit(i)&&t.haveNCharacters(r,2)&&hn.isDigit(t.charAt(r+1))?this.addEdge(e,new An(t,gn.ASCII,r,2,n)):this.addEdge(e,new An(t,gn.ASCII,r,1,n));const s=[gn.C40,gn.TEXT];for(const i of s){const s=[];wn.getNumberOfC40Words(t,r,i===gn.C40,s)>0&&this.addEdge(e,new An(t,i,r,s[0],n))}t.haveNCharacters(r,3)&&hn.isNativeX12(t.charAt(r))&&hn.isNativeX12(t.charAt(r+1))&&hn.isNativeX12(t.charAt(r+2))&&this.addEdge(e,new An(t,gn.X12,r,3,n)),this.addEdge(e,new An(t,gn.B256,r,1,n))}let s;for(s=0;s<3;s++){const i=r+s;if(!t.haveNCharacters(i,1)||!hn.isNativeEDIFACT(t.charAt(i)))break;this.addEdge(e,new An(t,gn.EDF,r,s+1,n))}3===s&&t.haveNCharacters(r,4)&&hn.isNativeEDIFACT(t.charAt(r+3))&&this.addEdge(e,new An(t,gn.EDF,r,4,n))}static encodeMinimally(t){const e=t.length(),r=Array(e+1).fill(null).map(()=>Array(6).fill(0));this.addEdges(t,r,0,null);for(let n=1;n<=e;n++){for(let i=0;i<6;i++)null!==r[n][i]&&n=1&&t<=3?s.cachedTotalSize+1:s.cachedTotalSize;o0&&(r+=this.prepend(An.getBytes(232),n));for(let t=0;t=0;r--)e.unshift(t[r]);return t.length}randomize253State(t){const e=129+(149*t%253+1);return e<=254?e:e-254}applyRandomPattern(t,e,r){for(let n=0;n0&&this.getCodewordsRemaining(this.cachedTotalSize+t)<=2-t)return gn.ASCII}if(this.mode===gn.C40||this.mode===gn.TEXT||this.mode===gn.X12){if(this.fromPosition+this.characterLength>=this.input.length()&&0===this.getCodewordsRemaining(this.cachedTotalSize))return gn.ASCII;if(1===this.getLastASCII()&&0===this.getCodewordsRemaining(this.cachedTotalSize+1))return gn.ASCII}return this.mode}getMode(){return this.mode}getLastASCII(){const t=this.input.length(),e=this.fromPosition+this.characterLength;return t-e>4||e>=t?0:t-e===1?wn.isExtendedASCII(this.input.charAt(e),this.input.getFNC1Character())?0:1:t-e===2?wn.isExtendedASCII(this.input.charAt(e),this.input.getFNC1Character())||wn.isExtendedASCII(this.input.charAt(e+1),this.input.getFNC1Character())?0:hn.isDigit(this.input.charAt(e))&&hn.isDigit(this.input.charAt(e+1))?1:2:t-e===3?hn.isDigit(this.input.charAt(e))&&hn.isDigit(this.input.charAt(e+1))&&!wn.isExtendedASCII(this.input.charAt(e+2),this.input.getFNC1Character())||hn.isDigit(this.input.charAt(e+1))&&hn.isDigit(this.input.charAt(e+2))&&!wn.isExtendedASCII(this.input.charAt(e),this.input.getFNC1Character())?2:0:hn.isDigit(this.input.charAt(e))&&hn.isDigit(this.input.charAt(e+1))&&hn.isDigit(this.input.charAt(e+2))&&hn.isDigit(this.input.charAt(e+3))?2:0}getMinSymbolSize(t){switch(this.input.getShapeHint()){case 1:for(const e of this.squareCodewordCapacities)if(e>=t)return e;break;case 2:for(const e of this.rectangularCodewordCapacities)if(e>=t)return e}for(const e of this.allCodewordCapacities)if(e>=t)return e;return this.allCodewordCapacities[this.allCodewordCapacities.length-1]}getCodewordsRemaining(t){return this.getMinSymbolSize(t)-t}static getBytes(t,e){const r=new Uint8Array(e?2:1);return r[0]=t,e&&(r[1]=e),r}setC40Word(t,e,r,n,i){const s=1600*(255&r)+40*(255&n)+(255&i)+1;t[e]=s/256,t[e+1]=s%256}getX12Value(t){return 13===t?0:42===t?1:62===t?2:32===t?3:t>=48&&t<=57?t-44:t>=65&&t<=90?t-51:t}getX12Words(){if(this.characterLength%3!=0)throw new Error("X12 words must be a multiple of 3");const t=new Uint8Array(this.characterLength/3*2);for(let e=0;e=33&&r<=47?r-33:r>=48&&r<=57?r-44:r>=58&&r<=64?r-43:r>=65&&r<=90?r-64:r>=91&&r<=95?r-69:96===r?0:r>=97&&r<=122?r-83:r>=123&&r<=127?r-96:r}getC40Words(t,e){const r=[];for(let n=0;n>16&255,e[i+1]=s>>8&255,e[i+2]=255&s}return e}getLatchBytes(){switch(this.getPreviousMode()){case gn.ASCII:case gn.B256:switch(this.mode){case gn.B256:return An.getBytes(231);case gn.C40:return An.getBytes(230);case gn.TEXT:return An.getBytes(239);case gn.X12:return An.getBytes(238);case gn.EDF:return An.getBytes(240)}break;case gn.C40:case gn.TEXT:case gn.X12:if(this.mode!==this.getPreviousMode())switch(this.mode){case gn.ASCII:return An.getBytes(254);case gn.B256:return An.getBytes(254,231);case gn.C40:return An.getBytes(254,230);case gn.TEXT:return An.getBytes(254,239);case gn.X12:return An.getBytes(254,238);case gn.EDF:return An.getBytes(254,240)}break;case gn.EDF:if(this.mode!==gn.EDF)throw new Error("Cannot switch from EDF to "+this.mode)}return new Uint8Array(0)}getDataBytes(){switch(this.mode){case gn.ASCII:return this.input.isECI(this.fromPosition)?An.getBytes(241,this.input.getECIValue(this.fromPosition)+1):wn.isExtendedASCII(this.input.charAt(this.fromPosition),this.input.getFNC1Character())?An.getBytes(235,this.input.charAt(this.fromPosition)-127):2===this.characterLength?An.getBytes(10*this.input.charAt(this.fromPosition)+this.input.charAt(this.fromPosition+1)+130):this.input.isFNC1(this.fromPosition)?An.getBytes(232):An.getBytes(this.input.charAt(this.fromPosition)+1);case gn.B256:return An.getBytes(this.input.charAt(this.fromPosition));case gn.C40:return this.getC40Words(!0,this.input.getFNC1Character());case gn.TEXT:return this.getC40Words(!1,this.input.getFNC1Character());case gn.X12:return this.getX12Words();case gn.EDF:return this.getEDFBytes()}}}class En extends dn{constructor(t,e,r,n,i){super(t,e,r),this.shape=n,this.macroId=i}getMacroId(){return this.macroId}getShapeHint(){return this.shape}}class mn{isCompact(){return this.compact}setCompact(t){this.compact=t}getSize(){return this.size}setSize(t){this.size=t}getLayers(){return this.layers}setLayers(t){this.layers=t}getCodeWords(){return this.codeWords}setCodeWords(t){this.codeWords=t}getMatrix(){return this.matrix}setMatrix(t){this.matrix=t}}class In{static singletonList(t){return[t]}static min(t,e){return t.sort(e)[0]}}class _n{constructor(t){this.previous=t}getPrevious(){return this.previous}}class Sn extends _n{constructor(t,e,r){super(t),this.value=e,this.bitCount=r}appendTo(t,e){t.appendBits(this.value,this.bitCount)}add(t,e){return new Sn(this,t,e)}addBinaryShift(t,e){return console.warn("addBinaryShift on SimpleToken, this simply returns a copy of this token"),new Sn(this,t,e)}toString(){let t=this.value&(1<"}}class pn extends Sn{constructor(t,e,r){super(t,0,0),this.binaryShiftStart=e,this.binaryShiftByteCount=r}appendTo(t,e){for(let r=0;r62?t.appendBits(this.binaryShiftByteCount-31,16):0===r?t.appendBits(Math.min(this.binaryShiftByteCount,31),5):t.appendBits(this.binaryShiftByteCount-31,5)),t.appendBits(e[this.binaryShiftStart+r],8)}addBinaryShift(t,e){return new pn(this,t,e)}toString(){return"<"+this.binaryShiftStart+"::"+(this.binaryShiftStart+this.binaryShiftByteCount-1)+">"}}function Tn(t,e,r){return new Sn(t,e,r)}const Rn=["UPPER","LOWER","DIGIT","MIXED","PUNCT"],Nn=new Sn(null,0,0),Dn=[Int32Array.from([0,327708,327710,327709,656318]),Int32Array.from([590318,0,327710,327709,656318]),Int32Array.from([262158,590300,0,590301,932798]),Int32Array.from([327709,327708,656318,0,327710]),Int32Array.from([327711,656380,656382,656381,0])];const Mn=function(t){for(let e of t)f.fill(e,-1);return t[0][4]=0,t[1][4]=0,t[1][0]=28,t[3][4]=0,t[2][4]=0,t[2][0]=15,t}(f.createInt32Array(6,6));class yn{constructor(t,e,r,n){this.token=t,this.mode=e,this.binaryShiftByteCount=r,this.bitCount=n}getMode(){return this.mode}getToken(){return this.token}getBinaryShiftByteCount(){return this.binaryShiftByteCount}getBitCount(){return this.bitCount}latchAndAppend(t,e){let r=this.bitCount,n=this.token;if(t!==this.mode){let e=Dn[this.mode][t];n=Tn(n,65535&e,e>>16),r+=e>>16}let i=2===t?4:5;return n=Tn(n,e,i),new yn(n,t,0,r+i)}shiftAndAppend(t,e){let r=this.token,n=2===this.mode?4:5;return r=Tn(r,Mn[this.mode][t],n),r=Tn(r,e,5),new yn(r,this.mode,0,this.bitCount+n+5)}addBinaryShiftChar(t){let e=this.token,r=this.mode,n=this.bitCount;if(4===this.mode||2===this.mode){let t=Dn[r][0];e=Tn(e,65535&t,t>>16),n+=t>>16,r=0}let i=0===this.binaryShiftByteCount||31===this.binaryShiftByteCount?18:62===this.binaryShiftByteCount?9:8,s=new yn(e,r,this.binaryShiftByteCount+1,n+i);return 2078===s.binaryShiftByteCount&&(s=s.endBinaryShift(t+1)),s}endBinaryShift(t){if(0===this.binaryShiftByteCount)return this;let e=this.token;return e=function(t,e,r){return new pn(t,e,r)}(e,t-this.binaryShiftByteCount,this.binaryShiftByteCount),new yn(e,this.mode,0,this.bitCount)}isBetterThanOrEqualTo(t){let e=this.bitCount+(Dn[this.mode][t.mode]>>16);return this.binaryShiftByteCountt.binaryShiftByteCount&&t.binaryShiftByteCount>0&&(e+=10),e<=t.bitCount}toBitArray(t){let e=[];for(let r=this.endBinaryShift(t.length).token;null!==r;r=r.getPrevious())e.unshift(r);let r=new C;for(const n of e)n.appendTo(r,t);return r}toString(){return p.format("%s bits=%d bytes=%d",Rn[this.mode],this.bitCount,this.binaryShiftByteCount)}static calculateBinaryShiftCost(t){return t.binaryShiftByteCount>62?21:t.binaryShiftByteCount>31?20:t.binaryShiftByteCount>0?10:0}}yn.INITIAL_STATE=new yn(Nn,0,0,0);const On=function(t){const e=p.getCharCode(" "),r=p.getCharCode("."),n=p.getCharCode(",");t[0][e]=1;const i=p.getCharCode("Z"),s=p.getCharCode("A");for(let e=s;e<=i;e++)t[0][e]=e-s+2;t[1][e]=1;const o=p.getCharCode("z"),a=p.getCharCode("a");for(let e=a;e<=o;e++)t[1][e]=e-a+2;t[2][e]=1;const h=p.getCharCode("9"),l=p.getCharCode("0");for(let e=l;e<=h;e++)t[2][e]=e-l+2;t[2][n]=12,t[2][r]=13;const c=["\0"," ","","","","","","","","\b","\t","\n","\v","\f","\r","","","","","","@","\\","^","_","`","|","~",""];for(let e=0;e","?","[","]","{","}"];for(let e=0;e0&&(t[4][p.getCharCode(d[e])]=e);return t}(f.createInt32Array(5,256));class bn{constructor(t){this.text=t}encode(){const t=p.getCharCode(" "),e=p.getCharCode("\n");let r=In.singletonList(yn.INITIAL_STATE);for(let n=0;n0?(r=bn.updateStateListForPair(r,n,i),n++):r=this.updateStateListForChar(r,n)}return In.min(r,(t,e)=>t.getBitCount()-e.getBitCount()).toBitArray(this.text)}updateStateListForChar(t,e){const r=[];for(let n of t)this.updateStateForChar(n,e,r);return bn.simplifyStates(r)}updateStateForChar(t,e,r){let n=255&this.text[e],i=On[t.getMode()][n]>0,s=null;for(let o=0;o<=4;o++){let a=On[o][n];if(a>0){if(null==s&&(s=t.endBinaryShift(e)),!i||o===t.getMode()||2===o){const t=s.latchAndAppend(o,a);r.push(t)}if(!i&&Mn[t.getMode()][o]>=0){const t=s.shiftAndAppend(o,a);r.push(t)}}}if(t.getBinaryShiftByteCount()>0||0===On[t.getMode()][n]){let n=t.addBinaryShiftChar(e);r.push(n)}}static updateStateListForPair(t,e,r){const n=[];for(let i of t)this.updateStateForPair(i,e,r,n);return this.simplifyStates(n)}static updateStateForPair(t,e,r,n){let i=t.endBinaryShift(e);if(n.push(i.latchAndAppend(4,r)),4!==t.getMode()&&n.push(i.shiftAndAppend(4,r)),3===r||4===r){let t=i.latchAndAppend(2,16-r).latchAndAppend(2,1);n.push(t)}if(t.getBinaryShiftByteCount()>0){let r=t.addBinaryShiftChar(e).addBinaryShiftChar(e+1);n.push(r)}}static simplifyStates(t){let e=[];for(const r of t){let t=!0;for(const n of e){if(n.isBetterThanOrEqualTo(r)){t=!1;break}r.isBetterThanOrEqualTo(n)&&(e=e.filter(t=>t!==n))}t&&e.push(r)}return e}}class Bn{constructor(){}static encodeBytes(t){return Bn.encode(t,Bn.DEFAULT_EC_PERCENT,Bn.DEFAULT_AZTEC_LAYERS)}static encode(t,e,r){let n,i,s,o,h,l=new bn(t).encode(),c=w.truncDivision(l.getSize()*e,100)+11,d=l.getSize()+c;if(r!==Bn.DEFAULT_AZTEC_LAYERS){if(n=r<0,i=Math.abs(r),i>(n?Bn.MAX_NB_BITS_COMPACT:Bn.MAX_NB_BITS))throw new a(p.format("Illegal value %s for layers",r));s=Bn.totalBitsInLayer(i,n),o=Bn.WORD_SIZE[i];let t=s-s%o;if(h=Bn.stuffBits(l,o),h.getSize()+c>t)throw new a("Data to large for user specified layer");if(n&&h.getSize()>64*o)throw new a("Data to large for user specified layer")}else{o=0,h=null;for(let t=0;;t++){if(t>Bn.MAX_NB_BITS)throw new a("Data too large for an Aztec code");if(n=t<=3,i=n?t+1:t,s=Bn.totalBitsInLayer(i,n),d>s)continue;null!=h&&o===Bn.WORD_SIZE[i]||(o=Bn.WORD_SIZE[i],h=Bn.stuffBits(l,o));let e=s-s%o;if(!(n&&h.getSize()>64*o)&&h.getSize()+c<=e)break}}let u,g=Bn.generateCheckWords(h,s,o),f=h.getSize()/o,C=Bn.generateModeMessage(n,i,f),A=(n?11:14)+4*i,E=new Int32Array(A);if(n){u=A;for(let t=0;t=n||t.get(s+r))&&(o|=1<=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", + "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", + "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", + "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", + "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", + "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", + "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", + "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", + "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", + "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", + "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", + "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", + "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", + "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", + "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", + "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", + "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", + "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", + "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", + "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", + "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", + "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", + "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", + "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", + "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", + "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@zeit/schemas": { "version": "2.36.0", "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz", @@ -19,6 +465,30 @@ "dev": true, "license": "MIT" }, + "node_modules/@zxing/library": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@zxing/library/-/library-0.23.0.tgz", + "integrity": "sha512-6fkkoFwP8CHxl6ugnPsj74PLJgX2iRv5zczGAyt5OBzQgxFhuhF0NCEc4t4OvSr8xAv2MRLlI0Iu9ZGDZQ2urA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "ts-custom-error": "^3.3.1" + }, + "engines": { + "node": ">= 24.0.0" + }, + "optionalDependencies": { + "@zxing/text-encoding": "~0.9.0" + } + }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "dev": true, + "license": "(Unlicense OR Apache-2.0)", + "optional": true + }, "node_modules/ajv": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", @@ -302,6 +772,94 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -396,6 +954,16 @@ "ms": "2.0.0" } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -406,6 +974,13 @@ "node": ">=4.0.0" } }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "dev": true, + "license": "MIT" + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -420,6 +995,48 @@ "dev": true, "license": "MIT" }, + "node_modules/esbuild": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", + "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.0", + "@esbuild/android-arm": "0.28.0", + "@esbuild/android-arm64": "0.28.0", + "@esbuild/android-x64": "0.28.0", + "@esbuild/darwin-arm64": "0.28.0", + "@esbuild/darwin-x64": "0.28.0", + "@esbuild/freebsd-arm64": "0.28.0", + "@esbuild/freebsd-x64": "0.28.0", + "@esbuild/linux-arm": "0.28.0", + "@esbuild/linux-arm64": "0.28.0", + "@esbuild/linux-ia32": "0.28.0", + "@esbuild/linux-loong64": "0.28.0", + "@esbuild/linux-mips64el": "0.28.0", + "@esbuild/linux-ppc64": "0.28.0", + "@esbuild/linux-riscv64": "0.28.0", + "@esbuild/linux-s390x": "0.28.0", + "@esbuild/linux-x64": "0.28.0", + "@esbuild/netbsd-arm64": "0.28.0", + "@esbuild/netbsd-x64": "0.28.0", + "@esbuild/openbsd-arm64": "0.28.0", + "@esbuild/openbsd-x64": "0.28.0", + "@esbuild/openharmony-arm64": "0.28.0", + "@esbuild/sunos-x64": "0.28.0", + "@esbuild/win32-arm64": "0.28.0", + "@esbuild/win32-ia32": "0.28.0", + "@esbuild/win32-x64": "0.28.0" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -468,6 +1085,30 @@ ], "license": "BSD-3-Clause" }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -580,6 +1221,13 @@ "dev": true, "license": "ISC" }, + "node_modules/jsbarcode": { + "version": "3.12.3", + "resolved": "https://registry.npmjs.org/jsbarcode/-/jsbarcode-3.12.3.tgz", + "integrity": "sha512-CuHU9hC6dPsHF5oVFMo8NW76uQVjH4L22CsP4hW+dNnGywJHC/B0ThA1CTDVLnxKLrrpYdicBLnd2xsgTfRnvg==", + "dev": true, + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -587,6 +1235,19 @@ "dev": true, "license": "MIT" }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -716,6 +1377,55 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", @@ -740,6 +1450,34 @@ "dev": true, "license": "MIT" }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -790,6 +1528,16 @@ "node": ">=0.10.0" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -800,6 +1548,13 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true, + "license": "ISC" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -873,6 +1628,13 @@ "node": ">= 0.8" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -970,6 +1732,16 @@ "node": ">=8" } }, + "node_modules/ts-custom-error": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.3.1.tgz", + "integrity": "sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/type-fest": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", @@ -1020,6 +1792,13 @@ "node": ">= 8" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true, + "license": "ISC" + }, "node_modules/widest-line": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", @@ -1053,6 +1832,105 @@ "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-parser/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } } } } diff --git a/package.json b/package.json index 117727e..15b26aa 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,15 @@ "version": "1.0.0", "description": "Universal Text Encoder/Decoder & Steganography Tool", "scripts": { + "build:codes-vendor": "node build/build-code-vendor.js", "build:copy": "node build/copy-static.js", "build:index": "node build/build-index.js", "build:tools": "node build/inject-tool-scripts.js", "build:templates": "node build/inject-tool-templates.js", "build:emoji": "node build/build-emoji-data.js", - "build:transforms": "node build/build-transforms.js", - "build": "npm run build:tools && npm run build:copy && npm run build:index && npm run build:transforms && npm run build:emoji && npm run build:templates", + "build:alphabets": "node build/build-alphabet-transforms.js", + "build:transforms": "npm run build:alphabets && node build/build-transforms.js", + "build": "npm run build:tools && npm run build:codes-vendor && npm run build:copy && npm run build:index && npm run build:transforms && npm run build:emoji && npm run build:templates", "start": "serve dist -l 8080", "preview": "npm run build && serve dist -l 8080", "test": "node tests/test_universal.js", @@ -33,6 +35,10 @@ "author": "", "license": "MIT", "devDependencies": { + "@zxing/library": "^0.23.0", + "esbuild": "^0.28.0", + "jsbarcode": "^3.12.3", + "qrcode": "^1.5.4", "serve": "^14.2.6" } } diff --git a/src/transformers/README.md b/src/transformers/README.md index 8483883..c5361a5 100644 --- a/src/transformers/README.md +++ b/src/transformers/README.md @@ -4,17 +4,18 @@ Transformers are instantiated using `BaseTransformer` class. Category is automat ## Directory Structure -Categories (auto-assigned from directory name): -- `encoding/` - Base64, Hex, Binary, URL, HTML, etc. -- `cipher/` - ROT13, Caesar, Vigenère, Atbash, etc. -- `unicode/` - Cursive, Medieval, Monospace, Bubble, etc. -- `case/` - Snake case, Kebab case, Title case, etc. -- `technical/` - Morse, Braille, NATO, Brainfuck, etc. -- `fantasy/` - Elder Futhark, Tengwar, Klingon, Aurebesh, etc. -- `ancient/` - Hieroglyphics, Ogham, Roman Numerals, etc. -- `format/` - Leetspeak, Pig Latin, Reverse, etc. -- `visual/` - Emoji speak, Rovarspraket, etc. -- `special/` - Randomizer, etc. +Categories (auto-assigned from directory name by `npm run build:transforms`): +- `case/` — Case and capitalization transforms +- `cipher/` — Classical ciphers, transposition, polyalphabetic, A1Z26, tap code, codons, etc. +- `concealment/` — Steganography and hidden-message schemes (null cipher, acrostic, zero-width, etc.) +- `encoding/` — Byte and data encodings (Base64, hex, binary, line codes, Brainfuck, etc.) +- `format/` — Text cleanup and layout utilities +- `signwriting/` — SignWriting fingerspelling and related notation +- `special/` — Randomizer and other misc tools +- `symbol/` — Substitution alphabets, runes, scripts, pigpen, braille, numeral systems, etc. +- `technical/` — Morse, NATO, phone keypad, spelling alphabets, semaphore, etc. +- `unicode/` — Unicode presentation styles (bold, bubble, zalgo, etc.) +- `visual/` — Spoken-language games and wordplay (Pig Latin, leetspeak, etc.) ## Creating a Transformer @@ -129,12 +130,12 @@ Higher priority = more specific pattern (used for decoder result ordering): ## After Adding -1. Place file in appropriate category directory -2. Run `npm run build:transforms` -3. Test in webapp -4. Add `detector` function if format has distinctive patterns -5. Optionally add test cases to `tests/test_universal.js` -6. Add a one-line description for the transform’s `name` in `DESCRIPTIONS` inside `build/readme-transform-section.js`, then run `node build/readme-transform-section.js` and merge the printed block into the **Text Transformations** section of the root `README.md` (the script exits with an error if a transform is missing from `DESCRIPTIONS`) +1. Place the file in the appropriate category directory (folder name = UI category). +2. Run `npm run build:transforms` (or `npm run build`). +3. Test in the webapp (`npm start` → http://localhost:8080). +4. Add a `detector` function if the format has distinctive patterns (helps the universal decoder). +5. Optionally add known limitations to `limitations` in `tests/test_universal.js`. +6. Update the root **README.md**: add or edit a bullet under **Text Transformations** in the matching category section, using the transform’s `name` and a one-line description. ## Testing diff --git a/src/transformers/format/capitalize-words.js b/src/transformers/case/capitalize-words.js similarity index 100% rename from src/transformers/format/capitalize-words.js rename to src/transformers/case/capitalize-words.js diff --git a/src/transformers/format/lowercase-all.js b/src/transformers/case/lowercase-all.js similarity index 100% rename from src/transformers/format/lowercase-all.js rename to src/transformers/case/lowercase-all.js diff --git a/src/transformers/format/uppercase-all.js b/src/transformers/case/uppercase-all.js similarity index 100% rename from src/transformers/format/uppercase-all.js rename to src/transformers/case/uppercase-all.js diff --git a/src/transformers/format/uppercase-lowercase.js b/src/transformers/case/uppercase-lowercase.js similarity index 100% rename from src/transformers/format/uppercase-lowercase.js rename to src/transformers/case/uppercase-lowercase.js diff --git a/src/transformers/technical/a1z26.js b/src/transformers/cipher/a1z26.js similarity index 100% rename from src/transformers/technical/a1z26.js rename to src/transformers/cipher/a1z26.js diff --git a/src/transformers/cipher/acere-cipher.js b/src/transformers/cipher/acere-cipher.js new file mode 100644 index 0000000..dd8de46 --- /dev/null +++ b/src/transformers/cipher/acere-cipher.js @@ -0,0 +1,208 @@ +// Acéré cipher — French solfège (A = Ré) with optional note-duration variants +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const SOLFEGE = ['Ré', 'Mi', 'Fa', 'Sol', 'La', 'Si', 'Do']; + const SOLFEGE_ASCII = ['re', 'mi', 'fa', 'sol', 'la', 'si', 'do']; + const EIGHTH = '♪'; + const HALF = '●'; + const WHOLE = '𝅝'; + const QUARTER = '♩'; + + /** Eighth then half; whole notes used for digits / extended tiers */ + const BLOCK_DURATIONS = { + 'full-alphabet': [EIGHTH, HALF, WHOLE, QUARTER], + 'eighth-then-half': [EIGHTH, HALF, WHOLE, QUARTER], + 'half-then-eighth': [HALF, EIGHTH, QUARTER, WHOLE], + 'first-half-eighth': null, + 'solfège-only': null, + 'an-septet': null + }; + + function solfegeToPitch(token) { + const key = token.toLowerCase().replace(/é/g, 'e'); + return SOLFEGE_ASCII.indexOf(key); + } + + function durationForLetterIndex(index, durationMode) { + if (durationMode === 'solfège-only') return ''; + if (durationMode === 'first-half-eighth') { + return index < 13 ? EIGHTH : HALF; + } + if (durationMode === 'an-septet') { + return index < 7 ? EIGHTH : HALF; + } + const block = Math.floor(index / 7); + const table = BLOCK_DURATIONS[durationMode] || BLOCK_DURATIONS['full-alphabet']; + return table[block] || QUARTER; + } + + function durationForDigit(digit, durationMode) { + if (durationMode === 'solfège-only') return ''; + return WHOLE; + } + + function encodeLetter(ch, options) { + const upper = ch.toUpperCase(); + if (/[A-Z]/.test(upper)) { + const index = upper.charCodeAt(0) - 65; + const duration = durationForLetterIndex(index, options.durationMode); + return duration + SOLFEGE[index % 7]; + } + if (options.includeDigits && /[0-9]/.test(ch)) { + const digit = parseInt(ch, 10); + return durationForDigit(digit, options.durationMode) + SOLFEGE[digit % 7]; + } + return ch; + } + + function matchingLetterIndices(pitch, duration, durationMode) { + const out = []; + for (let i = 0; i < 26; i++) { + if (i % 7 !== pitch) continue; + if (durationMode === 'solfège-only') { + out.push(i); + continue; + } + const expected = durationForLetterIndex(i, durationMode); + if (!duration || duration === expected) out.push(i); + } + return out; + } + + function parseToken(raw) { + const chars = [...raw.trim()]; + if (!chars.length) return { duration: '', namePart: '' }; + const first = chars[0]; + if (first === EIGHTH || first === HALF || first === WHOLE || first === QUARTER) { + return { duration: first, namePart: chars.slice(1).join('') }; + } + return { duration: '', namePart: raw.trim() }; + } + + function decodeToken(raw, options) { + const t = raw.trim(); + if (!t) return ''; + + const { duration, namePart } = parseToken(t); + + const pitch = solfegeToPitch(namePart); + if (pitch < 0) return t; + + if (duration === WHOLE && options.includeDigits && !/[A-Za-z]/.test(t)) { + for (let d = 0; d <= 9; d++) { + if (d % 7 === pitch) return String(d); + } + } + + const candidates = matchingLetterIndices(pitch, duration, options.durationMode); + if (candidates.length === 0) return t; + return String.fromCharCode(65 + candidates[0]); + } + + function splitTokens(text, separator) { + if (separator === 'none') { + return text.match(/[♪●𝅝♩]?(?:Ré|Re|Mi|Fa|Sol|La|Si|Do)/gi) || []; + } + if (separator === 'comma') { + return text.split(/\s*,\s*/).filter(Boolean); + } + return text.trim().split(/\s+/).filter(Boolean); + } + + return new BaseTransformer({ + name: 'Acéré Cipher', + priority: 88, + category: 'music', + configurableOptions: [ + { + id: 'durationMode', + label: 'Note duration variant', + type: 'select', + default: 'full-alphabet', + options: [ + { + value: 'full-alphabet', + label: '♪ / ● / 𝅝 / ♩ by septet (full A–Z, reversible)' + }, + { + value: 'an-septet', + label: '♪ A–G, ● H–N (A–N only)' + }, + { + value: 'eighth-then-half', + label: '♪ / ● / 𝅝 / ♩ septets (same as full)' + }, + { + value: 'half-then-eighth', + label: 'Inverted septet durations' + }, + { + value: 'first-half-eighth', + label: '♪ A–M, ● N–Z (lossy)' + }, + { + value: 'solfège-only', + label: 'Solfège names only (lossy)' + } + ] + }, + { + id: 'includeDigits', + label: 'Encode digits 0–9 (0 = Ré, 𝅝 whole note)', + type: 'boolean', + default: false + }, + { + id: 'lettersOnly', + label: 'Letters (and digits) only on encode', + type: 'boolean', + default: true + }, + { + id: 'separator', + label: 'Separator between notes', + type: 'select', + default: 'space', + options: [ + { value: 'space', label: 'Space' }, + { value: 'comma', label: 'Comma' }, + { value: 'none', label: 'None' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const durationMode = options.durationMode || 'full-alphabet'; + const opts = { + durationMode, + includeDigits: !!options.includeDigits + }; + const sep = options.separator === 'comma' ? ', ' + : (options.separator === 'none' ? '' : ' '); + const chars = options.lettersOnly !== false + ? [...text].filter(c => /[A-Za-z0-9]/.test(c) && (opts.includeDigits || /[A-Za-z]/.test(c))) + : [...text]; + const parts = chars.map(c => encodeLetter(c, opts)); + return options.separator === 'none' ? parts.join('') : parts.join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const opts = { + durationMode: options.durationMode || 'full-alphabet', + includeDigits: !!options.includeDigits + }; + const tokens = splitTokens(text, options.separator || 'space'); + return tokens.map(t => decodeToken(t, opts)).join(''); + }, + preview: function(text, options) { + if (!text) return '[acéré]'; + return this.func(text.slice(0, 8), options) + '...'; + }, + detector: function(text) { + const solfegeHits = (text.match(/\b(ré|re|mi|fa|sol|la|si|do)\b/gi) || []).length; + const symbolPairs = (text.match(/[♪●𝅝♩](?:Ré|Re|Mi|Fa|Sol|La|Si|Do)/g) || []).length; + return solfegeHits >= 2 || symbolPairs >= 2; + } + }); +})(); diff --git a/src/transformers/cipher/adfgvx.js b/src/transformers/cipher/adfgvx.js new file mode 100644 index 0000000..f705333 --- /dev/null +++ b/src/transformers/cipher/adfgvx.js @@ -0,0 +1,162 @@ +// ADFGVX cipher (WWI extension of ADFGX with digits) +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'ADFGVX Cipher', + priority: 60, + category: 'cipher', + key: 'KEYWORD', + coords: ['A', 'D', 'F', 'G', 'V', 'X'], + square: [ + ['A', 'B', 'C', 'D', 'E', 'F'], + ['G', 'H', 'I', 'J', 'K', 'L'], + ['M', 'N', 'O', 'P', 'Q', 'R'], + ['S', 'T', 'U', 'V', 'W', 'X'], + ['Y', 'Z', '0', '1', '2', '3'], + ['4', '5', '6', '7', '8', '9'] + ], + configurableOptions: [ + { + id: 'polybiusKey', + label: 'Polybius square keyword', + type: 'text', + default: '' + }, + { + id: 'key', + label: 'Transposition keyword', + type: 'text', + default: 'KEYWORD' + } + ], + _buildSquare: function(polybiusKey) { + const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + const key = String(polybiusKey || '').toUpperCase().replace(/[^A-Z0-9]/g, '').replace(/J/g, 'I'); + const seen = new Set(); + let cells = ''; + for (let i = 0; i < key.length; i++) { + const c = key[i]; + if (!seen.has(c)) { + seen.add(c); + cells += c; + } + } + for (let i = 0; i < alphabet.length; i++) { + const c = alphabet[i]; + if (!seen.has(c)) { + seen.add(c); + cells += c; + } + } + cells = cells.padEnd(36, 'X').slice(0, 36); + const square = []; + for (let row = 0; row < 6; row++) { + square.push(cells.slice(row * 6, row * 6 + 6).split('')); + } + return square; + }, + _squareFor: function(options) { + options = options || {}; + const polybiusKey = String(options.polybiusKey || '').trim(); + return polybiusKey ? this._buildSquare(polybiusKey) : this.square; + }, + _transKey: function(options) { + const k = options && options.key !== undefined && options.key !== null + ? String(options.key) + : null; + return (k || this.key || 'KEYWORD').toUpperCase().replace(/[^A-Z]/g, ''); + }, + _charToPair: function(char, square) { + const c = char === 'J' ? 'I' : char; + for (let row = 0; row < 6; row++) { + for (let col = 0; col < 6; col++) { + if (square[row][col] === c) { + return this.coords[row] + this.coords[col]; + } + } + } + return ''; + }, + _pairToChar: function(pair, square) { + if (pair.length !== 2) return ''; + const row = this.coords.indexOf(pair[0]); + const col = this.coords.indexOf(pair[1]); + if (row < 0 || col < 0) return ''; + return square[row][col]; + }, + _columnarEncode: function(text, transKey) { + const numCols = transKey.length; + const numRows = Math.ceil(text.length / numCols); + const grid = []; + let idx = 0; + for (let row = 0; row < numRows; row++) { + grid[row] = []; + for (let col = 0; col < numCols; col++) { + grid[row][col] = idx < text.length ? text[idx++] : ''; + } + } + const keyOrder = transKey.split('').map((char, index) => ({ char, index })) + .sort((a, b) => (a.char === b.char ? a.index - b.index : a.char.localeCompare(b.char))); + let result = ''; + for (const item of keyOrder) { + for (let row = 0; row < numRows; row++) { + if (grid[row][item.index]) result += grid[row][item.index]; + } + } + return result; + }, + _columnarDecode: function(text, transKey) { + const numCols = transKey.length; + const numRows = Math.ceil(text.length / numCols); + const keyOrder = transKey.split('').map((char, index) => ({ char, index })) + .sort((a, b) => (a.char === b.char ? a.index - b.index : a.char.localeCompare(b.char))); + const grid = Array.from({ length: numRows }, () => new Array(numCols)); + let textIdx = 0; + for (const item of keyOrder) { + const colLen = Math.ceil((text.length - item.index) / numCols); + for (let row = 0; row < colLen && textIdx < text.length; row++) { + grid[row][item.index] = text[textIdx++]; + } + } + let out = ''; + for (let row = 0; row < numRows; row++) { + for (let col = 0; col < numCols; col++) { + if (grid[row][col]) out += grid[row][col]; + } + } + return out; + }, + func: function(text, options) { + options = options || {}; + const transKey = this._transKey(options); + if (!transKey.length) return text; + const square = this._squareFor(options); + const cleaned = text.toUpperCase().replace(/[^A-Z0-9]/g, '').replace(/J/g, 'I'); + if (!cleaned.length) return text; + let pairs = ''; + for (const char of cleaned) pairs += this._charToPair(char, square); + return this._columnarEncode(pairs, transKey); + }, + reverse: function(text, options) { + options = options || {}; + const transKey = this._transKey(options); + if (!transKey.length) return text; + const square = this._squareFor(options); + const cleaned = text.toUpperCase().replace(/[^ADFGVX]/g, ''); + if (!cleaned.length || cleaned.length % 2 !== 0) return text; + const pairs = this._columnarDecode(cleaned, transKey); + let result = ''; + for (let i = 0; i < pairs.length; i += 2) { + result += this._pairToChar(pairs.slice(i, i + 2), square); + } + return result; + }, + preview: function(text, options) { + if (!text) return '[adfgvx]'; + return this.func(text.slice(0, 4), options).slice(0, 12) + '...'; + }, + detector: function(text) { + const cleaned = text.replace(/\s/g, '').toUpperCase(); + return cleaned.length >= 10 && cleaned.length % 2 === 0 && /^[ADFGVX]+$/.test(cleaned); + } +}); diff --git a/src/transformers/cipher/amsco.js b/src/transformers/cipher/amsco.js new file mode 100644 index 0000000..8b6c8b8 --- /dev/null +++ b/src/transformers/cipher/amsco.js @@ -0,0 +1,90 @@ +// AMSCO cipher (alternating 1/2 column heights + keyword transposition) +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'AMSCO Cipher', + priority: 60, + category: 'cipher', + key: 'KEY', + configurableOptions: [ + { id: 'key', label: 'Keyword', type: 'text', default: 'KEY' } + ], + _key: function(options) { + const k = options && options.key != null ? String(options.key) : null; + return (k || this.key || 'KEY').toUpperCase().replace(/[^A-Z]/g, ''); + }, + _colCapacity: function(colIndex) { + return colIndex % 2 === 0 ? 1 : 2; + }, + _sortedColumns: function(key) { + return key.split('').map((char, index) => ({ char, index })) + .sort((a, b) => (a.char === b.char ? a.index - b.index : a.char.localeCompare(b.char))); + }, + _columnLengths: function(textLen, numCols) { + const lens = new Array(numCols).fill(0); + let idx = 0; + while (idx < textLen) { + for (let col = 0; col < numCols && idx < textLen; col++) { + const take = Math.min(this._colCapacity(col), textLen - idx); + lens[col] += take; + idx += take; + } + } + return lens; + }, + func: function(text, options) { + const key = this._key(options); + if (!key.length) return text; + const cleaned = text.toUpperCase().replace(/[^A-Z]/g, ''); + if (!cleaned.length) return text; + + const numCols = key.length; + const columns = Array.from({ length: numCols }, () => ''); + let idx = 0; + while (idx < cleaned.length) { + for (let col = 0; col < numCols && idx < cleaned.length; col++) { + const take = Math.min(this._colCapacity(col), cleaned.length - idx); + columns[col] += cleaned.slice(idx, idx + take); + idx += take; + } + } + + let out = ''; + for (const item of this._sortedColumns(key)) out += columns[item.index]; + return out; + }, + reverse: function(text, options) { + const key = this._key(options); + if (!key.length) return text; + const cleaned = text.toUpperCase().replace(/[^A-Z]/g, ''); + if (!cleaned.length) return text; + + const numCols = key.length; + const lens = this._columnLengths(cleaned.length, numCols); + const columns = Array.from({ length: numCols }, () => ''); + let idx = 0; + for (const item of this._sortedColumns(key)) { + const len = lens[item.index]; + columns[item.index] = cleaned.slice(idx, idx + len); + idx += len; + } + + const colOffsets = new Array(numCols).fill(0); + let out = ''; + let remaining = cleaned.length; + while (remaining > 0) { + for (let col = 0; col < numCols && remaining > 0; col++) { + const take = Math.min(this._colCapacity(col), columns[col].length - colOffsets[col], remaining); + if (take <= 0) continue; + out += columns[col].slice(colOffsets[col], colOffsets[col] + take); + colOffsets[col] += take; + remaining -= take; + } + } + return out; + }, + preview: function(text, options) { + if (!text) return '[amsco]'; + return this.func(text.slice(0, 8), options).slice(0, 12) + '...'; + } +}); diff --git a/src/transformers/cipher/book-cipher.js b/src/transformers/cipher/book-cipher.js new file mode 100644 index 0000000..3aeec91 --- /dev/null +++ b/src/transformers/cipher/book-cipher.js @@ -0,0 +1,64 @@ +// Book cipher (word indices in reference text) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const DEFAULT_BOOK = 'the quick brown fox jumps over the lazy dog hello world while pack my box with five dozen liquor jugs'; + + return new BaseTransformer({ + name: 'Book Cipher', + priority: 55, + category: 'cipher', + configurableOptions: [ + { id: 'book', label: 'Reference text (book)', type: 'text', default: DEFAULT_BOOK }, + { + id: 'separator', + label: 'Index separator', + type: 'select', + default: ' ', + options: [ + { value: ' ', label: 'Space' }, + { value: '-', label: 'Dash' }, + { value: '.', label: 'Dot' } + ] + } + ], + _bookWords: function(options) { + const book = String(options && options.book != null ? options.book : DEFAULT_BOOK).toLowerCase(); + return book.match(/[a-z0-9']+/g) || []; + }, + func: function(text, options) { + options = options || {}; + const words = this._bookWords(options); + const sep = options.separator != null ? String(options.separator) : ' '; + if (!words.length) return text; + const inputWords = text.match(/[a-zA-Z0-9']+/g) || []; + const indices = inputWords.map(w => { + const target = w.toLowerCase(); + const idx = words.indexOf(target); + return idx >= 0 ? String(idx + 1) : '?'; + }); + return indices.join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const words = this._bookWords(options); + if (!words.length) return text; + const sep = options.separator != null ? String(options.separator) : ' '; + const esc = sep.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const parts = text.trim().split(new RegExp(esc.length ? esc : '\\s+')); + return parts.map(p => { + const n = parseInt(p, 10); + if (!Number.isFinite(n) || n < 1 || n > words.length) return p; + return words[n - 1]; + }).join(' '); + }, + preview: function(text, options) { + if (!text) return '[book]'; + return this.func(text.slice(0, 20), options).slice(0, 20) + '...'; + }, + detector: function(text) { + const cleaned = text.trim(); + return /^[\d\s.\-]+$/.test(cleaned) && cleaned.replace(/\D/g, '').length >= 2; + } + }); +})(); diff --git a/src/transformers/cipher/codons.js b/src/transformers/cipher/codons.js new file mode 100644 index 0000000..1211e95 --- /dev/null +++ b/src/transformers/cipher/codons.js @@ -0,0 +1,54 @@ +// Genetic codons — letters encoded as DNA triplets (RNA codon table, simplified) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const MAP = { + 'A': 'GCT', 'B': 'TGT', 'C': 'TGT', 'D': 'GAT', 'E': 'GAA', 'F': 'TTT', + 'G': 'GGT', 'H': 'CAT', 'I': 'ATT', 'J': 'TAT', 'K': 'AAA', 'L': 'TTA', + 'M': 'ATG', 'N': 'AAT', 'O': 'TAT', 'P': 'CCT', 'Q': 'CAA', 'R': 'CGT', + 'S': 'TCT', 'T': 'ACT', 'U': 'TGT', 'V': 'GTT', 'W': 'TGG', 'X': 'TAG', + 'Y': 'TAT', 'Z': 'TGT' + }; + const REV = {}; + for (const [k, v] of Object.entries(MAP)) { + if (!REV[v]) REV[v] = k; + } + + return new BaseTransformer({ + name: 'Codons (Genetic Code)', + priority: 84, + category: 'encoding', + configurableOptions: [ + { + id: 'separator', + label: 'Separator between codons', + type: 'select', + default: 'space', + options: [ + { value: 'space', label: 'Space' }, + { value: 'none', label: 'None' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const sep = options.separator === 'none' ? '' : ' '; + return [...text.toUpperCase()].filter(c => /[A-Z]/.test(c)).map(c => MAP[c] || c).join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const tokens = options.separator === 'none' + ? text.match(/[ACGT]{3}/gi) || [] + : text.trim().split(/\s+/); + return tokens.map(t => REV[t.toUpperCase()] || '').join(''); + }, + preview: function(text, options) { + if (!text) return '[codon]'; + return this.func(text.slice(0, 6), options); + }, + detector: function(text) { + const tokens = text.trim().split(/\s+/); + return tokens.length >= 2 && tokens.every(t => /^[ACGT]{3}$/i.test(t)); + } + }); +})(); diff --git a/src/transformers/cipher/double-transposition.js b/src/transformers/cipher/double-transposition.js new file mode 100644 index 0000000..f3baf7e --- /dev/null +++ b/src/transformers/cipher/double-transposition.js @@ -0,0 +1,89 @@ +// Double columnar transposition cipher +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + function columnarEncode(text, key, pad) { + pad = pad || 'X'; + const numCols = key.length; + const numRows = Math.ceil(text.length / numCols); + const grid = []; + let idx = 0; + for (let row = 0; row < numRows; row++) { + grid[row] = []; + for (let col = 0; col < numCols; col++) { + grid[row][col] = idx < text.length ? text[idx++] : pad; + } + } + const order = key.split('').map((char, index) => ({ char, index })) + .sort((a, b) => (a.char === b.char ? a.index - b.index : a.char.localeCompare(b.char))); + let out = ''; + for (const item of order) { + for (let row = 0; row < numRows; row++) out += grid[row][item.index]; + } + return out; + } + + function columnarDecode(text, key, pad) { + pad = pad || 'X'; + const numCols = key.length; + const numRows = Math.ceil(text.length / numCols); + const order = key.split('').map((char, index) => ({ char, index })) + .sort((a, b) => (a.char === b.char ? a.index - b.index : a.char.localeCompare(b.char))); + const grid = Array.from({ length: numRows }, () => new Array(numCols)); + let textIdx = 0; + for (const item of order) { + for (let row = 0; row < numRows && textIdx < text.length; row++) { + grid[row][item.index] = text[textIdx++]; + } + } + let out = ''; + for (let row = 0; row < numRows; row++) { + for (let col = 0; col < numCols; col++) { + if (grid[row][col]) out += grid[row][col]; + } + } + return out.replace(new RegExp((pad || 'X').replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '+$'), ''); + } + + return new BaseTransformer({ + name: 'Double Transposition', + priority: 60, + category: 'cipher', + key1: 'FIRST', + key2: 'SECOND', + configurableOptions: [ + { id: 'key1', label: 'First keyword', type: 'text', default: 'FIRST' }, + { id: 'key2', label: 'Second keyword', type: 'text', default: 'SECOND' }, + { + id: 'padChar', + label: 'Padding character', + type: 'text', + default: 'X' + } + ], + _keys: function(options) { + options = options || {}; + const k1 = String(options.key1 != null ? options.key1 : this.key1).toUpperCase().replace(/[^A-Z]/g, ''); + const k2 = String(options.key2 != null ? options.key2 : this.key2).toUpperCase().replace(/[^A-Z]/g, ''); + const padChar = String(options.padChar != null ? options.padChar : 'X').charAt(0) || 'X'; + return { k1: k1 || 'FIRST', k2: k2 || 'SECOND', padChar }; + }, + func: function(text, options) { + const { k1, k2, padChar } = this._keys(options); + const cleaned = text.replace(/\s/g, '').toUpperCase(); + if (!cleaned.length) return text; + return columnarEncode(columnarEncode(cleaned, k1, padChar), k2, padChar); + }, + reverse: function(text, options) { + const { k1, k2, padChar } = this._keys(options); + const cleaned = text.replace(/\s/g, '').toUpperCase(); + if (!cleaned.length) return text; + const esc = padChar.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return columnarDecode(columnarDecode(cleaned, k2, padChar), k1, padChar).replace(new RegExp(esc + '+$'), ''); + }, + preview: function(text, options) { + if (!text) return '[double-trans]'; + return this.func(text.slice(0, 8), options).slice(0, 12) + '...'; + } + }); +})(); diff --git a/src/transformers/cipher/fractionated-morse.js b/src/transformers/cipher/fractionated-morse.js new file mode 100644 index 0000000..4c255e3 --- /dev/null +++ b/src/transformers/cipher/fractionated-morse.js @@ -0,0 +1,134 @@ +// Fractionated Morse cipher (Morse pairs mapped via Polybius-style square) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const MORSE = { + 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', + 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', + 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', + 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', + 'Y': '-.--', 'Z': '--..' + }; + const REV_MORSE = Object.fromEntries(Object.entries(MORSE).map(([k, v]) => [v, k])); + const SQUARE = [ + ['A', 'B', 'C', 'D', 'E'], + ['F', 'G', 'H', 'I', 'K'], + ['L', 'M', 'N', 'O', 'P'], + ['Q', 'R', 'S', 'T', 'U'], + ['V', 'W', 'X', 'Y', 'Z'] + ]; + const SYM = ['.', '-']; + + function morseStream(text) { + return text.toUpperCase().replace(/[^A-Z]/g, '').split('') + .map(c => MORSE[c] || '') + .join(''); + } + + function streamToText(stream) { + const chars = []; + let buf = ''; + for (const s of stream) { + if (s === '.' || s === '-') buf += s; + else if (buf) { + chars.push(buf); + buf = ''; + } + } + if (buf) chars.push(buf); + let out = ''; + for (const code of chars) out += REV_MORSE[code] || ''; + return out; + } + + function pairToChar(a, b) { + const row = SYM.indexOf(a); + const col = SYM.indexOf(b); + if (row < 0 || col < 0) return ''; + return SQUARE[row][col]; + } + + function charToPair(ch) { + const c = ch === 'J' ? 'I' : ch; + for (let r = 0; r < 5; r++) { + for (let col = 0; col < 5; col++) { + if (SQUARE[r][col] === c) return SYM[r] + SYM[col]; + } + } + return ''; + } + + return new BaseTransformer({ + name: 'Fractionated Morse', + priority: 65, + category: 'technical', + configurableOptions: [ + { + id: 'letterSeparator', + label: 'Separator between letters', + type: 'text', + default: '' + }, + { + id: 'wordSeparator', + label: 'Separator between words', + type: 'select', + default: ' ', + options: [ + { value: ' ', label: 'Space' }, + { value: ' / ', label: 'Slash (Morse style)' }, + { value: ' | ', label: 'Pipe' }, + { value: '', label: 'None' } + ] + } + ], + _opts: function(options) { + options = options || {}; + return { + letterSeparator: options.letterSeparator != null ? String(options.letterSeparator) : '', + wordSeparator: options.wordSeparator != null ? String(options.wordSeparator) : ' ' + }; + }, + func: function(text, options) { + const { letterSeparator, wordSeparator } = this._opts(options); + const words = text.toUpperCase().match(/[A-Z]+/g) || []; + if (!words.length) { + return text; + } + return words.map(function(word) { + const stream = morseStream(word); + let out = ''; + for (let i = 0; i < stream.length; i += 2) { + if (i + 1 < stream.length) { + if (out && letterSeparator) { + out += letterSeparator; + } + out += pairToChar(stream[i], stream[i + 1]); + } + } + return out; + }).join(wordSeparator); + }, + reverse: function(text, options) { + const { letterSeparator, wordSeparator } = this._opts(options); + let chunks = [text]; + if (wordSeparator) { + chunks = text.split(wordSeparator); + } + return chunks.map(function(chunk) { + const cleaned = letterSeparator + ? chunk.split(letterSeparator).join('') + : chunk; + let pairs = ''; + for (const ch of cleaned.toUpperCase().replace(/[^A-Z]/g, '')) { + pairs += charToPair(ch); + } + return streamToText(pairs); + }).join(' '); + }, + preview: function(text, options) { + if (!text) return '[frac-morse]'; + return this.func(text.slice(0, 6), options) + '...'; + } + }); +})(); diff --git a/src/transformers/cipher/keyword-shift.js b/src/transformers/cipher/keyword-shift.js new file mode 100644 index 0000000..059d41d --- /dev/null +++ b/src/transformers/cipher/keyword-shift.js @@ -0,0 +1,58 @@ +// Keyword shift cipher (Caesar shift from keyword letters) +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Keyword Shift Cipher', + priority: 60, + category: 'cipher', + key: 'KEY', + configurableOptions: [ + { id: 'key', label: 'Keyword', type: 'text', default: 'KEY' } + ], + _keyStr: function(options) { + const k = options && options.key != null ? String(options.key) : null; + return (k || this.key || 'KEY').toUpperCase().replace(/[^A-Z]/g, ''); + }, + _shiftChar: function(c, shift, decode) { + const code = c.charCodeAt(0); + const s = ((shift % 26) + 26) % 26; + const delta = decode ? (26 - s) % 26 : s; + if (code >= 65 && code <= 90) return String.fromCharCode(((code - 65 + delta) % 26) + 65); + if (code >= 97 && code <= 122) return String.fromCharCode(((code - 97 + delta) % 26) + 97); + return c; + }, + func: function(text, options) { + const key = this._keyStr(options); + if (!key.length) return text; + let out = ''; + let j = 0; + for (let i = 0; i < text.length; i++) { + const c = text[i]; + if (/[a-zA-Z]/.test(c)) { + const shift = key[j % key.length].charCodeAt(0) - 65; + out += this._shiftChar(c, shift, false); + j++; + } else out += c; + } + return out; + }, + reverse: function(text, options) { + const key = this._keyStr(options); + if (!key.length) return text; + let out = ''; + let j = 0; + for (let i = 0; i < text.length; i++) { + const c = text[i]; + if (/[a-zA-Z]/.test(c)) { + const shift = key[j % key.length].charCodeAt(0) - 65; + out += this._shiftChar(c, shift, true); + j++; + } else out += c; + } + return out; + }, + preview: function(text, options) { + if (!text) return '[keyword-shift]'; + return this.func(text.slice(0, 8), options) + '...'; + } +}); diff --git a/src/transformers/cipher/monoalphabetic.js b/src/transformers/cipher/monoalphabetic.js new file mode 100644 index 0000000..ab0cc4c --- /dev/null +++ b/src/transformers/cipher/monoalphabetic.js @@ -0,0 +1,94 @@ +// Monoalphabetic substitution cipher (custom 26-letter alphabet) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const PLAIN = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + + return new BaseTransformer({ + name: 'Monoalphabetic Substitution', + priority: 60, + category: 'cipher', + configurableOptions: [ + { + id: 'keyword', + label: 'Keyword (builds cipher alphabet when set)', + type: 'text', + default: '' + }, + { + id: 'alphabet', + label: 'Cipher alphabet (26 unique letters A-Z)', + type: 'text', + default: 'QWERTYUIOPASDFGHJKLZXCVBNM' + } + ], + _keywordAlpha: function(keyword) { + const kw = String(keyword || '').toUpperCase().replace(/[^A-Z]/g, ''); + const seen = new Set(); + let alpha = ''; + for (let i = 0; i < kw.length; i++) { + const c = kw[i]; + if (!seen.has(c)) { + seen.add(c); + alpha += c; + } + } + for (let i = 0; i < PLAIN.length; i++) { + const c = PLAIN[i]; + if (!seen.has(c)) { + seen.add(c); + alpha += c; + } + } + return alpha.slice(0, 26); + }, + _cipherAlpha: function(options) { + const keyword = String(options && options.keyword != null ? options.keyword : '').trim(); + if (keyword) { + return this._keywordAlpha(keyword); + } + const raw = String(options && options.alphabet != null ? options.alphabet : 'QWERTYUIOPASDFGHJKLZXCVBNM') + .toUpperCase() + .replace(/[^A-Z]/g, ''); + const seen = new Set(); + let alpha = ''; + for (const c of raw) { + if (!seen.has(c)) { + seen.add(c); + alpha += c; + } + } + for (const c of PLAIN) { + if (!seen.has(c)) { + seen.add(c); + alpha += c; + } + } + return alpha.slice(0, 26); + }, + _maps: function(options) { + const cipher = this._cipherAlpha(options); + const enc = {}; + const dec = {}; + for (let i = 0; i < 26; i++) { + enc[PLAIN[i]] = cipher[i]; + enc[PLAIN[i].toLowerCase()] = cipher[i].toLowerCase(); + dec[cipher[i]] = PLAIN[i]; + dec[cipher[i].toLowerCase()] = PLAIN[i].toLowerCase(); + } + return { enc, dec }; + }, + func: function(text, options) { + const { enc } = this._maps(options || {}); + return [...text].map(c => enc[c] || c).join(''); + }, + reverse: function(text, options) { + const { dec } = this._maps(options || {}); + return [...text].map(c => dec[c] || c).join(''); + }, + preview: function(text, options) { + if (!text) return '[mono]'; + return this.func(text.slice(0, 8), options) + '...'; + } + }); +})(); diff --git a/src/transformers/cipher/multiplicative-cipher.js b/src/transformers/cipher/multiplicative-cipher.js new file mode 100644 index 0000000..45079b6 --- /dev/null +++ b/src/transformers/cipher/multiplicative-cipher.js @@ -0,0 +1,50 @@ +// Multiplicative cipher (mod 26; key must be coprime with 26) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const COPRIMES = [1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25]; + const INVERSES = { 1: 1, 3: 9, 5: 21, 7: 15, 9: 3, 11: 19, 15: 7, 17: 23, 19: 11, 21: 5, 23: 17, 25: 25 }; + + return new BaseTransformer({ + name: 'Multiplicative Cipher', + priority: 60, + category: 'cipher', + multiplier: 5, + configurableOptions: [ + { + id: 'multiplier', + label: 'Multiplier (coprime with 26)', + type: 'select', + default: '5', + options: COPRIMES.map(n => ({ value: String(n), label: String(n) })) + } + ], + _mult: function(options) { + const m = Number(options && options.multiplier != null ? options.multiplier : this.multiplier); + return COPRIMES.includes(m) ? m : 5; + }, + func: function(text, options) { + const mult = this._mult(options || {}); + return [...text].map(c => { + const code = c.charCodeAt(0); + if (code >= 65 && code <= 90) return String.fromCharCode(((code - 65) * mult % 26) + 65); + if (code >= 97 && code <= 122) return String.fromCharCode(((code - 97) * mult % 26) + 97); + return c; + }).join(''); + }, + reverse: function(text, options) { + const mult = this._mult(options || {}); + const inv = INVERSES[mult] || 21; + return [...text].map(c => { + const code = c.charCodeAt(0); + if (code >= 65 && code <= 90) return String.fromCharCode(((code - 65) * inv % 26) + 65); + if (code >= 97 && code <= 122) return String.fromCharCode(((code - 97) * inv % 26) + 97); + return c; + }).join(''); + }, + preview: function(text, options) { + if (!text) return '[mult]'; + return this.func(text.slice(0, 6), options) + '...'; + } + }); +})(); diff --git a/src/transformers/format/qwerty-shift.js b/src/transformers/cipher/qwerty-shift.js similarity index 100% rename from src/transformers/format/qwerty-shift.js rename to src/transformers/cipher/qwerty-shift.js diff --git a/src/transformers/cipher/route-cipher.js b/src/transformers/cipher/route-cipher.js new file mode 100644 index 0000000..b9947b2 --- /dev/null +++ b/src/transformers/cipher/route-cipher.js @@ -0,0 +1,163 @@ +// Route / path cipher (grid + reading route) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + function buildGrid(text, cols, pad) { + const cleaned = text.replace(/\s/g, '').toUpperCase(); + const rows = Math.ceil(cleaned.length / cols); + const grid = []; + let idx = 0; + for (let r = 0; r < rows; r++) { + grid[r] = []; + for (let c = 0; c < cols; c++) { + grid[r][c] = idx < cleaned.length ? cleaned[idx++] : pad; + } + } + return { grid, rows, cols, len: cleaned.length }; + } + + function readSpiral(grid, rows, cols) { + const out = []; + let top = 0; + let bottom = rows - 1; + let left = 0; + let right = cols - 1; + while (top <= bottom && left <= right) { + for (let c = left; c <= right; c++) out.push(grid[top][c]); + top++; + for (let r = top; r <= bottom; r++) out.push(grid[r][right]); + right--; + if (top <= bottom) { + for (let c = right; c >= left; c--) out.push(grid[bottom][c]); + bottom--; + } + if (left <= right) { + for (let r = bottom; r >= top; r--) out.push(grid[r][left]); + left++; + } + } + return out.join(''); + } + + function stripPad(text, pad) { + const esc = pad.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return text.replace(new RegExp(esc + '+$'), ''); + } + + function writeSpiral(text, rows, cols, pad) { + const grid = Array.from({ length: rows }, () => new Array(cols).fill(pad)); + let top = 0; + let bottom = rows - 1; + let left = 0; + let right = cols - 1; + let idx = 0; + while (top <= bottom && left <= right && idx < text.length) { + for (let c = left; c <= right && idx < text.length; c++) grid[top][c] = text[idx++]; + top++; + for (let r = top; r <= bottom && idx < text.length; r++) grid[r][right] = text[idx++]; + right--; + if (top <= bottom) { + for (let c = right; c >= left && idx < text.length; c--) grid[bottom][c] = text[idx++]; + bottom--; + } + if (left <= right) { + for (let r = bottom; r >= top && idx < text.length; r--) grid[r][left] = text[idx++]; + left++; + } + } + return grid; + } + + return new BaseTransformer({ + name: 'Route Cipher', + priority: 60, + category: 'cipher', + configurableOptions: [ + { id: 'cols', label: 'Grid columns', type: 'number', default: 5, min: 2, max: 20, step: 1 }, + { + id: 'route', + label: 'Reading route', + type: 'select', + default: 'spiral', + options: [ + { value: 'spiral', label: 'Spiral (clockwise)' }, + { value: 'rows', label: 'Row by row' }, + { value: 'cols', label: 'Column by column' }, + { value: 'snake', label: 'Snake rows' } + ] + }, + { + id: 'padChar', + label: 'Padding character', + type: 'text', + default: 'X' + } + ], + _opts: function(options) { + options = options || {}; + const cols = Math.max(2, Number(options.cols != null ? options.cols : 5) || 5); + const route = options.route || 'spiral'; + const padChar = String(options.padChar != null ? options.padChar : 'X').charAt(0) || 'X'; + return { cols, route, padChar }; + }, + _readRoute: function(grid, rows, cols, route) { + if (route === 'rows') return grid.flat().join(''); + if (route === 'cols') { + let out = ''; + for (let c = 0; c < cols; c++) { + for (let r = 0; r < rows; r++) out += grid[r][c]; + } + return out; + } + if (route === 'snake') { + return grid.map((row, i) => (i % 2 ? [...row].reverse() : row).join('')).join(''); + } + return readSpiral(grid, rows, cols); + }, + func: function(text, options) { + const { cols, route, padChar } = this._opts(options); + const { grid, rows } = buildGrid(text, cols, padChar); + const raw = this._readRoute(grid, rows, cols, route); + return stripPad(raw, padChar); + }, + reverse: function(text, options) { + const { cols, route, padChar } = this._opts(options); + const cleaned = text.replace(/\s/g, '').toUpperCase(); + if (!cleaned.length) return text; + const rows = Math.ceil(cleaned.length / cols); + if (route === 'spiral') { + const grid = writeSpiral(cleaned, rows, cols, padChar); + let out = ''; + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) out += grid[r][c]; + } + return stripPad(out, padChar); + } + if (route === 'rows') return cleaned; + if (route === 'cols') { + const grid = Array.from({ length: rows }, () => new Array(cols).fill(padChar)); + let idx = 0; + for (let c = 0; c < cols; c++) { + for (let r = 0; r < rows && idx < cleaned.length; r++) grid[r][c] = cleaned[idx++]; + } + return stripPad(grid.flat().join(''), padChar); + } + if (route === 'snake') { + const grid = Array.from({ length: rows }, () => new Array(cols).fill(padChar)); + let idx = 0; + for (let r = 0; r < rows; r++) { + const order = r % 2 ? [...Array(cols).keys()].reverse() : [...Array(cols).keys()]; + for (const c of order) { + if (idx < cleaned.length) grid[r][c] = cleaned[idx++]; + } + } + return stripPad(grid.flat().join(''), padChar); + } + return cleaned; + }, + preview: function(text, options) { + if (!text) return '[route]'; + return this.func(text.slice(0, 10), options).slice(0, 12) + '...'; + } + }); +})(); diff --git a/src/transformers/technical/tap-code.js b/src/transformers/cipher/tap-code.js similarity index 100% rename from src/transformers/technical/tap-code.js rename to src/transformers/cipher/tap-code.js diff --git a/src/transformers/cipher/trithemius.js b/src/transformers/cipher/trithemius.js new file mode 100644 index 0000000..c9d52b2 --- /dev/null +++ b/src/transformers/cipher/trithemius.js @@ -0,0 +1,48 @@ +// Trithemius cipher (progressive Caesar / tabula recta rows) +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Trithemius Cipher', + priority: 60, + category: 'cipher', + configurableOptions: [ + { id: 'startShift', label: 'Starting shift', type: 'number', default: 0, min: 0, max: 25, step: 1 }, + { id: 'step', label: 'Shift increment per letter', type: 'number', default: 1, min: 1, max: 25, step: 1 } + ], + _opts: function(options) { + options = options || {}; + return { + start: Number(options.startShift != null ? options.startShift : 0) || 0, + step: Number(options.step != null ? options.step : 1) || 1 + }; + }, + _transform: function(text, options, decode) { + const { start, step } = this._opts(options); + let out = ''; + let letterIdx = 0; + for (let i = 0; i < text.length; i++) { + const c = text[i]; + const code = c.charCodeAt(0); + const shift = (start + letterIdx * step) % 26; + const delta = decode ? (26 - shift) % 26 : shift; + if (code >= 65 && code <= 90) { + out += String.fromCharCode(((code - 65 + delta) % 26) + 65); + letterIdx++; + } else if (code >= 97 && code <= 122) { + out += String.fromCharCode(((code - 97 + delta) % 26) + 97); + letterIdx++; + } else out += c; + } + return out; + }, + func: function(text, options) { + return this._transform(text, options, false); + }, + reverse: function(text, options) { + return this._transform(text, options, true); + }, + preview: function(text, options) { + if (!text) return '[trithemius]'; + return this.func(text.slice(0, 8), options) + '...'; + } +}); diff --git a/src/transformers/cipher/vernam.js b/src/transformers/cipher/vernam.js new file mode 100644 index 0000000..6bd590c --- /dev/null +++ b/src/transformers/cipher/vernam.js @@ -0,0 +1,49 @@ +// Vernam cipher (one-time pad style additive mod 26 with key) +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Vernam Cipher', + priority: 60, + category: 'cipher', + key: 'SECRET', + configurableOptions: [ + { id: 'key', label: 'Key (pad)', type: 'text', default: 'SECRET' } + ], + _keyStr: function(options) { + const k = options && options.key != null ? String(options.key) : null; + return (k || this.key || 'SECRET').toUpperCase().replace(/[^A-Z]/g, ''); + }, + _apply: function(text, options, decode) { + const key = this._keyStr(options); + if (!key.length) return text; + let out = ''; + let j = 0; + for (let i = 0; i < text.length; i++) { + const c = text[i]; + const code = c.charCodeAt(0); + const k = key[j % key.length].charCodeAt(0) - 65; + if (code >= 65 && code <= 90) { + out += String.fromCharCode(decode + ? ((code - 65 + 26 - k) % 26) + 65 + : ((code - 65 + k) % 26) + 65); + j++; + } else if (code >= 97 && code <= 122) { + out += String.fromCharCode(decode + ? ((code - 97 + 26 - k) % 26) + 97 + : ((code - 97 + k) % 26) + 97); + j++; + } else out += c; + } + return out; + }, + func: function(text, options) { + return this._apply(text, options, false); + }, + reverse: function(text, options) { + return this._apply(text, options, true); + }, + preview: function(text, options) { + if (!text) return '[vernam]'; + return this.func(text.slice(0, 8), options) + '...'; + } +}); diff --git a/src/transformers/concealment/acrostic.js b/src/transformers/concealment/acrostic.js new file mode 100644 index 0000000..ac12451 --- /dev/null +++ b/src/transformers/concealment/acrostic.js @@ -0,0 +1,122 @@ +// Acrostic — read or build messages from initial letters +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const TEMPLATES = [ + '{letter}idden words carry meaning beyond the surface.', + '{letter}ach line begins with the secret letter.', + '{letter}ften the first letter tells the story.', + '{letter}essages can hide in plain sight.', + '{letter}eaders who look closely will find clues.' + ]; + + function extractAcrostic(text, mode, includeSpecial) { + if (mode === 'words') { + if (includeSpecial) { + const words = text.match(/\S+/g) || []; + return words.map(function(word) { + return word.charAt(0) || ''; + }).join(''); + } + const words = text.match(/[a-zA-Z0-9']+/g) || []; + return words.map(function(word) { + return word.replace(/[^a-zA-Z0-9]/g, '')[0] || ''; + }).join(''); + } + return text.split(/\r?\n/).map(function(line) { + const trimmed = line.trim(); + if (!trimmed) { + return ''; + } + if (includeSpecial) { + return trimmed.charAt(0); + } + const match = trimmed.match(/[a-zA-Z0-9]/); + return match ? match[0] : ''; + }).join(''); + } + + function normalizeSecret(text, includeSpecial) { + if (includeSpecial) { + return text.replace(/\s+/g, ''); + } + return text.replace(/[^a-zA-Z0-9]/g, ''); + } + + function formatAcrosticLine(letter, template) { + const line = template.replace(/\{letter\}/g, letter); + if (/[a-zA-Z]/.test(letter)) { + return line.charAt(0).toUpperCase() + line.slice(1); + } + return line; + } + + return new BaseTransformer({ + name: 'Acrostic', + priority: 46, + category: 'concealment', + description: 'Extract hidden messages from the first letter of each line or word, or build acrostic cover text.', + configurableOptions: [ + { + id: 'mode', + label: 'Read letters from', + type: 'select', + default: 'lines', + options: [ + { value: 'lines', label: 'First letter of each line' }, + { value: 'words', label: 'First letter of each word' } + ] + }, + { + id: 'includeSpecial', + label: 'Include special characters', + type: 'boolean', + default: false + }, + { + id: 'lineTemplate', + label: 'Custom line template ({letter} placeholder)', + type: 'text', + default: '' + } + ], + func: function(text, options) { + options = options || {}; + const mode = options.mode === 'words' ? 'words' : 'lines'; + const includeSpecial = !!options.includeSpecial; + const customTemplate = String(options.lineTemplate || '').trim(); + const secret = normalizeSecret(text, includeSpecial); + if (!secret) { + return text; + } + if (mode === 'words') { + return secret.split('').join(' '); + } + return secret.split('').map(function(letter, index) { + const template = customTemplate || TEMPLATES[index % TEMPLATES.length]; + return formatAcrosticLine(letter, template); + }).join('\n'); + }, + reverse: function(text, options) { + options = options || {}; + const mode = options.mode === 'words' ? 'words' : 'lines'; + const includeSpecial = !!options.includeSpecial; + return extractAcrostic(text, mode, includeSpecial); + }, + preview: function(text, options) { + if (!text) { + return '[acrostic]'; + } + return this.func(text.slice(0, 5), options); + }, + detector: function(text) { + if (/\n/.test(text)) { + const lines = text.split(/\r?\n/).filter(function(line) { + return line.trim().length > 0; + }); + return lines.length >= 2; + } + return (text.match(/[a-zA-Z0-9']+/g) || []).length >= 3; + } + }); +})(); diff --git a/src/transformers/concealment/cardan-grille.js b/src/transformers/concealment/cardan-grille.js new file mode 100644 index 0000000..f80c846 --- /dev/null +++ b/src/transformers/concealment/cardan-grille.js @@ -0,0 +1,208 @@ +// Cardan grille — write/read through a rotating hole template +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const DEFAULT_GRILLE = '#.#.\n.#.#\n#.#.\n.#.#'; + const DEFAULT_FILLER = 'abcdefghijklmnopqrstuvwxyz'; + + function parseGrille(pattern, size) { + const rows = String(pattern || DEFAULT_GRILLE) + .trim() + .split(/\r?\n/) + .map(function(row) { return row.trim(); }) + .filter(function(row) { return row.length > 0; }); + + const holes = []; + for (let r = 0; r < rows.length && r < size; r++) { + for (let c = 0; c < rows[r].length && c < size; c++) { + const ch = rows[r][c]; + if (ch === '#' || ch === 'X' || ch === 'x' || ch === '1') { + holes.push([r, c]); + } + } + } + return holes.sort(function(a, b) { + return a[0] - b[0] || a[1] - b[1]; + }); + } + + function rotateCoord(r, c, size) { + return [c, size - 1 - r]; + } + + function rotateHoles(holes, size) { + return holes.map(function(pair) { + return rotateCoord(pair[0], pair[1], size); + }).sort(function(a, b) { + return a[0] - b[0] || a[1] - b[1]; + }); + } + + function makeGrid(size, filler) { + const grid = []; + for (let r = 0; r < size; r++) { + grid.push(new Array(size).fill('')); + } + return grid; + } + + function flattenGrid(grid) { + return grid.map(function(row) { return row.join(''); }).join('\n'); + } + + function parseGrid(text, size) { + const cleaned = text.replace(/[^a-zA-Z0-9]/g, '').toLowerCase(); + const grid = makeGrid(size); + let index = 0; + for (let r = 0; r < size; r++) { + for (let c = 0; c < size; c++) { + grid[r][c] = cleaned[index] || 'x'; + index++; + } + } + return grid; + } + + function holeSets(baseHoles, size, rotations) { + const sets = [baseHoles]; + let current = baseHoles; + for (let i = 1; i < rotations; i++) { + current = rotateHoles(current, size); + sets.push(current); + } + return sets; + } + + function nextFillerChar(filler, index) { + return filler[index % filler.length] || 'x'; + } + + return new BaseTransformer({ + name: 'Cardan Grille', + priority: 44, + category: 'concealment', + description: 'Hide text using a Cardan grille template with optional 90° rotations.', + inputKind: 'textarea', + configurableOptions: [ + { + id: 'gridSize', + label: 'Grid size', + type: 'number', + default: 4, + min: 3, + max: 8, + step: 1 + }, + { + id: 'rotations', + label: 'Grille rotations', + type: 'select', + default: '4', + options: [ + { value: '1', label: '1 (single pass)' }, + { value: '4', label: '4 (classic Cardan)' } + ] + }, + { + id: 'grille', + label: 'Grille pattern (# = hole, . = cover)', + type: 'text', + default: DEFAULT_GRILLE + }, + { + id: 'filler', + label: 'Decoy letters for empty cells', + type: 'text', + default: DEFAULT_FILLER + }, + { + id: 'outputFormat', + label: 'Output layout', + type: 'select', + default: 'grid', + options: [ + { value: 'grid', label: 'Grid with newlines' }, + { value: 'flat', label: 'Continuous string' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const size = Math.max(3, Math.min(8, parseInt(options.gridSize, 10) || 4)); + const rotations = Math.max(1, Math.min(4, parseInt(options.rotations, 10) || 4)); + const filler = String(options.filler || DEFAULT_FILLER).replace(/[^a-zA-Z0-9]/g, '').toLowerCase() || DEFAULT_FILLER; + const message = text.replace(/[^a-zA-Z0-9]/g, '').toLowerCase(); + if (!message) { + return text; + } + + const baseHoles = parseGrille(options.grille || DEFAULT_GRILLE, size); + const sets = holeSets(baseHoles, size, rotations); + const grid = makeGrid(size); + let msgIndex = 0; + let fillerIndex = 0; + + sets.forEach(function(holes) { + holes.forEach(function(pair) { + const r = pair[0]; + const c = pair[1]; + if (!grid[r][c]) { + grid[r][c] = message[msgIndex] || nextFillerChar(filler, fillerIndex++); + if (message[msgIndex]) { + msgIndex++; + } + } + }); + }); + + for (let r = 0; r < size; r++) { + for (let c = 0; c < size; c++) { + if (!grid[r][c]) { + grid[r][c] = nextFillerChar(filler, fillerIndex++); + } + } + } + + if (options.outputFormat === 'flat') { + return grid.map(function(row) { return row.join(''); }).join(''); + } + return flattenGrid(grid); + }, + reverse: function(text, options) { + options = options || {}; + const size = Math.max(3, Math.min(8, parseInt(options.gridSize, 10) || 4)); + const rotations = Math.max(1, Math.min(4, parseInt(options.rotations, 10) || 4)); + const baseHoles = parseGrille(options.grille || DEFAULT_GRILLE, size); + const sets = holeSets(baseHoles, size, rotations); + const grid = parseGrid(text, size); + let result = ''; + + sets.forEach(function(holes) { + holes.forEach(function(pair) { + result += grid[pair[0]][pair[1]] || ''; + }); + }); + + return result; + }, + preview: function(text, options) { + if (!text) { + return '[cardan]'; + } + return this.func(text.slice(0, 8), options); + }, + detector: function(text) { + const lines = text.trim().split(/\r?\n/); + if (lines.length < 3) { + return false; + } + const widths = lines.map(function(line) { + return line.replace(/\s/g, '').length; + }); + const first = widths[0]; + return first >= 3 && widths.every(function(width) { + return width === first; + }); + } + }); +})(); diff --git a/src/transformers/concealment/homoglyph.js b/src/transformers/concealment/homoglyph.js new file mode 100644 index 0000000..084eb79 --- /dev/null +++ b/src/transformers/concealment/homoglyph.js @@ -0,0 +1,34 @@ +// Homoglyph substitution — visually confusable Unicode characters +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const TO = { + 'A': '\u0410', 'B': '\u0412', 'C': '\u0421', 'E': '\u0415', 'H': '\u041D', + 'I': '\u0406', 'J': '\u0408', 'K': '\u041A', 'M': '\u041C', 'N': '\u041D', + 'O': '\u041E', 'P': '\u0420', 'S': '\u0405', 'T': '\u0422', 'X': '\u0425', + 'Y': '\u0423', 'a': '\u0430', 'c': '\u0441', 'e': '\u0435', 'i': '\u0456', + 'j': '\u0458', 'o': '\u043E', 'p': '\u0440', 's': '\u0455', 'x': '\u0445', + 'y': '\u0443' + }; + const REV = {}; + for (const [k, v] of Object.entries(TO)) REV[v] = k; + + return new BaseTransformer({ + name: 'Homoglyph Generator', + priority: 70, + category: 'unicode', + func: function(text) { + return [...text].map(c => TO[c] || c).join(''); + }, + reverse: function(text) { + return [...text].map(c => REV[c] || c).join(''); + }, + preview: function(text) { + if (!text) return '[homoglyph]'; + return this.func(text.slice(0, 12)); + }, + detector: function(text) { + return /[\u0400-\u04FF]/.test(text) && /[A-Za-z]/.test(text) === false; + } + }); +})(); diff --git a/src/transformers/encoding/invisible-text.js b/src/transformers/concealment/invisible-text.js similarity index 100% rename from src/transformers/encoding/invisible-text.js rename to src/transformers/concealment/invisible-text.js diff --git a/src/transformers/concealment/null-cipher.js b/src/transformers/concealment/null-cipher.js new file mode 100644 index 0000000..f5f859d --- /dev/null +++ b/src/transformers/concealment/null-cipher.js @@ -0,0 +1,154 @@ +// Null cipher — hide/extract letters at a fixed position in each word +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + function syntheticWord(letter, position) { + const L = letter.toLowerCase(); + const pads = ['a', 'e', 'i', 'o', 'u', 'r', 's', 't', 'n', 'l']; + let word = ''; + const len = Math.max(position + 1, 3); + for (let i = 0; i < len; i++) { + if (i === position - 1) { + word += L; + } else { + word += pads[i % pads.length]; + } + } + return word; + } + + function pickCoverWord(letter, position, index, coverWords) { + const target = letter.toLowerCase(); + const pos = position - 1; + if (coverWords && coverWords.length) { + for (let i = 0; i < coverWords.length; i++) { + const word = coverWords[(index + i) % coverWords.length]; + const clean = word.replace(/[^a-zA-Z0-9]/g, ''); + if (clean[pos] && clean[pos].toLowerCase() === target) { + return word; + } + } + } + return syntheticWord(letter, position); + } + + function normalizeSecret(text, includeSpecial) { + if (includeSpecial) { + return text.replace(/\s+/g, ''); + } + return text.replace(/[^a-zA-Z0-9]/g, ''); + } + + function extractNull(text, options) { + options = options || {}; + const scope = options.scope === 'text' ? 'text' : 'words'; + const includeSpecial = !!options.includeSpecial; + const position = Math.max(1, Math.min(10, parseInt(options.position, 10) || 2)); + + if (scope === 'text') { + const source = includeSpecial ? text.replace(/\s/g, '') : text.replace(/[^a-zA-Z0-9]/g, ''); + let out = ''; + for (let i = position - 1; i < source.length; i += position) { + out += source[i]; + } + return out; + } + + const pos = position - 1; + if (includeSpecial) { + const words = text.match(/\S+/g) || []; + return words.map(function(word) { + return word.charAt(pos) || ''; + }).join(''); + } + + const words = text.match(/[a-zA-Z0-9']+/g) || []; + return words.map(function(word) { + const clean = word.replace(/[^a-zA-Z0-9]/g, ''); + if (pos >= 0 && pos < clean.length) { + return clean[pos]; + } + return ''; + }).join(''); + } + + return new BaseTransformer({ + name: 'Null Cipher', + priority: 45, + category: 'concealment', + description: 'Conceal a message in cover text by fixing one letter position in each word, or extract hidden letters.', + configurableOptions: [ + { + id: 'scope', + label: 'Extraction scope', + type: 'select', + default: 'words', + options: [ + { value: 'words', label: 'Nth letter of each word' }, + { value: 'text', label: 'Every Nth letter of full text' } + ] + }, + { + id: 'position', + label: 'Letter position / interval (1 = first letter or every letter)', + type: 'number', + default: 2, + min: 1, + max: 10, + step: 1 + }, + { + id: 'includeSpecial', + label: 'Include special characters', + type: 'boolean', + default: false + }, + { + id: 'coverText', + label: 'Cover word pool (optional, space-separated)', + type: 'text', + default: '' + }, + { + id: 'wordSeparator', + label: 'Word separator', + type: 'select', + default: ' ', + options: [ + { value: ' ', label: 'Space' }, + { value: '\n', label: 'New line' }, + { value: ', ', label: 'Comma' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const position = Math.max(1, Math.min(10, parseInt(options.position, 10) || 2)); + const sep = options.wordSeparator != null ? String(options.wordSeparator) : ' '; + const includeSpecial = !!options.includeSpecial; + const secret = normalizeSecret(text, includeSpecial); + if (!secret) { + return text; + } + const coverWords = String(options.coverText || '') + .match(/[a-zA-Z0-9']+/g) || []; + const words = secret.split('').map(function(ch, index) { + return pickCoverWord(ch, position, index, coverWords); + }); + return words.join(sep); + }, + reverse: function(text, options) { + return extractNull(text, options || {}); + }, + preview: function(text, options) { + if (!text) { + return '[null-cipher]'; + } + return this.func(text.slice(0, 8), options) + '...'; + }, + detector: function(text) { + const words = text.match(/[a-zA-Z0-9']+/g) || []; + return words.length >= 3 && words.length <= 500; + } + }); +})(); diff --git a/src/transformers/concealment/trevanion.js b/src/transformers/concealment/trevanion.js new file mode 100644 index 0000000..af3bb76 --- /dev/null +++ b/src/transformers/concealment/trevanion.js @@ -0,0 +1,133 @@ +// Trevanion cipher — extract letters N positions after punctuation (steganography) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const DEFAULT_TRIGGERS = '.,!?;:\u2014'; + const DEFAULT_FILLER = 'the quick brown fox jumps over the lazy dog while a warm wind blew across the open field'; + + function isTrigger(ch, triggers) { + return triggers.includes(ch); + } + + function extractLetter(text, start, offset, lettersOnly) { + let count = 0; + for (let i = start; i < text.length; i++) { + const c = text[i]; + if (lettersOnly) { + if (/[A-Za-z]/.test(c)) count++; + } else if (!/\s/.test(c)) { + count++; + } + if (count === offset) return c; + } + return ''; + } + + function postTriggerSnippet(letter, offset) { + const pads = 'etaoinshrdlucmfwypvbgkqjxz'; + let out = ''; + for (let i = 1; i <= offset; i++) { + if (i === offset) { + out += letter; + } else { + out += pads[(letter.charCodeAt(0) + i * 3) % pads.length]; + } + } + return out; + } + + function buildCover(secret, options) { + const offset = Math.max(1, Number(options.offset) || 3); + const triggers = options.triggers || DEFAULT_TRIGGERS; + const trigger = triggers.charAt(0) || ','; + const coverWords = String(options.fillerWords || DEFAULT_FILLER) + .match(/[a-zA-Z']+/g) || DEFAULT_FILLER.split(/\s+/); + let out = ''; + for (let si = 0; si < secret.length; si++) { + if (si > 0) out += ' '; + out += coverWords[si % coverWords.length]; + out += trigger; + out += postTriggerSnippet(secret[si], offset); + } + return out.replace(/\s+/g, ' ').trim(); + } + + return new BaseTransformer({ + name: 'Trevanion Cipher', + priority: 75, + category: 'concealment', + description: 'Hide letters N positions after punctuation marks, or extract them from cover text.', + configurableOptions: [ + { + id: 'offset', + label: 'Letters after each mark (N)', + type: 'number', + default: 3, + min: 1, + max: 20 + }, + { + id: 'lettersOnly', + label: 'Count letters only (ignore spaces/punct)', + type: 'boolean', + default: true + }, + { + id: 'triggers', + label: 'Trigger punctuation characters', + type: 'text', + default: '.,!?;:' + }, + { + id: 'mode', + label: 'Encode mode', + type: 'select', + default: 'embed', + options: [ + { value: 'embed', label: 'Build cover text around secret' }, + { value: 'decode', label: 'Extract only (input is cover text)' } + ] + }, + { + id: 'fillerWords', + label: 'Cover word pool (space-separated)', + type: 'text', + default: '' + } + ], + func: function(text, options) { + options = options || {}; + if (options.mode === 'decode') return text; + const secret = text.replace(/\s/g, ''); + if (!secret) return text; + return buildCover(secret, options); + }, + reverse: function(text, options) { + options = options || {}; + const offset = Number(options.offset) || 3; + const triggers = options.triggers || DEFAULT_TRIGGERS; + const lettersOnly = options.lettersOnly !== false; + let out = ''; + for (let i = 0; i < text.length; i++) { + if (isTrigger(text[i], triggers)) { + const ch = extractLetter(text, i + 1, offset, lettersOnly); + if (ch) out += ch; + } + } + return out; + }, + preview: function(text, options) { + if (!text) return '[trevanion]'; + const dec = this.reverse(text, options); + return dec ? dec.slice(0, 16) + '...' : this.func(text.slice(0, 8), options).slice(0, 24) + '...'; + }, + detector: function(text) { + const triggers = DEFAULT_TRIGGERS; + let hits = 0; + for (let i = 0; i < text.length; i++) { + if (isTrigger(text[i], triggers)) hits++; + } + return hits >= 3; + } + }); +})(); diff --git a/src/transformers/format/whitespace-steganography.js b/src/transformers/concealment/whitespace-steganography.js similarity index 100% rename from src/transformers/format/whitespace-steganography.js rename to src/transformers/concealment/whitespace-steganography.js diff --git a/src/transformers/format/zerowidth-steganography.js b/src/transformers/concealment/zerowidth-steganography.js similarity index 100% rename from src/transformers/format/zerowidth-steganography.js rename to src/transformers/concealment/zerowidth-steganography.js diff --git a/src/transformers/encoding/bibi-binary.js b/src/transformers/encoding/bibi-binary.js new file mode 100644 index 0000000..2b1285d --- /dev/null +++ b/src/transformers/encoding/bibi-binary.js @@ -0,0 +1,74 @@ +// Bibi-binary (Boby Lapointe) — hex syllables for text via UTF-8 bytes +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const HEX_TO_BIBI = { + '0': 'HO', '1': 'HA', '2': 'HE', '3': 'HI', '4': 'BO', '5': 'BA', + '6': 'BE', '7': 'BI', '8': 'KO', '9': 'KA', 'a': 'KE', 'b': 'KI', + 'c': 'DO', 'd': 'DA', 'e': 'DE', 'f': 'DI' + }; + const BIBI_TO_HEX = {}; + for (const [h, b] of Object.entries(HEX_TO_BIBI)) BIBI_TO_HEX[b.toUpperCase()] = h; + + function parseBibiToken(t) { + return BIBI_TO_HEX[t.toUpperCase()] || null; + } + + return new BaseTransformer({ + name: 'Bibi-binary Code', + priority: 85, + category: 'encoding', + configurableOptions: [ + { + id: 'separator', + label: 'Separator between syllable pairs', + type: 'select', + default: 'space', + options: [ + { value: 'space', label: 'Space' }, + { value: 'none', label: 'None' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const sep = options.separator === 'none' ? '' : ' '; + const bytes = new TextEncoder().encode(text); + const hex = Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join(''); + const pairs = []; + for (let i = 0; i < hex.length; i += 2) { + const pair = hex.slice(i, i + 2); + pairs.push(HEX_TO_BIBI[pair[0]] + HEX_TO_BIBI[pair[1]]); + } + return pairs.join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const tokens = options.separator === 'none' + ? text.match(/[A-Za-z]{4}/g) || [] + : text.trim().split(/\s+/); + let hex = ''; + for (const tok of tokens) { + if (tok.length !== 4) continue; + const h1 = parseBibiToken(tok.slice(0, 2)); + const h2 = parseBibiToken(tok.slice(2, 4)); + if (h1 && h2) hex += h1 + h2; + } + if (!hex || hex.length % 2 !== 0) return text; + const bytes = new Uint8Array(hex.match(/.{2}/g).map(h => parseInt(h, 16))); + try { + return new TextDecoder().decode(bytes); + } catch (e) { + return text; + } + }, + preview: function(text, options) { + if (!text) return '[bibi]'; + return this.func(text.slice(0, 3), options); + }, + detector: function(text) { + const tokens = text.trim().split(/\s+/); + return tokens.length >= 2 && tokens.every(t => /^[A-Za-z]{4}$/.test(t)); + } + }); +})(); diff --git a/src/transformers/format/bitwise-not.js b/src/transformers/encoding/bitwise-not.js similarity index 100% rename from src/transformers/format/bitwise-not.js rename to src/transformers/encoding/bitwise-not.js diff --git a/src/transformers/technical/brainfuck.js b/src/transformers/encoding/brainfuck.js similarity index 100% rename from src/transformers/technical/brainfuck.js rename to src/transformers/encoding/brainfuck.js diff --git a/src/transformers/encoding/decabit.js b/src/transformers/encoding/decabit.js new file mode 100644 index 0000000..65a4bd6 --- /dev/null +++ b/src/transformers/encoding/decabit.js @@ -0,0 +1,86 @@ +// Decabit code (10-pulse ripple control encoding, ASCII 0-126) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + // Patterns use + (positive pulse) and - (negative pulse); index = code value + const PATTERNS = [ + '--+-+++-+-', '+--+++--+-', '+--++-+-+-', '+--+-++-+-', '----+++-++', + '++--+++---', '++--++--+-', '++--+-+-+-', '++---++-+-', '---++++-+-', + '+-+-+++---', '+-+-+-+-+-', '+-+--++-+-', '+---++-++-', '+---++--++', + '--+++-++--', '---++-+++-', '+---+-++-+', '+--++--+-+', '+--++-+--+', + '+-+++--+--', '+--+++-+--', '++--+-++--', '-+-++-++--', '+--++--++-', + '+-+++-+---', '++-+--++--', '+-+-+-++--', '+--+-+++--', '+--+--++-+', + '+-++-++---', '+-++-+-+--', '+-+-++-+--', '+---++++--', '+-+--+-++-', + '+++--++---', '+++--+-+--', '+++---++--', '++---+++--', '--+-++++--', + '++--++-+--', '-+-+-+-++-', '++----+++-', '+----+-+++', '++---+-+-+', + '++-+-+-+--', '++-+-+--+-', '+++----++-', '++--+--++-', '+--+-+-++-', + '++++----+-', '++-++---+-', '+-+++---+-', '-++++---+-', '+-+-+---++', + '+++-++----', '+++-+-+---', '+-+-+--++-', '-++-+--++-', '+++-+----', + '-+++-++---', '-+-+-++-+-', '++---++--+', '++-+--+--+', '++-+++----', + '++++--+---', '+--++++---', '-+-++++---', '++-+--+-+-', '-++---+++-', + '+---+-+++-', '--+-+-+++-', '+----++++-', '--+--++++-', '+++---+-+-', + '+-++---++-', '+--+--+++-', '--++--+++-', '-+-+---+-++', '-+++--+-+-', + '-+-++-+-+-', '-+++---++-', '-+-++--++-', '-+---++++-', '-++++--+--', + '-++-++-+--', '--++++-+--', '--++-+++--', '--++-+-++-', '-++++----', + '--++++--+-', '--++-++-+-', '+-++----++', '-+-+++--+-', '-++-+-+-+-', + '-+--++-++-', '---+++-++-', '-+--+-+++-', '+---+++-+-', '-+--+++-+-', + '+-+-++--+-', '+--++-++--', '++-++--+--', '+-++--++--', '+-+--+++--', + '-++--+++--', '++---+-++-', '++-+---++-', '+++-+---+-', '+++-+--+--', + '++-+-++---', '++-++-+---', '+-+---+++-', '+-++--+-+-', '-+-+--+++-', + '-+++-+-+--', '+-++-+--+-', '-++-+++---', '+++--+--+-', '+++++-----', + '-+++++----', '--+++++---', '---+++++--', '----+++++-', '++++++++++' + ]; + const TO_CODE = {}; + const TO_CHAR = {}; + for (let i = 0; i < PATTERNS.length; i++) { + TO_CODE[i] = PATTERNS[i]; + TO_CHAR[PATTERNS[i]] = String.fromCharCode(i); + } + + function normalizePattern(raw) { + return raw.replace(/[+]/g, '+').replace(/[-−–—]/g, '-').replace(/\s/g, ''); + } + + return new BaseTransformer({ + name: 'Decabit Code', + priority: 90, + category: 'electronics', + configurableOptions: [ + { + id: 'groupSeparator', + label: 'Separator between pulse groups', + type: 'select', + default: 'space', + options: [ + { value: 'space', label: 'Space' }, + { value: 'newline', label: 'New line' }, + { value: 'none', label: 'None' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const sep = options.groupSeparator === 'newline' ? '\n' + : (options.groupSeparator === 'none' ? '' : ' '); + return [...text].map(c => TO_CODE[c.charCodeAt(0)] || TO_CODE[63]).join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const splitRe = options.groupSeparator === 'newline' ? /\n+/ + : (options.groupSeparator === 'none' ? /(?=[+-]{10})/ : /\s+/); + const groups = text.trim().split(splitRe).filter(Boolean); + return groups.map(g => { + const pat = normalizePattern(g); + return TO_CHAR[pat] || ''; + }).join(''); + }, + preview: function(text, options) { + if (!text) return '[decabit]'; + return this.func(text.slice(0, 3), options) + '...'; + }, + detector: function(text) { + const groups = text.trim().split(/\s+/); + return groups.length >= 2 && groups.every(g => /^[+-]{10}$/.test(normalizePattern(g))); + } + }); +})(); diff --git a/src/transformers/encoding/emoji-encoding.js b/src/transformers/encoding/emoji-encoding.js index 7002f6d..74448db 100644 --- a/src/transformers/encoding/emoji-encoding.js +++ b/src/transformers/encoding/emoji-encoding.js @@ -1,79 +1,113 @@ -// emoji encoding transform +// Base256Emoji — multiformats/multibase (1 byte ↔ 1 emoji, lossless) +// https://github.com/multiformats/multibase/blob/master/rfcs/Base256Emoji.md import BaseTransformer from '../BaseTransformer.js'; -export default new BaseTransformer({ - name: 'Emoji Encoding', - priority: 250, - category: 'encoding', - // Map bytes to emoji (using common emojis) - emojiMap: [ - '😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂', '🙂', '🙃', - '😉', '😊', '😇', '🥰', '😍', '🤩', '😘', '😗', '😚', '😙', - '😋', '😛', '😜', '🤪', '😝', '🤑', '🤗', '🤭', '🤫', '🤔', - '🤐', '🤨', '😐', '😑', '😶', '😏', '😒', '🙄', '😬', '🤥', - '😌', '😔', '😪', '🤤', '😴', '😷', '🤒', '🤕', '🤢', '🤮', - '🤧', '🥵', '🥶', '😶‍🌫️', '😵', '😵‍💫', '🤯', '🤠', '🥳', '😎', - '🤓', '🧐', '😕', '😟', '🙁', '😮', '😯', '😲', '😳', '🥺', - '😦', '😧', '😨', '😰', '😥', '😢', '😭', '😱', '😖', '😣', - '😞', '😓', '😩', '😫', '🥱', '😤', '😡', '😠', '🤬', '😈', - '👿', '💀', '☠️', '💩', '🤡', '👹', '👺', '👻', '👽', '👾', - '🤖', '😺', '😸', '😹', '😻', '😼', '😽', '🙀', '😿', '😾', - '🙈', '🙉', '🙊', '💋', '💌', '💘', '💝', '💖', '💗', '💓', - '💞', '💕', '💟', '❣️', '💔', '❤️', '🧡', '💛', '💚', '💙', - '💜', '🖤', '🤍', '🤎', '💯', '💢', '💥', '💫', '💦', '💨', - '🕳️', '💣', '💬', '👁️‍🗨️', '🗨️', '🗯️', '💭', '💤', '👋', '🤚', - '🖐️', '✋', '🖖', '👌', '🤌', '🤏', '✌️', '🤞', '🤟', '🤘', - '🤙', '👈', '👉', '👆', '🖕', '👇', '☝️', '👍', '👎', '✊', - '👊', '🤛', '🤜', '👏', '🙌', '👐', '🤲', '🤝', '🙏', '✍️', - '💪', '🦾', '🦿', '🦵', '🦶', '👂', '🦻', '👃', '🧠', '🫀', - '🫁', '🦷', '🦴', '👀', '👁️', '👅', '👄', '💋', '🩸', '👶', - '🧒', '👦', '👧', '🧑', '👱', '👨', '🧔', '👨‍🦰', '👨‍🦱', '👨‍🦳', - '👨‍🦲', '👩', '👩‍🦰', '👩‍🦱', '👩‍🦳', '👩‍🦲', '🧓', '👴', '👵', '🙍', - '🙎', '🙅', '🙆', '💁', '🙋', '🧏', '🤦', '🤦‍♂️', '🤦‍♀️', '🤷', - '🤷‍♂️', '🤷‍♀️', '🙇', '🙇‍♂️', '🙇‍♀️', '🤦', '🤦‍♂️', '🤦‍♀️', '🤷', '🤷‍♂️' - ], - func: function(text) { - const bytes = new TextEncoder().encode(text); - let result = ''; - - for (const byte of bytes) { - result += this.emojiMap[byte % this.emojiMap.length] + ' '; - } - - return result.trim(); - }, - reverse: function(text) { - // Create reverse map - const reverseMap = {}; - for (let i = 0; i < this.emojiMap.length; i++) { - reverseMap[this.emojiMap[i]] = i; - } - - // Extract emojis (match any emoji, not just specific range) - const emojis = text.match(/[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu) || []; - const bytes = []; - - for (const emoji of emojis) { - if (reverseMap[emoji] !== undefined) { - bytes.push(reverseMap[emoji]); - } - } - - try { - return new TextDecoder().decode(new Uint8Array(bytes)); - } catch (e) { - return ''; - } - }, - preview: function(text) { - if (!text) return '[emoji-encoding]'; - return this.func(text.slice(0, 3)); - }, - detector: function(text) { - // Check for emoji patterns (broader range) - const emojiPattern = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu; - const matches = text.match(emojiPattern) || []; - return matches.length >= 3; - } -}); +export default (function() { + // Official 256-rune table (go-multibase / base256emoji crate) + const ALPHABET = '🚀🪐☄🛰🌌🌑🌒🌓🌔🌕🌖🌗🌘🌍🌏🌎🐉☀💻🖥💾💿😂❤😍🤣😊🙏💕😭😘👍😅👏😁🔥🥰💔💖💙😢🤔😆🙄💪😉☺👌🤗💜😔😎😇🌹🤦🎉💞✌✨🤷😱😌🌸🙌😋💗💚😏💛🙂💓🤩😄😀🖤😃💯🙈👇🎶😒🤭❣😜💋👀😪😑💥🙋😞😩😡🤪👊🥳😥🤤👉💃😳✋😚😝😴🌟😬🙃🍀🌷😻😓⭐✅🥺🌈😈🤘💦✔😣🏃💐☹🎊💘😠☝😕🌺🎂🌻😐🖕💝🙊😹🗣💫💀👑🎵🤞😛🔴😤🌼😫⚽🤙☕🏆🤫👈😮🙆🍻🍃🐶💁😲🌿🧡🎁⚡🌞🎈❌✊👋😰🤨😶🤝🚶💰🍓💢🤟🙁🚨💨🤬✈🎀🍺🤓😙💟🌱😖👶🥴▶➡❓💎💸⬇😨🌚🦋😷🕺⚠🙅😟😵👎🤲🤠🤧📌🔵💅🧐🐾🍒😗🤑🌊🤯🐷☎💧😯💆👆🎤🙇🍑❄🌴💣🐸💌📍🥀🤢👅💡💩👐📸👻🤐🤮🎼🥵🚩🍎🍊👼💍📣🥂'; + const TABLE = [...ALPHABET]; + const MULTIBASE_PREFIX = TABLE[0]; // U+1F680 🚀 — multibase code for this encoding + if (TABLE.length !== 256) { + throw new Error('Base256Emoji alphabet must contain exactly 256 codepoints'); + } + + const REVERSE = new Map(TABLE.map(function(emoji, index) { + return [emoji, index]; + })); + + function encodeBytes(bytes, multibase) { + const emojis = Array.from(bytes, function(byte) { + return TABLE[byte]; + }); + if (multibase) { + return MULTIBASE_PREFIX + emojis.join(''); + } + return emojis.join(''); + } + + function decodeToBytes(text, multibase) { + let runes = [...String(text).replace(/\s/g, '')]; + if (multibase && runes[0] === MULTIBASE_PREFIX) { + runes = runes.slice(1); + } + if (runes.length === 0) { + return null; + } + const bytes = new Uint8Array(runes.length); + for (let i = 0; i < runes.length; i++) { + const value = REVERSE.get(runes[i]); + if (value === undefined) { + return null; + } + bytes[i] = value; + } + return bytes; + } + + return new BaseTransformer({ + name: 'Base256Emoji', + priority: 265, + category: 'encoding', + description: 'Multiformats Base256Emoji encoding (multibase): each byte maps to one emoji from the standard 256-codepoint alphabet.', + configurableOptions: [ + { + key: 'multibase', + label: 'Multibase prefix', + type: 'boolean', + default: false, + help: 'Prepend the 🚀 multibase code on encode; strip it on decode (interoperable with IPFS/multibase tools).' + } + ], + func: function(text, options) { + if (!text) { + return ''; + } + const multibase = !!(options && options.multibase); + const bytes = new TextEncoder().encode(text); + return encodeBytes(bytes, multibase); + }, + reverse: function(text, options) { + if (!text) { + return ''; + } + const multibase = !!(options && options.multibase); + let bytes = decodeToBytes(text, multibase); + if (!bytes && !multibase) { + bytes = decodeToBytes(text, true); + } + if (!bytes) { + return ''; + } + try { + return new TextDecoder('utf-8', { fatal: true }).decode(bytes); + } catch (e) { + return ''; + } + }, + preview: function(text, options) { + if (!text) { + return '[base256emoji]'; + } + return this.func(text.slice(0, 4), options); + }, + detector: function(text) { + const runes = [...String(text).replace(/\s/g, '')]; + if (runes.length < 3) { + return false; + } + let start = 0; + if (runes[0] === MULTIBASE_PREFIX && runes.length > 3) { + start = 1; + } + let hits = 0; + for (let i = start; i < runes.length; i++) { + if (REVERSE.has(runes[i])) { + hits++; + } + } + const checked = runes.length - start; + return checked >= 3 && hits / checked >= 0.85; + } + }); +})(); diff --git a/src/transformers/encoding/manchester-code.js b/src/transformers/encoding/manchester-code.js new file mode 100644 index 0000000..7733bf5 --- /dev/null +++ b/src/transformers/encoding/manchester-code.js @@ -0,0 +1,63 @@ +// Manchester line code (IEEE 802.3: 0=10, 1=01) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + function toBits(text) { + const bytes = new TextEncoder().encode(text); + return Array.from(bytes).map(b => b.toString(2).padStart(8, '0')).join(''); + } + + function fromBits(bits) { + const bytes = []; + for (let i = 0; i + 8 <= bits.length; i += 8) { + bytes.push(parseInt(bits.slice(i, i + 8), 2)); + } + try { + return new TextDecoder().decode(new Uint8Array(bytes)); + } catch (e) { + return bits; + } + } + + return new BaseTransformer({ + name: 'Manchester Code', + priority: 95, + category: 'technical', + configurableOptions: [ + { + id: 'spacing', + label: 'Space between bit pairs', + type: 'boolean', + default: true + } + ], + func: function(text, options) { + options = options || {}; + const pairs = [...toBits(text)].map(b => (b === '0' ? '10' : '01')); + return options.spacing ? pairs.join(' ') : pairs.join(''); + }, + reverse: function(text, options) { + options = options || {}; + const cleaned = text.replace(/\s/g, ''); + if (!/^[01]+$/.test(cleaned) || cleaned.length % 2 !== 0) return text; + let bits = ''; + for (let i = 0; i < cleaned.length; i += 2) { + const pair = cleaned.slice(i, i + 2); + if (pair === '10') bits += '0'; + else if (pair === '01') bits += '1'; + else return text; + } + return fromBits(bits); + }, + preview: function(text, options) { + if (!text) return '[manchester]'; + const out = this.func(text.slice(0, 2), options); + return out.length > 24 ? out.slice(0, 24) + '...' : out; + }, + detector: function(text) { + const cleaned = text.replace(/\s/g, ''); + return cleaned.length >= 16 && /^[01]+$/.test(cleaned) && cleaned.length % 2 === 0 + && /^((10|01)+)$/.test(cleaned); + } + }); +})(); diff --git a/src/transformers/encoding/metaphone.js b/src/transformers/encoding/metaphone.js new file mode 100644 index 0000000..8493f50 --- /dev/null +++ b/src/transformers/encoding/metaphone.js @@ -0,0 +1,214 @@ +// Metaphone phonetic encoding +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + function metaphoneWord(word) { + let w = String(word).toUpperCase().replace(/[^A-Z]/g, ''); + if (!w) { + return ''; + } + + const first = w.charAt(0); + if (/^[AEIOU]/.test(w)) { + w = w.replace(/^([AEIOU])/, 'A'); + } else if (w.startsWith('KN') || w.startsWith('GN') || w.startsWith('PN') || w.startsWith('WR') || w.startsWith('AE')) { + w = w.slice(1); + } + + let out = first === 'A' && /^[AEIOU]/.test(String(word).toUpperCase()) ? 'A' : first; + let i = 1; + + while (i < w.length && out.length < 4) { + const ch = w.charAt(i); + const next = w.charAt(i + 1); + const prev = w.charAt(i - 1); + + if ('AEIOU'.indexOf(ch) >= 0) { + if (i === 0 || prev === 'A') { + out += 'A'; + } + i++; + continue; + } + + if (ch === 'B') { + out += 'P'; + i += next === 'B' ? 2 : 1; + continue; + } + if (ch === 'C') { + if (next === 'I' || next === 'E' || next === 'Y') { + out += 'S'; + } else { + out += 'K'; + } + i += next === 'H' && (next === 'I' || next === 'E' || next === 'Y') ? 2 : 1; + continue; + } + if (ch === 'D') { + out += next === 'G' && 'EIY'.indexOf(w.charAt(i + 2)) >= 0 ? 'J' : 'T'; + i += next === 'G' ? 3 : 1; + continue; + } + if (ch === 'F') { + out += 'F'; + i += next === 'F' ? 2 : 1; + continue; + } + if (ch === 'G') { + if (next === 'H' && 'EIY'.indexOf(w.charAt(i + 2)) < 0) { + i += 2; + continue; + } + if (next === 'N' && w.charAt(i + 2) === 'E' && w.charAt(i + 3) === 'D') { + i += 2; + continue; + } + out += 'K'; + i += next === 'G' ? 2 : 1; + continue; + } + if (ch === 'H') { + if ('AEIOU'.indexOf(prev) >= 0 && 'AEIOU'.indexOf(next) >= 0) { + out += 'H'; + } + i++; + continue; + } + if (ch === 'J') { + out += 'J'; + i += next === 'J' ? 2 : 1; + continue; + } + if (ch === 'K') { + out += 'K'; + i += next === 'K' ? 2 : 1; + continue; + } + if (ch === 'L') { + out += 'L'; + i += next === 'L' ? 2 : 1; + continue; + } + if (ch === 'M') { + out += 'M'; + i += next === 'M' ? 2 : 1; + continue; + } + if (ch === 'N') { + out += 'N'; + i += next === 'N' ? 2 : 1; + continue; + } + if (ch === 'P') { + out += next === 'H' ? 'F' : 'P'; + i += next === 'H' ? 2 : next === 'P' ? 2 : 1; + continue; + } + if (ch === 'Q') { + out += 'K'; + i += next === 'Q' ? 2 : 1; + continue; + } + if (ch === 'R') { + out += 'R'; + i += next === 'R' ? 2 : 1; + continue; + } + if (ch === 'S') { + out += next === 'H' ? 'X' : 'S'; + i += next === 'H' ? 2 : next === 'S' ? 2 : 1; + continue; + } + if (ch === 'T') { + if (next === 'I' && 'AO'.indexOf(w.charAt(i + 2)) >= 0) { + out += 'X'; + } else if (next === 'H') { + out += '0'; + } else if (next === 'C' && w.charAt(i + 2) === 'H') { + out += 'X'; + } else { + out += 'T'; + } + i += next === 'H' || (next === 'C' && w.charAt(i + 2) === 'H') ? 2 : next === 'T' ? 2 : 1; + continue; + } + if (ch === 'V') { + out += 'F'; + i += next === 'V' ? 2 : 1; + continue; + } + if (ch === 'W') { + if ('AEIOU'.indexOf(next) >= 0) { + out += 'W'; + } + i++; + continue; + } + if (ch === 'X') { + out += 'KS'; + i += next === 'X' ? 2 : 1; + continue; + } + if (ch === 'Y') { + if ('AEIOU'.indexOf(next) >= 0) { + out += 'Y'; + } + i++; + continue; + } + if (ch === 'Z') { + out += 'S'; + i += next === 'Z' ? 2 : 1; + continue; + } + i++; + } + + return out.slice(0, 4); + } + + return new BaseTransformer({ + name: 'Metaphone', + priority: 50, + category: 'format', + canDecode: false, + description: 'Phonetic encoding for English words (Metaphone algorithm).', + configurableOptions: [ + { + id: 'separator', + label: 'Word separator', + type: 'select', + default: ' ', + options: [ + { value: ' ', label: 'Space' }, + { value: '-', label: 'Dash' }, + { value: ',', label: 'Comma' }, + { value: '', label: 'None' } + ] + }, + { + id: 'uppercase', + label: 'Uppercase output', + type: 'boolean', + default: true + } + ], + func: function(text, options) { + options = options || {}; + const separator = options.separator != null ? String(options.separator) : ' '; + const uppercase = options.uppercase !== false; + const encoded = text.split(/\s+/).map(function(word) { + return metaphoneWord(word); + }).filter(Boolean); + let out = encoded.join(separator); + return uppercase ? out.toUpperCase() : out.toLowerCase(); + }, + preview: function(text, options) { + if (!text) { + return '[metaphone]'; + } + return this.func(text.slice(0, 30), options); + } + }); +})(); diff --git a/src/transformers/encoding/shadoks.js b/src/transformers/encoding/shadoks.js new file mode 100644 index 0000000..4f2ad57 --- /dev/null +++ b/src/transformers/encoding/shadoks.js @@ -0,0 +1,77 @@ +// Shadoks numeral system — GA BU ZO MEU (base 4) for text via UTF-8 bytes +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const DIGITS = ['GA', 'BU', 'ZO', 'MEU']; + const REV = { GA: 0, BU: 1, ZO: 2, MEU: 3 }; + + function toShadoks(n) { + if (n === 0) return 'GA'; + let x = n; + let out = ''; + while (x > 0) { + out = DIGITS[x % 4] + (out ? ' ' + out : ''); + x = Math.floor(x / 4); + } + return out; + } + + function fromShadoks(tokens) { + let n = 0; + for (const t of tokens) { + const v = REV[t.toUpperCase()]; + if (v === undefined) return null; + n = n * 4 + v; + } + return n; + } + + return new BaseTransformer({ + name: 'Shadoks Numeral System', + priority: 82, + category: 'encoding', + configurableOptions: [ + { + id: 'separator', + label: 'Separator between bytes', + type: 'select', + default: 'pipe', + options: [ + { value: 'pipe', label: 'Pipe (|)' }, + { value: 'space', label: 'Space' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const sep = options.separator === 'space' ? ' ' : ' | '; + const bytes = new TextEncoder().encode(text); + return Array.from(bytes).map(b => toShadoks(b)).join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const groups = options.separator === 'space' + ? text.trim().split(/\s{2,}|\|/) + : text.split('|'); + const bytes = []; + for (const g of groups) { + const tokens = g.trim().split(/\s+/).filter(Boolean); + const n = fromShadoks(tokens); + if (n === null || n > 255) return text; + bytes.push(n); + } + try { + return new TextDecoder().decode(new Uint8Array(bytes)); + } catch (e) { + return text; + } + }, + preview: function(text, options) { + if (!text) return '[shadok]'; + return this.func(text.slice(0, 2), options); + }, + detector: function(text) { + return /\b(GA|BU|ZO|MEU)(\s+(GA|BU|ZO|MEU))+\b/i.test(text); + } + }); +})(); diff --git a/src/transformers/format/group-letters.js b/src/transformers/format/group-letters.js new file mode 100644 index 0000000..bcedc39 --- /dev/null +++ b/src/transformers/format/group-letters.js @@ -0,0 +1,71 @@ +// Split text into fixed-size letter groups +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Group Letters', + priority: 50, + category: 'format', + description: 'Split letters into fixed-size groups or rejoin grouped text.', + configurableOptions: [ + { + id: 'groupSize', + label: 'Letters per group', + type: 'number', + default: 5, + min: 1, + max: 32, + step: 1 + }, + { + id: 'separator', + label: 'Group separator', + type: 'select', + default: ' ', + options: [ + { value: ' ', label: 'Space' }, + { value: '-', label: 'Dash' }, + { value: '.', label: 'Dot' }, + { value: '\n', label: 'New line' } + ] + }, + { + id: 'lettersOnly', + label: 'Letters only (ignore spaces/punctuation)', + type: 'boolean', + default: true + } + ], + func: function(text, options) { + options = options || {}; + const size = Math.max(1, Math.min(32, parseInt(options.groupSize, 10) || 5)); + const sep = options.separator != null ? String(options.separator) : ' '; + const lettersOnly = options.lettersOnly !== false; + const source = lettersOnly ? text.replace(/[^a-zA-Z]/g, '') : text.replace(/\s+/g, ''); + if (!source) { + return text; + } + const groups = []; + for (let i = 0; i < source.length; i += size) { + groups.push(source.slice(i, i + size)); + } + return groups.join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const sep = options.separator != null ? String(options.separator) : ' '; + if (sep === ' ') { + return text.replace(/\s+/g, ''); + } + const esc = sep.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return text.split(new RegExp(esc.length ? esc : '\\s+')).join(''); + }, + preview: function(text, options) { + if (!text) { + return '[group-letters]'; + } + return this.func(text.slice(0, 20), options); + }, + detector: function(text) { + return /\b[a-zA-Z]{1,8}(?:[ \-.][a-zA-Z]{1,8}){2,}\b/.test(text); + } +}); diff --git a/src/transformers/format/leading-zeros.js b/src/transformers/format/leading-zeros.js new file mode 100644 index 0000000..9614ea6 --- /dev/null +++ b/src/transformers/format/leading-zeros.js @@ -0,0 +1,66 @@ +// Pad or strip leading zeros on numeric tokens +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Leading Zeros', + priority: 50, + category: 'format', + description: 'Pad numbers with leading zeros or strip them from numeric tokens.', + configurableOptions: [ + { + id: 'mode', + label: 'Mode', + type: 'select', + default: 'pad', + options: [ + { value: 'pad', label: 'Pad to width' }, + { value: 'strip', label: 'Strip leading zeros' } + ] + }, + { + id: 'width', + label: 'Pad width', + type: 'number', + default: 4, + min: 1, + max: 32, + step: 1 + } + ], + func: function(text, options) { + options = options || {}; + const mode = options.mode === 'strip' ? 'strip' : 'pad'; + const width = Math.max(1, Math.min(32, parseInt(options.width, 10) || 4)); + + return text.replace(/\d+/g, function(num) { + if (mode === 'strip') { + const stripped = num.replace(/^0+(?=\d)/, ''); + return stripped === '' ? '0' : stripped; + } + return num.length >= width ? num : num.padStart(width, '0'); + }); + }, + reverse: function(text, options) { + options = options || {}; + const mode = options.mode === 'strip' ? 'strip' : 'pad'; + if (mode === 'pad') { + return text.replace(/\d+/g, function(num) { + const stripped = num.replace(/^0+(?=\d)/, ''); + return stripped === '' ? '0' : stripped; + }); + } + const width = Math.max(1, Math.min(32, parseInt(options.width, 10) || 4)); + return text.replace(/\d+/g, function(num) { + return num.length >= width ? num : num.padStart(width, '0'); + }); + }, + preview: function(text, options) { + if (!text) { + return '[leading-zeros]'; + } + return this.func(text.slice(0, 40), options); + }, + detector: function(text) { + return /\b0+\d+\b/.test(text) || /\b\d{1,3}\b/.test(text); + } +}); diff --git a/src/transformers/format/list-deduplicate.js b/src/transformers/format/list-deduplicate.js new file mode 100644 index 0000000..5e1ed2b --- /dev/null +++ b/src/transformers/format/list-deduplicate.js @@ -0,0 +1,50 @@ +// Remove duplicate lines from a list +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'List Deduplicate', + priority: 50, + category: 'format', + canDecode: false, + description: 'Remove duplicate lines while preserving first occurrence order.', + configurableOptions: [ + { + id: 'ignoreCase', + label: 'Ignore case when comparing', + type: 'boolean', + default: false + }, + { + id: 'trimLines', + label: 'Trim whitespace on each line', + type: 'boolean', + default: true + } + ], + func: function(text, options) { + options = options || {}; + const ignoreCase = !!options.ignoreCase; + const trimLines = options.trimLines !== false; + const lines = text.split(/\r?\n/); + const seen = {}; + const out = []; + + lines.forEach(function(line) { + let value = trimLines ? line.trim() : line; + const key = ignoreCase ? value.toLowerCase() : value; + if (seen[key]) { + return; + } + seen[key] = true; + out.push(value); + }); + + return out.join('\n'); + }, + preview: function(text, options) { + if (!text) { + return '[dedupe]'; + } + return this.func(text, options).split('\n').slice(0, 3).join('\n') + '...'; + } +}); diff --git a/src/transformers/format/shuffled-letters.js b/src/transformers/format/shuffled-letters.js new file mode 100644 index 0000000..1fae1ab --- /dev/null +++ b/src/transformers/format/shuffled-letters.js @@ -0,0 +1,74 @@ +// Shuffle letters within each word (seeded for reversible decode) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + function seededRandom(seed) { + let s = seed >>> 0; + return function() { + s = (s * 1664525 + 1013904223) >>> 0; + return s / 4294967296; + }; + } + + function shuffleWord(word, seed) { + const chars = [...word]; + const rand = seededRandom(seed); + for (let i = chars.length - 1; i > 0; i--) { + const j = Math.floor(rand() * (i + 1)); + [chars[i], chars[j]] = [chars[j], chars[i]]; + } + return chars.join(''); + } + + function unshuffleWord(word, seed) { + const n = word.length; + const rand = seededRandom(seed); + const swaps = []; + for (let i = n - 1; i > 0; i--) { + swaps.push([i, Math.floor(rand() * (i + 1))]); + } + const chars = [...word]; + for (let s = swaps.length - 1; s >= 0; s--) { + const [i, j] = swaps[s]; + [chars[i], chars[j]] = [chars[j], chars[i]]; + } + return chars.join(''); + } + + return new BaseTransformer({ + name: 'Shuffled Letters', + priority: 58, + category: 'format', + configurableOptions: [ + { + id: 'seed', + label: 'Shuffle seed (same seed to decode)', + type: 'number', + default: 42, + min: 0, + max: 999999 + } + ], + func: function(text, options) { + options = options || {}; + const seed = Number(options.seed); + const base = Number.isFinite(seed) ? seed : 42; + let wi = 0; + return text.replace(/\S+/g, w => shuffleWord(w, base + wi++)); + }, + reverse: function(text, options) { + options = options || {}; + const seed = Number(options.seed); + const base = Number.isFinite(seed) ? seed : 42; + let wi = 0; + return text.replace(/\S+/g, w => unshuffleWord(w, base + wi++)); + }, + preview: function(text, options) { + if (!text) return '[shuffle]'; + return this.func(text.slice(0, 20), options); + }, + detector: function(text) { + return false; + } + }); +})(); diff --git a/src/transformers/format/typoglycemia.js b/src/transformers/format/typoglycemia.js new file mode 100644 index 0000000..09a428f --- /dev/null +++ b/src/transformers/format/typoglycemia.js @@ -0,0 +1,67 @@ +// Typoglycemia — scramble middle letters while keeping first/last +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + function hashString(str) { + let hash = 2166136261; + for (let i = 0; i < str.length; i++) { + hash ^= str.charCodeAt(i); + hash = Math.imul(hash, 16777619); + } + return hash >>> 0; + } + + function seededShuffle(arr, seed) { + const copy = arr.slice(); + for (let i = copy.length - 1; i > 0; i--) { + seed = (Math.imul(seed, 1103515245) + 12345) >>> 0; + const j = seed % (i + 1); + const tmp = copy[i]; + copy[i] = copy[j]; + copy[j] = tmp; + } + return copy; + } + + function scrambleWord(word, minLength) { + if (word.length < minLength) { + return word; + } + const first = word.charAt(0); + const last = word.charAt(word.length - 1); + const middle = word.slice(1, -1).split(''); + return first + seededShuffle(middle, hashString(word)).join('') + last; + } + + return new BaseTransformer({ + name: 'Typoglycemia', + priority: 50, + category: 'format', + canDecode: false, + description: 'Reorder inner letters of each word — readable but scrambled (deterministic shuffle).', + configurableOptions: [ + { + id: 'minLength', + label: 'Minimum word length to scramble', + type: 'number', + default: 4, + min: 3, + max: 12, + step: 1 + } + ], + func: function(text, options) { + options = options || {}; + const minLength = Math.max(3, Math.min(12, parseInt(options.minLength, 10) || 4)); + return text.replace(/[a-zA-Z]+/g, function(word) { + return scrambleWord(word, minLength); + }); + }, + preview: function(text, options) { + if (!text) { + return '[typoglycemia]'; + } + return this.func(text.slice(0, 40), options); + } + }); +})(); diff --git a/src/transformers/format/word-letter-add.js b/src/transformers/format/word-letter-add.js new file mode 100644 index 0000000..c3e5b96 --- /dev/null +++ b/src/transformers/format/word-letter-add.js @@ -0,0 +1,72 @@ +// Insert a letter into each word at a fixed position +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + function mutateWord(word, insertChar, position) { + if (!word || !insertChar) return word; + const ch = insertChar.charAt(0); + if (position === 'start' || position === 'prefix') return ch + word; + if (position === 'end' || position === 'suffix') return word + ch; + const idx = parseInt(position, 10); + if (Number.isFinite(idx) && idx >= 0 && idx <= word.length) { + return word.slice(0, idx) + ch + word.slice(idx); + } + return word + ch; + } + + return new BaseTransformer({ + name: 'Word Letter Add', + priority: 60, + category: 'format', + configurableOptions: [ + { + id: 'insertChar', + label: 'Letter to insert', + type: 'text', + default: 'x' + }, + { + id: 'position', + label: 'Position in each word', + type: 'select', + default: 'end', + options: [ + { value: 'start', label: 'Start (prefix)' }, + { value: 'end', label: 'End (suffix)' }, + { value: '1', label: 'After 1st character' }, + { value: '2', label: 'After 2nd character' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const insertChar = (options.insertChar || 'x').charAt(0); + const position = options.position || 'end'; + return text.replace(/\S+/g, w => mutateWord(w, insertChar, position)); + }, + reverse: function(text, options) { + options = options || {}; + const insertChar = (options.insertChar || 'x').charAt(0); + const position = options.position || 'end'; + const esc = insertChar.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + if (position === 'start' || position === 'prefix') { + return text.replace(new RegExp('^' + esc + '(\\S+)|(\\s|^)' + esc + '(\\S+)', 'g'), '$1$2$3'); + } + if (position === 'end' || position === 'suffix') { + return text.replace(new RegExp('(\\S+)' + esc + '(?=\\s|$)', 'g'), '$1'); + } + const idx = parseInt(position, 10); + if (Number.isFinite(idx)) { + return text.replace(new RegExp('(\\S{' + idx + '})' + esc + '(\\S*)', 'g'), '$1$2'); + } + return text.replace(new RegExp(esc + '$'), ''); + }, + preview: function(text, options) { + if (!text) return '[+letter]'; + return this.func(text.slice(0, 24), options); + }, + detector: function(text) { + return false; + } + }); +})(); diff --git a/src/transformers/format/word-letter-change.js b/src/transformers/format/word-letter-change.js new file mode 100644 index 0000000..389bfa3 --- /dev/null +++ b/src/transformers/format/word-letter-change.js @@ -0,0 +1,59 @@ +// Replace a letter at a fixed index in each word +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + function changeAt(word, index, replacement) { + if (!word || !replacement) return word; + let i = index; + if (i < 0) i = word.length + i; + if (i < 0 || i >= word.length) return word; + return word.slice(0, i) + replacement.charAt(0) + word.slice(i + 1); + } + + return new BaseTransformer({ + name: 'Word Letter Change', + priority: 60, + category: 'format', + configurableOptions: [ + { + id: 'index', + label: 'Character index to replace', + type: 'number', + default: 0, + min: -20, + max: 20 + }, + { + id: 'replaceChar', + label: 'Replacement letter', + type: 'text', + default: 'x' + } + ], + func: function(text, options) { + options = options || {}; + const index = Number.isFinite(Number(options.index)) ? Number(options.index) : 0; + const rep = (options.replaceChar || 'x').charAt(0); + return text.replace(/\S+/g, w => changeAt(w, index, rep)); + }, + reverse: function(text, options) { + options = options || {}; + const index = Number.isFinite(Number(options.index)) ? Number(options.index) : 0; + const rep = (options.replaceChar || 'x').charAt(0); + const esc = rep.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return text.replace(/\S+/g, w => { + let i = index; + if (i < 0) i = w.length + i; + if (i < 0 || i >= w.length) return w; + const re = new RegExp('^(.{' + i + '})' + esc + '(.*)$'); + const m = w.match(re); + return m ? m[1] + '?' + m[2] : w; + }); + }, + preview: function(text, options) { + if (!text) return '[~letter]'; + return this.func(text.slice(0, 24), options); + }, + canDecode: false + }); +})(); diff --git a/src/transformers/format/word-letter-remove.js b/src/transformers/format/word-letter-remove.js new file mode 100644 index 0000000..e7e76b4 --- /dev/null +++ b/src/transformers/format/word-letter-remove.js @@ -0,0 +1,49 @@ +// Remove a letter at a fixed index from each word +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + function removeAt(word, index) { + if (!word) return word; + let i = index; + if (i < 0) i = word.length + i; + if (i < 0 || i >= word.length) return word; + return word.slice(0, i) + word.slice(i + 1); + } + + return new BaseTransformer({ + name: 'Word Letter Remove', + priority: 60, + category: 'format', + configurableOptions: [ + { + id: 'index', + label: 'Character index to remove (0 = first, -1 = last)', + type: 'number', + default: -1, + min: -20, + max: 20 + } + ], + func: function(text, options) { + options = options || {}; + const index = Number.isFinite(Number(options.index)) ? Number(options.index) : -1; + return text.replace(/\S+/g, w => removeAt(w, index)); + }, + reverse: function(text, options) { + options = options || {}; + const index = Number.isFinite(Number(options.index)) ? Number(options.index) : -1; + const placeholder = '\u0001'; + return text.replace(/\S+/g, w => { + if (index === 0 || index <= -w.length) return placeholder + w; + if (index === -1 || index === w.length - 1) return w + placeholder; + const i = index < 0 ? w.length + index : index; + return w.slice(0, i) + placeholder + w.slice(i); + }).replace(/\u0001/g, '?'); + }, + preview: function(text, options) { + if (!text) return '[-letter]'; + return this.func(text.slice(0, 24), options); + }, + canDecode: false + }); +})(); diff --git a/src/transformers/signwriting/asl-signwriting.js b/src/transformers/signwriting/asl-signwriting.js new file mode 100644 index 0000000..f621bfb --- /dev/null +++ b/src/transformers/signwriting/asl-signwriting.js @@ -0,0 +1,99 @@ +// ASL SignWriting transform +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'ASL SignWriting', + priority: 0, + canDecode: false, + description: 'American Sign Language fingerspelling in SignWriting (ISWA 2010). Horizontal or vertical layout.', + configurableOptions: [ + { + id: 'layout', + label: 'Layout', + type: 'select', + default: 'horizontal', + options: [ + { label: 'Horizontal', value: 'horizontal' }, + { label: 'Vertical', value: 'vertical' } + ] + } + ], + + THIN: '\u2004', + NBSP: '\u00A0', + + aslMap: { + 'A': '𝣷𝪜', 'B': '𝡇𝪜', 'C': '𝡭𝪜', 'D': '𝠁𝪜', 'E': '𝡊𝪜', + 'F': '𝣎𝪜', 'G': '𝣰', 'H': '𝠕𝪢', 'I': '𝢒𝪜', + 'J': '𝦢𝪬\n𝢒𝪜', 'K': '𝡀𝪜', 'L': '𝣜𝪜', 'M': '𝢍𝪜', + 'N': '𝠙𝪜', 'O': '𝡶𝪜', 'P': '𝡀𝪜𝪡', 'Q': '𝣱𝪜𝪡', + 'R': '𝠚𝪜', 'S': '𝤃𝪜', 'T': '𝣻𝪜', 'U': '𝠕𝪜', + 'V': '𝠎𝪜', 'W': '𝢇𝪜', 'X': '𝠆𝪜', 'Y': '𝢚𝪜', + 'Z': '\u2004𝥅𝪪\n𝠀𝪜', + '.': '𝪈𝪢', ',': '𝪇𝪢', ':': '𝪊𝪢', ';': '𝪉𝪢', + '(': '𝪋𝪢', ')': '𝪋𝪦', '?': '𝦟𝪝𝪬\n𝠀𝪜', + '0': '𝡶𝪜', '1': '𝠀𝪜', '2': '𝠎𝪜', '3': '𝠞𝪜', + '4': '𝡄𝪜', '5': '𝡌𝪜', '6': '𝢇𝪜', '7': '𝢥𝪜', + '8': '𝢻𝪜', '9': '𝣎𝪜' + }, + + func: function(text, options) { + var layout = (options && options.layout) || 'horizontal'; + text = text.toUpperCase(); + + if (layout === 'vertical') { + var words = text.split(/\s+/); + var wordBlocks = []; + for (var w = 0; w < words.length; w++) { + var chars = []; + for (var c = 0; c < words[w].length; c++) { + var val = this.aslMap[words[w][c]]; + if (val !== undefined) chars.push(val); + } + wordBlocks.push(chars.join('\n\n')); + } + return wordBlocks.join('\n\n\n'); + } + + // Horizontal layout + var SPACE_TOKEN = this.NBSP + this.NBSP; + var signs = []; + for (var i = 0; i < text.length; i++) { + var ch = text[i]; + if (ch === ' ') { + signs.push([SPACE_TOKEN]); + } else { + var val = this.aslMap[ch]; + if (val !== undefined) { + signs.push(val.split('\n')); + } else { + signs.push([ch]); + } + } + } + + var maxH = 1; + for (var s = 0; s < signs.length; s++) { + if (signs[s].length > maxH) maxH = signs[s].length; + } + + var lanes = []; + for (var r = 0; r < maxH; r++) lanes.push(''); + + for (var s = 0; s < signs.length; s++) { + var padCount = maxH - signs[s].length; + var padded = []; + for (var p = 0; p < padCount; p++) padded.push(this.NBSP); + for (var p = 0; p < signs[s].length; p++) padded.push(signs[s][p]); + for (var r = 0; r < maxH; r++) { + lanes[r] += padded[r]; + } + } + return lanes.join('\n'); + }, + + preview: function(text) { + if (!text) return '[ASL SignWriting]'; + return this.func(text.slice(0, 5)); + } +}); diff --git a/src/transformers/signwriting/ipa-lipreading.js b/src/transformers/signwriting/ipa-lipreading.js new file mode 100644 index 0000000..842e167 --- /dev/null +++ b/src/transformers/signwriting/ipa-lipreading.js @@ -0,0 +1,70 @@ +// IPA Lip-Reading SignWriting transform +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'IPA Lip-Reading', + priority: 0, + canDecode: false, + description: 'Converts IPA phonetic text to SignWriting lip-reading mouth shapes (ISWA 2010 head/face symbols).', + + HEAD: '𝧿', EYE: '𝨔', + + ipaToSw: { + 'p': '𝩓𝨵', 'b': '𝩓𝨮', 'm': '𝩓𝨳', + 'ɓ': '𝩓𝨮', 'ʙ': '𝩓𝨮', 'ɸ': '𝩓𝨵𝪛', 'β': '𝩓𝨮', + 'f': '𝩥𝨵', 'v': '𝩥𝨮', 'ʋ': '𝩥𝨮', 'ɱ': '𝩥𝨳', + 'θ': '𝩛𝨵', 'ð': '𝩛𝨮', + 't': '𝩜𝨵', 'd': '𝩜𝨮', 'n': '𝩜𝨳', + 's': '𝩀𝨵𝪛', 'z': '𝩀𝨮', 'l': '𝩜𝪤', 'r': '𝩟', 'ɾ': '𝩟', 'ɹ': '𝩟', 'ɻ': '𝩟', + 'ʃ': '𝩍𝨵𝪛', 'ʒ': '𝩍𝨮', + 'c': '𝩀𝨵', 'ɟ': '𝩀𝨮', 'ɲ': '𝩀𝨳', 'ç': '𝩀𝨵𝪛', 'ʝ': '𝩀𝨮', 'j': '𝩀', 'ʎ': '𝩀', + 'k': '𝩄𝨵', 'g': '𝩄𝨮', 'ŋ': '𝩄𝨳', 'x': '𝩄𝨵𝪛', 'ɣ': '𝩄𝨮', 'w': '𝩆', 'ʍ': '𝩆', + 'q': '𝩉𝨵', 'ɢ': '𝩉𝨮', 'ɴ': '𝩉𝨳', 'χ': '𝩉𝨵𝪛', 'ʁ': '𝩉𝨮', 'ʀ': '𝩉𝨮', + 'ʕ': '𝩌𝨮', 'ħ': '𝩌𝨮', 'ʔ': '𝩡', 'h': '𝩄𝨵𝪛', 'ɦ': '𝩄𝨵𝪛', + 'i': '𝩀', 'y': '𝩆', 'ɨ': '𝩀', 'ʉ': '𝩆', 'ɯ': '𝩐', 'u': '𝩆', + 'ɪ': '𝩊', 'ʏ': '𝩇', 'ʊ': '𝩇', + 'e': '𝩊', 'ø': '𝩇', 'ɘ': '𝩊', 'ɵ': '𝩇', 'ɤ': '𝩊', 'o': '𝩇', 'ə': '𝩊', 'ɚ': '𝩊', + 'ɛ': '𝩈', 'œ': '𝩈', 'ɜ': '𝩈', 'ɞ': '𝩈', 'ʌ': '𝩉', 'ɔ': '𝩉', + 'a': '𝩌', 'ɶ': '𝩌', 'ä': '𝩌', 'ɑ': '𝩌', 'ɒ': '𝩌', 'æ': '𝩌', 'ɐ': '𝩌', + 'ʘ': '𝩓𝨶', 'ǀ': '𝩣𝨶', 'ǃ': '𝩡𝨶', 'ǂ': '𝩡𝨶', 'ǁ': '𝩡𝨶' + }, + + diphthongs: { + 'aɪ': ['𝩌', '𝩀'], 'aʊ': ['𝩌', '𝩆'], 'eɪ': ['𝩊', '𝩀'], + 'oʊ': ['𝩇', '𝩆'], 'ɔɪ': ['𝩉', '𝩀'], 'əʊ': ['𝩊', '𝩆'], + 'ɪə': ['𝩊', '𝩊'], 'eə': ['𝩊', '𝩌'], 'ʊə': ['𝩇', '𝩊'] + }, + + skipChars: { 'ˈ': 1, 'ˌ': 1, 'ː': 1, ' ': 1, '\t': 1, '\n': 1 }, + + func: function(text) { + var result = [], i = 0, HEAD = this.HEAD, EYE = this.EYE; + while (i < text.length) { + if (this.skipChars[text[i]]) { i++; continue; } + // Check diphthongs (2-char) + if (i + 1 < text.length) { + var di = text[i] + text[i + 1]; + if (this.diphthongs[di]) { + var shapes = this.diphthongs[di]; + for (var s = 0; s < shapes.length; s++) { + result.push(HEAD + EYE + shapes[s]); + if (s < shapes.length - 1) result.push('\u2192'); + } + i += 2; continue; + } + } + var ch = text[i]; i++; + if (this.ipaToSw[ch]) { + result.push(HEAD + EYE + this.ipaToSw[ch]); + } else { + result.push(HEAD + EYE + '𝨻'); + } + } + return result.join(' '); + }, + + preview: function(text) { + if (!text) return '[IPA Lip-Reading]'; + return this.func(text.slice(0, 8)); + } +}); diff --git a/src/transformers/signwriting/jsl-signwriting.js b/src/transformers/signwriting/jsl-signwriting.js new file mode 100644 index 0000000..0201c15 --- /dev/null +++ b/src/transformers/signwriting/jsl-signwriting.js @@ -0,0 +1,94 @@ +// JSL SignWriting transform +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'JSL SignWriting', + priority: 0, + canDecode: false, + description: 'Japanese Sign Language fingerspelling in SignWriting (ISWA 2010). Hiragana input.', + configurableOptions: [ + { id: 'layout', label: 'Layout', type: 'select', default: 'horizontal', + options: [{ label: 'Horizontal', value: 'horizontal' }, { label: 'Vertical', value: 'vertical' }] } + ], + NBSP: '\u00A0', + SEP: '\u2001', + jslMap: { + 'あ': ['𝣷𝪜'], 'ぁ': ['𝥥𝪤', '𝣷𝪜'], 'い': ['𝢒𝪜'], 'ぃ': ['𝥥𝪤', '𝢒𝪜'], + 'う': ['𝠕𝪜'], 'ぅ': ['𝥥𝪤', '𝠕𝪜'], 'え': ['𝡦𝪜'], 'ぇ': ['𝥥𝪤', '𝡦𝪜'], + 'お': ['𝡶𝪛'], 'ぉ': ['𝥥𝪤', '𝡶𝪛'], 'か': ['𝡀𝪜'], 'ゕ': ['𝥥𝪤', '𝡀𝪜'], + 'き': ['𝣮𝪜𝪦'], 'く': ['𝡝𝪢'], 'け': ['𝡇𝪜'], 'ゖ': ['𝥥𝪤', '𝡇𝪜'], + 'こ': ['𝢀𝪛'], 'さ': ['𝤃𝪜'], 'し': ['𝠞𝪢'], 'す': ['𝠞𝪤'], 'せ': ['𝣆𝪜'], 'そ': ['𝠀𝪞'], + 'た': ['𝣷𝪞'], 'ち': ['𝢖𝪜'], 'つ': ['𝢳𝪜'], 'っ': ['𝥥𝪤', '𝢳𝪜'], + 'て': ['𝡌𝪜'], 'と': ['𝠕'], 'な': ['𝠎𝪤'], 'に': ['𝠎𝪢'], 'ぬ': ['𝠆𝪛'], 'ね': ['𝡌𝪤'], + 'の': ['𝤪𝪣', '𝠀𝪛'], 'は': ['𝠕𝪞'], 'ひ': ['𝠀𝪜'], 'ふ': ['𝣰𝪟𝪡'], 'へ': ['𝢚𝪟'], 'ほ': ['𝢀𝪝'], + 'ま': ['𝢌𝪤'], 'み': ['𝢌𝪢'], 'む': ['𝣜𝪢'], 'め': ['𝣎𝪜'], 'も': ['𝤪𝪤', '𝤜𝣴𝪝𝪦'], + 'や': ['𝢚𝪜'], 'ゃ': ['𝥥𝪤', '𝢚𝪜'], 'ゆ': ['𝢌'], 'ゅ': ['𝥥𝪤', '𝢌'], + 'よ': ['𝡄𝪢'], 'ょ': ['𝥥𝪤', '𝡄𝪢'], 'ら': ['𝠚𝪜'], 'り': ['𝦢𝪬', '𝠎𝪞'], 'る': ['𝠞𝪜'], + 'れ': ['𝣜𝪜'], 'ろ': ['𝠐𝪛'], 'わ': ['𝢆𝪜'], 'ゎ': ['𝥥𝪤', '𝢆𝪜'], + 'ゐ': ['𝥥𝪤', '𝢒𝪜'], 'ゑ': ['𝥥𝪤', '𝡦𝪜'], 'を': ['𝥥𝪤', '𝡶𝪛'], + 'ん': ['𝦢𝪤', '𝠀𝪞'], + 'が': ['𝡀𝪜𝥥𝪦'], 'ぎ': ['𝣮𝪜𝪦𝥥𝪦'], 'ぐ': ['𝡝𝪢𝥥𝪦'], 'げ': ['𝡇𝪜𝥥𝪦'], 'ご': ['𝢀𝪛𝥥𝪦'], + 'ざ': ['𝤃𝪜𝥥𝪦'], 'じ': ['𝠞𝪢𝥥𝪦'], 'ず': ['𝠞𝪤𝥥𝪦'], 'ぜ': ['𝣆𝪜𝥥𝪦'], 'ぞ': ['𝠀𝪞𝥥𝪦'], + 'だ': ['𝣷𝪞𝥥𝪦'], 'ぢ': ['𝢖𝪜𝥥𝪦'], 'づ': ['𝢳𝪜𝥥𝪦'], 'で': ['𝡌𝪜𝥥𝪦'], 'ど': ['𝠕𝥥𝪦'], + 'ば': ['𝠕𝪞𝥥𝪦'], 'び': ['𝠀𝪜𝥥𝪦'], 'ぶ': ['𝣰𝪟𝪡𝥥𝪦'], 'べ': ['𝢚𝪟𝥥𝪦'], 'ぼ': ['𝢀𝪝𝥥𝪦'], + 'ぱ': ['𝤪', '𝠕𝪞'], 'ぴ': ['𝤪', '𝠀𝪜'], 'ぷ': ['𝤪', '𝣰𝪟𝪡'], 'ぺ': ['𝤪', '𝢚𝪟'], 'ぽ': ['𝤪', '𝢀𝪝'], + 'ー': ['𝥥𝪤'], + '0': ['𝠊𝪛'], '1': ['𝠀𝪜'], '2': ['𝠎𝪜'], '3': ['𝢆𝪜'], '4': ['𝡄𝪜'], + '5': ['𝣷𝪜'], '6': ['𝣜𝪢'], '7': ['𝠞𝪢'], '8': ['𝢎𝪢'], '9': ['𝡝𝪢'], + ' ': ['\u00A0'] + }, + jslDigraph: { + 'きゃ': ['𝣮𝪜𝪦', '𝥥𝪤', '𝢚𝪜'], 'きゅ': ['𝣮𝪜𝪦', '𝥥𝪤', '𝢌'], 'きょ': ['𝣮𝪜𝪦', '𝥥𝪤', '𝡄𝪢'], + 'しゃ': ['𝠞𝪢', '𝥥𝪤', '𝢚𝪜'], 'しゅ': ['𝠞𝪢', '𝥥𝪤', '𝢌'], 'しょ': ['𝠞𝪢', '𝥥𝪤', '𝡄𝪢'], + 'ちゃ': ['𝢖𝪜', '𝥥𝪤', '𝢚𝪜'], 'ちゅ': ['𝢖𝪜', '𝥥𝪤', '𝢌'], 'ちょ': ['𝢖𝪜', '𝥥𝪤', '𝡄𝪢'], + 'にゃ': ['𝠎𝪢', '𝥥𝪤', '𝢚𝪜'], 'にゅ': ['𝠎𝪢', '𝥥𝪤', '𝢌'], 'にょ': ['𝠎𝪢', '𝥥𝪤', '𝡄𝪢'], + 'ひゃ': ['𝠀𝪜', '𝥥𝪤', '𝢚𝪜'], 'ひゅ': ['𝠀𝪜', '𝥥𝪤', '𝢌'], 'ひょ': ['𝠀𝪜', '𝥥𝪤', '𝡄𝪢'], + 'みゃ': ['𝢌𝪢', '𝥥𝪤', '𝢚𝪜'], 'みゅ': ['𝢌𝪢', '𝥥𝪤', '𝢌'], 'みょ': ['𝢌𝪢', '𝥥𝪤', '𝡄𝪢'], + 'りゃ': ['𝦢𝪬', '𝠎𝪞', '𝥥𝪤', '𝢚𝪜'], 'りゅ': ['𝦢𝪬', '𝠎𝪞', '𝥥𝪤', '𝢌'], + 'りょ': ['𝦢𝪬', '𝠎𝪞', '𝥥𝪤', '𝡄𝪢'], + 'ぎゃ': ['𝣮𝪜𝪦𝥥𝪦', '𝥥𝪤', '𝢚𝪜'], 'ぎゅ': ['𝣮𝪜𝪦𝥥𝪦', '𝥥𝪤', '𝢌'], + 'ぎょ': ['𝣮𝪜𝪦𝥥𝪦', '𝥥𝪤', '𝡄𝪢'], + 'じゃ': ['𝠞𝪢𝥥𝪦', '𝥥𝪤', '𝢚𝪜'], 'じゅ': ['𝠞𝪢𝥥𝪦', '𝥥𝪤', '𝢌'], + 'じょ': ['𝠞𝪢𝥥𝪦', '𝥥𝪤', '𝡄𝪢'], + 'ぴゃ': ['𝤪', '𝠀𝪜', '𝥥𝪤', '𝢚𝪜'], 'ぴゅ': ['𝤪', '𝠀𝪜', '𝥥𝪤', '𝢌'], + 'ぴょ': ['𝤪', '𝠀𝪜', '𝥥𝪤', '𝡄𝪢'] + }, + tokenize: function(text) { + var out = [], i = 0; + while (i < text.length) { + if (i + 1 < text.length && this.jslDigraph[text[i] + text[i + 1]]) { + out.push(this.jslDigraph[text[i] + text[i + 1]]); i += 2; + } else { + out.push(this.jslMap[text[i]] || [text[i]]); i++; + } + } + return out; + }, + func: function(text, options) { + var layout = (options && options.layout) || 'horizontal'; + if (layout === 'vertical') { + var words = text.split(/\s+/), wb = []; + for (var w = 0; w < words.length; w++) { + var tok = this.tokenize(words[w]), cb = []; + for (var t = 0; t < tok.length; t++) cb.push(tok[t].join('\n')); + wb.push(cb.join('\n\n')); + } + return wb.join('\n\n\n'); + } + var tokens = this.tokenize(text), maxH = 1; + for (var t = 0; t < tokens.length; t++) if (tokens[t].length > maxH) maxH = tokens[t].length; + var lanes = []; + for (var r = 0; r < maxH; r++) lanes.push([]); + for (var t = 0; t < tokens.length; t++) { + var pad = maxH - tokens[t].length, padded = []; + for (var p = 0; p < pad; p++) padded.push(''); + for (var p = 0; p < tokens[t].length; p++) padded.push(tokens[t][p]); + for (var r = 0; r < maxH; r++) lanes[r].push(padded[r] || this.NBSP); + } + return lanes.map(function(l) { return l.join('\u2001'); }).join('\n'); + }, + preview: function(text) { + if (!text) return '[JSL SignWriting]'; + return this.func(text.slice(0, 5)); + } +}); diff --git a/src/transformers/signwriting/libras-signwriting.js b/src/transformers/signwriting/libras-signwriting.js new file mode 100644 index 0000000..2fd5eeb --- /dev/null +++ b/src/transformers/signwriting/libras-signwriting.js @@ -0,0 +1,116 @@ +// LIBRAS SignWriting transform +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'LIBRAS SignWriting', + priority: 0, + canDecode: false, + description: 'Brazilian Sign Language (Libras) fingerspelling in SignWriting (ISWA 2010). Horizontal or vertical layout.', + configurableOptions: [ + { + id: 'layout', + label: 'Layout', + type: 'select', + default: 'horizontal', + options: [ + { label: 'Horizontal', value: 'horizontal' }, + { label: 'Vertical', value: 'vertical' } + ] + } + ], + + NBSP: '\u00A0', + + librasMap: { + 'A': ['𝣷𝪜'], 'B': ['𝡇𝪜'], 'C': ['𝡭𝪜'], + 'D': ['𝠁𝪜'], 'E': ['𝡊𝪜'], + 'F': ['𝣒𝪜'], 'G': ['𝣟𝪜'], 'H': ['𝧟', '𝡀𝪜𝪧'], + 'I': ['𝢒𝪜'], 'J': ['𝢒𝪟', '𝦢𝪬'], 'K': ['𝤮', '𝡀𝪜'], + 'L': ['𝣜𝪜'], 'M': ['𝢍𝪜'], 'N': ['𝠙𝪜'], + 'O': ['𝡶𝪜'], 'P': ['𝡀𝪟'], 'Q': ['𝣲𝪟'], + 'R': ['𝠚𝪜'], 'S': ['𝤃𝪜'], 'T': ['𝣓𝪜'], + 'U': ['𝠕𝪜'], 'V': ['𝠎𝪜'], 'W': ['𝢇𝪜'], + 'X': ['𝠊𝪟', '𝥥𝪤'], 'Y': ['𝢚𝪜'], + 'Z': ['\u2004𝥅𝪪', '𝠀𝪜'], + '0': ['𝡶𝪜'], '1': ['𝠀'], '2': ['𝠎'], '3': ['𝢆'], + '4': ['𝡄'], '5': ['𝠐𝪨'], '6': ['𝡴𝪝𝪮'], + '7': ['𝢃𝪛'], '8': ['𝧢𝪝', '𝤃𝪛'], '9': ['𝡵𝪟𝪢'] + }, + + /** + * Strip diacritics from text (e.g. Ç → C, É → E) + */ + stripDiacritics: function(text) { + // NFD decomposes, then remove combining marks + var decomposed = text.normalize('NFD'); + var out = ''; + for (var i = 0; i < decomposed.length; i++) { + // Combining Diacritical Marks block: U+0300–U+036F + var cp = decomposed.charCodeAt(i); + if (cp < 0x0300 || cp > 0x036F) { + out += decomposed[i]; + } + } + return out; + }, + + func: function(text, options) { + var layout = (options && options.layout) || 'horizontal'; + text = this.stripDiacritics(text).toUpperCase(); + + if (layout === 'vertical') { + var words = text.split(/\s+/); + var wordBlocks = []; + for (var w = 0; w < words.length; w++) { + var chars = []; + for (var c = 0; c < words[w].length; c++) { + var sign = this.librasMap[words[w][c]]; + if (sign) chars.push(sign.join('\n')); + } + wordBlocks.push(chars.join('\n\n')); + } + return wordBlocks.join('\n\n\n'); + } + + // Horizontal layout + var SPACE_TOKEN = this.NBSP + this.NBSP; + var signs = []; + for (var i = 0; i < text.length; i++) { + var ch = text[i]; + if (ch === ' ') { + signs.push([SPACE_TOKEN]); + } else { + var sign = this.librasMap[ch]; + if (sign) { + signs.push(sign.slice()); + } else { + signs.push([ch]); + } + } + } + + var maxH = 1; + for (var s = 0; s < signs.length; s++) { + if (signs[s].length > maxH) maxH = signs[s].length; + } + + var lanes = []; + for (var r = 0; r < maxH; r++) lanes.push(''); + + for (var s = 0; s < signs.length; s++) { + var padCount = maxH - signs[s].length; + var padded = []; + for (var p = 0; p < padCount; p++) padded.push(this.NBSP); + for (var p = 0; p < signs[s].length; p++) padded.push(signs[s][p]); + for (var r = 0; r < maxH; r++) { + lanes[r] += padded[r]; + } + } + return lanes.join('\n'); + }, + + preview: function(text) { + if (!text) return '[LIBRAS SignWriting]'; + return this.func(text.slice(0, 5)); + } +}); diff --git a/src/transformers/signwriting/morse-blink.js b/src/transformers/signwriting/morse-blink.js new file mode 100644 index 0000000..8a1436f --- /dev/null +++ b/src/transformers/signwriting/morse-blink.js @@ -0,0 +1,48 @@ +// Morse Blink SignWriting transform +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Morse Blink', + priority: 0, + canDecode: false, + description: 'Encodes text as Morse code using SignWriting eye blink symbols (dot = brief close, dash = tight press).', + + DOT: '𝧿𝨕', // Eye closes briefly + DASH: '𝧿𝨖', // Eye pressed tightly + GAP: '𝧿𝨚', // Eye open (delimiter) + + morseMap: { + 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', + 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', + 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', + 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', + 'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', + '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', + '9': '----.', '0': '-----', ' ': '/' + }, + + func: function(text) { + var upper = text.toUpperCase(); + var lines = []; + for (var i = 0; i < upper.length; i++) { + var ch = upper[i]; + var code = this.morseMap[ch]; + if (!code) continue; + if (code === '/') { + lines.push(''); + continue; + } + var symbols = []; + for (var j = 0; j < code.length; j++) { + symbols.push(code[j] === '.' ? this.DOT : this.DASH); + } + lines.push(symbols.join(' ') + ' ' + this.GAP); + } + return lines.join('\n'); + }, + + preview: function(text) { + if (!text) return '[Morse Blink]'; + return this.func(text.slice(0, 3)); + } +}); diff --git a/src/transformers/signwriting/tactile-signwriting.js b/src/transformers/signwriting/tactile-signwriting.js new file mode 100644 index 0000000..9a62808 --- /dev/null +++ b/src/transformers/signwriting/tactile-signwriting.js @@ -0,0 +1,60 @@ +// Deafblind Tactile SignWriting transform +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Tactile SignWriting', + priority: 0, + canDecode: false, + description: 'Deafblind tactile fingerspelling approximation in SignWriting (ISWA 2010). Two-hand layers per letter.', + + tactileMap: { + 'A': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝣷𝪝𝪩𝪆𝪞𝤅'], + 'B': ['𝡌𝪝𝪩𝡶𝪞', '𝡌𝪝𝪩𝪆𝪟𝤅'], + 'C': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝣜𝪝𝪩𝪆𝪟𝪧𝤎𝤻𝪩'], + 'D': ['𝡌𝪝𝪩𝣢𝪟𝪡', '𝠀𝪝𝪩𝪆𝪞𝪆𝪞𝪨𝤅'], + 'E': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝠀𝪝𝪩𝪆𝪞𝤅'], + 'F': ['𝡌𝪝𝪩𝠕𝪟𝪡', '𝠀𝪝𝪩𝪆𝪞𝪩𝤅'], + 'G': ['𝡌𝪝𝪩𝤃𝪞𝪡', '𝡌𝪝𝪩𝪆𝪟𝤅'], + 'H': ['𝡌𝪝𝪩𝡌𝪟𝪡', '𝡌𝪝𝪩𝤎𝥦𝪧'], + 'I': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝣆𝪝𝪧𝪆𝪞𝤅'], + 'J': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝡌𝪝𝪩𝣆𝪝𝪧𝪆𝪞𝤎𝥦𝪣𝪆𝪟𝥸𝪧'], + 'K': ['𝡌𝪝𝪩𝠆𝪝𝪡', '𝠀𝪝𝪩𝪆𝪞𝪩𝤅'], + 'L': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝡌𝪝𝪩𝪆𝪟𝤅'], + 'M': ['𝡌𝪝𝪩𝢌𝪟𝪡', '𝡌𝪝𝪩𝪆𝪟𝤅'], + 'N': ['𝡌𝪝𝪩𝠕𝪟𝪡', '𝡌𝪝𝪩𝪆𝪟𝤅'], + 'O': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝢮𝪝𝪩𝪆𝪞𝤅'], + 'P': ['𝡌𝪝𝪩𝣱𝪟𝪡', '𝠀𝪝𝪩𝪆𝪞𝪢𝤗'], + 'Q': ['𝡌𝪝𝪩𝠆𝪟𝪡', '𝣷𝪝𝪩𝤈𝩾𝪡'], + 'R': ['𝡌𝪝𝪩𝠆𝪞𝪡', '𝡌𝪝𝪩𝪆𝪟𝪫𝤅'], + 'S': ['𝡌𝪝𝪩𝠆𝪟𝪡', '𝢒𝪝𝪩𝤈𝩾𝪡'], + 'T': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝡌𝪝𝪩𝪆𝪟𝪫𝤅'], + 'U': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝢒𝪝𝪩𝪆𝪞𝤅'], + 'V': ['𝡌𝪝𝪩𝠎𝪟𝪡', '𝡌𝪝𝪩𝪆𝪟𝤅'], + 'W': ['𝡌𝪝𝪩𝡎𝪟𝪡', '𝡝𝪝𝪩𝪆𝪟𝪡𝤈'], + 'X': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝠀𝪝𝪩𝪆𝪞𝪩𝤅'], + 'Y': ['𝡌𝪝𝪩𝠀𝪟𝪡', '𝣷𝪝𝪩𝪆𝪟𝪬'], + 'Z': ['𝡌𝪝𝪩𝡚𝪞𝪡', '𝡌𝪝𝪩𝪆𝪟𝤅'] + }, + + func: function(text) { + var upper = text.toUpperCase(); + var blocks = []; + for (var i = 0; i < upper.length; i++) { + var ch = upper[i]; + if (ch === ' ') { + blocks.push('\u00A0\n\u00A0'); + continue; + } + var sign = this.tactileMap[ch]; + if (sign) { + blocks.push(sign[0] + '\n' + sign[1]); + } + } + return blocks.join('\n\n'); + }, + + preview: function(text) { + if (!text) return '[Tactile SignWriting]'; + return this.func(text.slice(0, 3)); + } +}); diff --git a/src/transformers/special/randomizer.js b/src/transformers/special/randomizer.js index b798f57..6a71f00 100644 --- a/src/transformers/special/randomizer.js +++ b/src/transformers/special/randomizer.js @@ -10,7 +10,7 @@ export default new BaseTransformer({ const suitable = [ 'base64', 'binary', 'hex', 'morse', 'rot13', 'caesar', 'atbash', 'rot5', 'upside_down', 'bubble', 'small_caps', 'fullwidth', 'leetspeak', 'superscript', 'subscript', - 'quenya', 'tengwar', 'klingon', 'dovahzul', 'elder_futhark', + 'quenya', 'tengwar', 'klingon', 'dovahzul', 'standard_galactic', 'elder_futhark', 'hieroglyphics', 'ogham', 'mathematical', 'cursive', 'medieval', 'monospace', 'greek', 'braille', 'alternating_case', 'reverse_words', 'title_case', 'sentence_case', 'camel_case', 'snake_case', 'kebab_case', 'random_case', diff --git a/src/transformers/symbol/alchemical.js b/src/transformers/symbol/alchemical.js new file mode 100644 index 0000000..dc02e91 --- /dev/null +++ b/src/transformers/symbol/alchemical.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Alchemical Symbols', + priority: 100, + category: 'symbol', + description: 'Classical alchemical symbol alphabet', + map: { + 'A': '🜂', + 'B': '🜃', + 'C': '🜄', + 'D': '🜅', + 'E': '🜆', + 'F': '🜇', + 'G': '🜈', + 'H': '🜉', + 'I': '🜊', + 'J': '🜋', + 'K': '🜌', + 'L': '🜍', + 'M': '🜎', + 'N': '🜏', + 'O': '🜐', + 'P': '🜑', + 'Q': '🜒', + 'R': '🜓', + 'S': '🜔', + 'T': '🜕', + 'U': '🜖', + 'V': '🜗', + 'W': '🜘', + 'X': '🜙', + 'Y': '🜚', + 'Z': '🜛' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[alchemical]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[🜂🜃🜄🜅🜆🜇🜈🜉]', 'u').test(text); + } +}); diff --git a/src/transformers/fantasy/aurebesh.js b/src/transformers/symbol/aurebesh.js similarity index 100% rename from src/transformers/fantasy/aurebesh.js rename to src/transformers/symbol/aurebesh.js diff --git a/src/transformers/symbol/babylonian-numerals.js b/src/transformers/symbol/babylonian-numerals.js new file mode 100644 index 0000000..fd1074a --- /dev/null +++ b/src/transformers/symbol/babylonian-numerals.js @@ -0,0 +1,70 @@ +// Babylonian numerals — A1Z26 letters to cuneiform sexagesimal digits (1–59) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const UNITS = ['', '\u{12415}', '\u{12416}', '\u{12417}', '\u{12418}', '\u{12419}', + '\u{1241A}', '\u{1241B}', '\u{1241C}', '\u{1241D}']; + const TENS = ['', '\u{1248B}', '\u{12499}', '\u{1240D}', '\u{1240F}', '\u{12410}']; + + function letterValue(ch) { + const code = ch.toUpperCase().charCodeAt(0); + if (code >= 65 && code <= 90) return code - 64; + return 0; + } + + function babylonianGlyph(n) { + if (n < 1 || n > 59) return ''; + const tens = Math.floor(n / 10); + const units = n % 10; + return (TENS[tens] || '') + (UNITS[units] || ''); + } + + const GLYPHS = []; + for (let n = 1; n <= 26; n++) { + GLYPHS.push({ glyph: babylonianGlyph(n), letter: String.fromCharCode(64 + n) }); + } + GLYPHS.sort(function(a, b) { return b.glyph.length - a.glyph.length; }); + + return new BaseTransformer({ + name: 'Babylonian Numerals', + priority: 100, + category: 'symbol', + description: 'A1Z26 (A=1 … Z=26) as Babylonian cuneiform numerals (Unicode sexagesimal signs)', + func: function(text) { + return [...text].map(function(ch) { + const n = letterValue(ch); + return n ? babylonianGlyph(n) : ch; + }).join(''); + }, + reverse: function(text) { + let out = ''; + let i = 0; + while (i < text.length) { + let hit = null; + for (let g = 0; g < GLYPHS.length; g++) { + const entry = GLYPHS[g]; + if (text.startsWith(entry.glyph, i)) { + hit = entry; + break; + } + } + if (hit) { + out += hit.letter; + i += hit.glyph.length; + } else { + const cp = text.codePointAt(i); + out += String.fromCodePoint(cp); + i += cp > 0xFFFF ? 2 : 1; + } + } + return out; + }, + preview: function(text) { + if (!text) return '[babylonian-numerals]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return /[\u{12415}-\u{1241D}\u{1248B}\u{12499}\u{1240D}-\u{12410}]/u.test(text); + } + }); +})(); diff --git a/src/transformers/technical/braille.js b/src/transformers/symbol/braille.js similarity index 100% rename from src/transformers/technical/braille.js rename to src/transformers/symbol/braille.js diff --git a/src/transformers/symbol/celestial.js b/src/transformers/symbol/celestial.js new file mode 100644 index 0000000..3ddfd64 --- /dev/null +++ b/src/transformers/symbol/celestial.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Celestial Alphabet', + priority: 100, + category: 'symbol', + description: 'Agrippa\'s celestial / angelic symbol alphabet', + map: { + 'A': '☉', + 'B': '☽', + 'C': '☿', + 'D': '♀', + 'E': '♂', + 'F': '♃', + 'G': '♄', + 'H': '♅', + 'I': '♆', + 'J': '♇', + 'K': '☊', + 'L': '☋', + 'M': '⚳', + 'N': '⚴', + 'O': '⚵', + 'P': '⚶', + 'Q': '⚷', + 'R': '⚸', + 'S': '⚹', + 'T': '⚺', + 'U': '⚻', + 'V': '⚼', + 'W': '⚽', + 'X': '⚾', + 'Y': '⛢', + 'Z': '⛣' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[celestial]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[☉☽☿♀♂♃♄♅♆♇☊☋]', 'u').test(text); + } +}); diff --git a/src/transformers/unicode/chemical.js b/src/transformers/symbol/chemical.js similarity index 100% rename from src/transformers/unicode/chemical.js rename to src/transformers/symbol/chemical.js diff --git a/src/transformers/symbol/daedric.js b/src/transformers/symbol/daedric.js new file mode 100644 index 0000000..f8293c6 --- /dev/null +++ b/src/transformers/symbol/daedric.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Daedric Alphabet', + priority: 100, + category: 'symbol', + description: 'Elder Scrolls inspired Daedric-style symbols', + map: { + 'A': 'ᚠ', + 'B': 'ᚡ', + 'C': 'ᚢ', + 'D': 'ᚣ', + 'E': 'ᚤ', + 'F': 'ᚥ', + 'G': 'ᚦ', + 'H': 'ᚧ', + 'I': 'ᚨ', + 'J': 'ᚩ', + 'K': 'ᚪ', + 'L': 'ᚫ', + 'M': 'ᚬ', + 'N': 'ᚭ', + 'O': 'ᚮ', + 'P': 'ᚯ', + 'Q': 'ᚰ', + 'R': 'ᚱ', + 'S': 'ᚲ', + 'T': 'ᚳ', + 'U': 'ᚴ', + 'V': 'ᚵ', + 'W': 'ᚶ', + 'X': 'ᚷ', + 'Y': 'ᚸ', + 'Z': 'ᚹ' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[daedric]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[ᚠᚡᚢᚣᚤᚥᚦᚧᚨᚩ]', 'u').test(text); + } +}); diff --git a/src/transformers/symbol/dancing-men.js b/src/transformers/symbol/dancing-men.js new file mode 100644 index 0000000..f5aa237 --- /dev/null +++ b/src/transformers/symbol/dancing-men.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Dancing Men Cipher', + priority: 100, + category: 'symbol', + description: 'Sherlock Holmes stick-figure cipher (Unicode approximations)', + map: { + 'A': '┣', + 'B': '┫', + 'C': '┳', + 'D': '┻', + 'E': '├', + 'F': '┤', + 'G': '┬', + 'H': '┴', + 'I': '╋', + 'J': '╞', + 'K': '╡', + 'L': '╤', + 'M': '╧', + 'N': '╥', + 'O': '╨', + 'P': '╪', + 'Q': '╫', + 'R': '╬', + 'S': '╭', + 'T': '╮', + 'U': '╯', + 'V': '╰', + 'W': '▸', + 'X': '◂', + 'Y': '▴', + 'Z': '▾' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[dancing-men]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[┣┫┳┻├┤┬┴╋╞╡╤╧]', 'u').test(text); + } +}); diff --git a/src/transformers/symbol/dominos-in-digits.js b/src/transformers/symbol/dominos-in-digits.js new file mode 100644 index 0000000..bf36306 --- /dev/null +++ b/src/transformers/symbol/dominos-in-digits.js @@ -0,0 +1,50 @@ +// Dominos in digits — map 0-9 to domino tile notation +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + // Unicode domino tiles U+1F019 (🀙) = 0-0, through 6-6 grid; use simplified [a|b] for 0-9 + const MAP = { + '0': '[0|0]', '1': '[0|1]', '2': '[1|1]', '3': '[1|2]', '4': '[2|2]', + '5': '[2|3]', '6': '[3|3]', '7': '[3|4]', '8': '[4|4]', '9': '[4|5]' + }; + const REV = {}; + for (const [d, v] of Object.entries(MAP)) REV[v] = d; + + return new BaseTransformer({ + name: 'Dominos in Digits', + priority: 78, + category: 'cipher', + configurableOptions: [ + { + id: 'separator', + label: 'Separator between dominoes', + type: 'select', + default: 'space', + options: [ + { value: 'space', label: 'Space' }, + { value: 'none', label: 'None' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const sep = options.separator === 'none' ? '' : ' '; + const digits = text.replace(/\D/g, ''); + if (!digits) return text; + return [...digits].map(d => MAP[d] || d).join(sep); + }, + reverse: function(text) { + const tokens = text.match(/\[\d\|\d\]/g) || []; + if (!tokens.length) return text; + return tokens.map(t => REV[t] || '').join(''); + }, + preview: function(text, options) { + if (!text) return '[domino]'; + const digits = text.replace(/\D/g, '').slice(0, 5); + return digits ? this.func(digits, options) : '[digits only]'; + }, + detector: function(text) { + return (text.match(/\[\d\|\d\]/g) || []).length >= 2; + } + }); +})(); diff --git a/src/transformers/fantasy/dovahzul.js b/src/transformers/symbol/dovahzul.js similarity index 100% rename from src/transformers/fantasy/dovahzul.js rename to src/transformers/symbol/dovahzul.js diff --git a/src/transformers/symbol/egyptian-numerals.js b/src/transformers/symbol/egyptian-numerals.js new file mode 100644 index 0000000..6ccb4f4 --- /dev/null +++ b/src/transformers/symbol/egyptian-numerals.js @@ -0,0 +1,85 @@ +// Egyptian hieroglyph numerals — A1Z26 letters to additive hieroglyph counts (1–26) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const ONE = '\u{133E4}'; + const TEN = '\u{13386}'; + const SEP = '\u2063'; + + function letterValue(ch) { + const code = ch.toUpperCase().charCodeAt(0); + if (code >= 65 && code <= 90) return code - 64; + return 0; + } + + function egyptianGlyph(n) { + if (n < 1 || n > 99) return ''; + const tens = Math.floor(n / 10); + const units = n % 10; + return TEN.repeat(tens) + ONE.repeat(units); + } + + function parseEgyptian(text) { + let n = 0; + for (const ch of text) { + if (ch === ONE) n += 1; + else if (ch === TEN) n += 10; + else break; + } + return n; + } + + return new BaseTransformer({ + name: 'Egyptian Numerals', + priority: 100, + category: 'symbol', + description: 'A1Z26 (A=1 … Z=26) as Egyptian hieroglyph stroke (1) and hobble (10) numerals', + func: function(text) { + let out = ''; + let prevGlyph = false; + for (const ch of text) { + const n = letterValue(ch); + if (n) { + if (prevGlyph) out += SEP; + out += egyptianGlyph(n); + prevGlyph = true; + } else { + out += ch; + prevGlyph = false; + } + } + return out; + }, + reverse: function(text) { + return text.split(SEP).map(function(token) { + if (!token) return ''; + let run = ''; + let out = ''; + for (const ch of token) { + if (ch === ONE || ch === TEN) { + run += ch; + } else { + if (run) { + const n = parseEgyptian(run); + out += (n >= 1 && n <= 26) ? String.fromCharCode(64 + n) : run; + run = ''; + } + out += ch; + } + } + if (run) { + const n = parseEgyptian(run); + out += (n >= 1 && n <= 26) ? String.fromCharCode(64 + n) : run; + } + return out; + }).join(''); + }, + preview: function(text) { + if (!text) return '[egyptian-numerals]'; + return this.func(text.slice(0, 4)) + (text.length > 4 ? '…' : ''); + }, + detector: function(text) { + return /[\u{133E4}\u{13386}]/u.test(text); + } + }); +})(); diff --git a/src/transformers/ancient/elder-futhark.js b/src/transformers/symbol/elder-futhark.js similarity index 100% rename from src/transformers/ancient/elder-futhark.js rename to src/transformers/symbol/elder-futhark.js diff --git a/src/transformers/symbol/enochian.js b/src/transformers/symbol/enochian.js new file mode 100644 index 0000000..0255842 --- /dev/null +++ b/src/transformers/symbol/enochian.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Enochian Alphabet', + priority: 100, + category: 'symbol', + description: 'Enochian angelic script (Unicode approximations)', + map: { + 'A': 'ᛂ', + 'B': 'ᛃ', + 'C': 'ᛄ', + 'D': 'ᛅ', + 'E': 'ᛆ', + 'F': 'ᛇ', + 'G': 'ᛈ', + 'H': 'ᛉ', + 'I': 'ᛊ', + 'J': 'ᛋ', + 'K': 'ᛌ', + 'L': 'ᛍ', + 'M': 'ᛎ', + 'N': 'ᛏ', + 'O': 'ᛐ', + 'P': 'ᛑ', + 'Q': 'ᛒ', + 'R': 'ᛓ', + 'S': 'ᛔ', + 'T': 'ᛕ', + 'U': 'ᛖ', + 'V': 'ᛗ', + 'W': 'ᛘ', + 'X': 'ᛙ', + 'Y': 'ᛚ', + 'Z': 'ᛛ' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[enochian]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[ᛂᛃᛄᛅᛆᛇᛈᛉᛊᛋ]', 'u').test(text); + } +}); diff --git a/src/transformers/symbol/eye-of-horus.js b/src/transformers/symbol/eye-of-horus.js new file mode 100644 index 0000000..f981abc --- /dev/null +++ b/src/transformers/symbol/eye-of-horus.js @@ -0,0 +1,51 @@ +// Eye of Horus (Wedjat) — A1Z26 mapped to the seven Wedjat fraction hieroglyphs +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const PARTS = [ + '\u{13080}', + '\u{13081}', + '\u{13082}', + '\u{13083}', + '\u{13084}', + '\u{13085}', + '\u{13086}' + ]; + + function letterValue(ch) { + const code = ch.toUpperCase().charCodeAt(0); + if (code >= 65 && code <= 90) return code - 64; + return 0; + } + + const REV = {}; + for (let n = 1; n <= 26; n++) { + const glyph = PARTS[(n - 1) % PARTS.length]; + if (!REV[glyph]) REV[glyph] = String.fromCharCode(64 + n); + } + + return new BaseTransformer({ + name: 'Eye of Horus (Wedjat)', + priority: 100, + category: 'symbol', + description: 'A1Z26 cycles through the seven Eye of Horus (Wedjat) fraction hieroglyphs', + func: function(text) { + return [...text].map(function(ch) { + const n = letterValue(ch); + return n ? PARTS[(n - 1) % PARTS.length] : ch; + }).join(''); + }, + reverse: function(text) { + return [...text].map(function(ch) { + return REV[ch] || ch; + }).join(''); + }, + preview: function(text) { + if (!text) return '[eye-of-horus]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return /[\u{13080}-\u{13086}]/u.test(text); + } + }); +})(); diff --git a/src/transformers/symbol/friderici-windows.js b/src/transformers/symbol/friderici-windows.js new file mode 100644 index 0000000..7f74709 --- /dev/null +++ b/src/transformers/symbol/friderici-windows.js @@ -0,0 +1,80 @@ +// Friderici window cipher — 4-pane window symbols per letter (1685 Fensterchiffre) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + // Pane order TL TR BL BR — B=black ▓, W=white □, D=dotted ◉ + // 24-letter Latin (J→I, V→U). Pane map from Friderici Cryptographia (1685). + const MAP = { + 'A': 'WWBW', 'B': 'BBWW', 'C': 'BWWB', 'D': 'WBBB', 'E': 'WBWW', 'F': 'BBBW', + 'G': 'WWBB', 'H': 'WWWB', 'I': 'WBBW', 'K': 'BBWB', 'L': 'BWDB', 'M': 'BWBW', + 'N': 'BWBB', 'O': 'BWWW', 'P': 'WBWB', 'Q': 'DWWB', 'R': 'BBBB', 'S': 'BWWD', + 'T': 'BBBD', 'U': 'WBBD', 'W': 'BBDB', 'X': 'WWWW', 'Y': 'BBWD', 'Z': 'BBDW' + }; + const REV = {}; + for (const [k, v] of Object.entries(MAP)) REV[v] = k; + + function normalizeLatin24(text) { + return text.toUpperCase().replace(/J/g, 'I').replace(/V/g, 'U'); + } + + function paneChar(code) { + if (code === 'B') return '\u2593'; + if (code === 'D') return '\u25C9'; + return '\u25A1'; + } + + function encodeWindow(code) { + return [...code].map(paneChar).join(''); + } + + function decodeWindow(symbol) { + let code = ''; + for (const ch of symbol) { + if (ch === '\u2593') code += 'B'; + else if (ch === '\u25C9') code += 'D'; + else code += 'W'; + } + return code.length === 4 ? REV[code] || '' : ''; + } + + return new BaseTransformer({ + name: 'Friderici Cipher (Windows)', + priority: 95, + category: 'symbol', + description: 'Friderici Fensterchiffre (1685): 4-pane windows (▓ □ ◉). J→I, V→U. Pane map from Cryptographia key.', + configurableOptions: [ + { + id: 'separator', + label: 'Separator between windows', + type: 'select', + default: 'space', + options: [ + { value: 'space', label: 'Space' }, + { value: 'none', label: 'None' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const sep = options.separator === 'none' ? '' : ' '; + return [...normalizeLatin24(text)].map(function(c) { + const code = MAP[c]; + return code ? encodeWindow(code) : c; + }).join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const parts = options.separator === 'none' + ? text.match(/[\u2593\u25C9\u25A1]{4}/g) || [] + : text.trim().split(/\s+/); + return parts.map(decodeWindow).join(''); + }, + preview: function(text, options) { + if (!text) return '[friderici]'; + return this.func(text.slice(0, 4), options); + }, + detector: function(text) { + return /([\u2593\u25C9\u25A1]{4}\s*){2,}/.test(text); + } + }); +})(); diff --git a/src/transformers/unicode/greek.js b/src/transformers/symbol/greek.js similarity index 100% rename from src/transformers/unicode/greek.js rename to src/transformers/symbol/greek.js diff --git a/src/transformers/ancient/hieroglyphics.js b/src/transformers/symbol/hieroglyphics.js similarity index 100% rename from src/transformers/ancient/hieroglyphics.js rename to src/transformers/symbol/hieroglyphics.js diff --git a/src/transformers/unicode/hiragana.js b/src/transformers/symbol/hiragana.js similarity index 100% rename from src/transformers/unicode/hiragana.js rename to src/transformers/symbol/hiragana.js diff --git a/src/transformers/unicode/katakana.js b/src/transformers/symbol/katakana.js similarity index 100% rename from src/transformers/unicode/katakana.js rename to src/transformers/symbol/katakana.js diff --git a/src/transformers/fantasy/klingon.js b/src/transformers/symbol/klingon.js similarity index 100% rename from src/transformers/fantasy/klingon.js rename to src/transformers/symbol/klingon.js diff --git a/src/transformers/symbol/malachim.js b/src/transformers/symbol/malachim.js new file mode 100644 index 0000000..292a497 --- /dev/null +++ b/src/transformers/symbol/malachim.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Malachim Alphabet', + priority: 100, + category: 'symbol', + description: 'Malachim / angel script symbol substitution', + map: { + 'A': '✁', + 'B': '✂', + 'C': '✃', + 'D': '✄', + 'E': '✆', + 'F': '✇', + 'G': '✈', + 'H': '✉', + 'I': '✊', + 'J': '✋', + 'K': '✌', + 'L': '✍', + 'M': '✎', + 'N': '✏', + 'O': '✐', + 'P': '✑', + 'Q': '✒', + 'R': '✓', + 'S': '✔', + 'T': '✕', + 'U': '✖', + 'V': '✗', + 'W': '✘', + 'X': '✙', + 'Y': '✚', + 'Z': '✛' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[malachim]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[✁✂✃✄✆✇✈✉✊✋✌✍✎✏]', 'u').test(text); + } +}); diff --git a/src/transformers/symbol/mary-stuart.js b/src/transformers/symbol/mary-stuart.js new file mode 100644 index 0000000..5fcf771 --- /dev/null +++ b/src/transformers/symbol/mary-stuart.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Mary Stuart Cipher', + priority: 100, + category: 'symbol', + description: 'Mary Queen of Scots nomenclator-style symbols', + map: { + 'A': '❶', + 'B': '❷', + 'C': '❸', + 'D': '❹', + 'E': '❺', + 'F': '❻', + 'G': '❼', + 'H': '❽', + 'I': '❾', + 'J': '❿', + 'K': '➀', + 'L': '➁', + 'M': '➂', + 'N': '➃', + 'O': '➄', + 'P': '➅', + 'Q': '➆', + 'R': '➇', + 'S': '➈', + 'T': '➉', + 'U': '➊', + 'V': '➋', + 'W': '➌', + 'X': '➍', + 'Y': '➎', + 'Z': '➏' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[mary-stuart]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[❶❷❸❹❺❻❼❽❾]', 'u').test(text); + } +}); diff --git a/src/transformers/symbol/mayan-numerals.js b/src/transformers/symbol/mayan-numerals.js new file mode 100644 index 0000000..8bf1561 --- /dev/null +++ b/src/transformers/symbol/mayan-numerals.js @@ -0,0 +1,94 @@ +// Mayan numerals — A1Z26 letters to Unicode Mayan numeral glyphs (positional for 20+) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const ZERO = '\u{124E0}'; + const SEP = '\u2063'; + + function letterValue(ch) { + const code = ch.toUpperCase().charCodeAt(0); + if (code >= 65 && code <= 90) return code - 64; + return 0; + } + + function mayanDigit(n) { + if (n < 0 || n > 19) return ''; + if (n === 0) return ZERO; + return String.fromCodePoint(0x124E0 + n); + } + + function mayanGlyph(n) { + if (n < 1 || n > 26) return ''; + if (n <= 19) return mayanDigit(n); + const hi = Math.floor(n / 20); + const lo = n % 20; + return mayanDigit(hi) + mayanDigit(lo); + } + + function codePointLen(text, index) { + const cp = text.codePointAt(index); + return cp > 0xFFFF ? 2 : 1; + } + + function decodeMayanToken(token) { + let out = ''; + let i = 0; + while (i < token.length) { + const cp = token.codePointAt(i); + if (cp >= 0x124E0 && cp <= 0x124F3) { + const len = codePointLen(token, i); + const cp2 = token.codePointAt(i + len); + if (cp2 >= 0x124E0 && cp2 <= 0x124F3) { + const pair = (cp - 0x124E0) * 20 + (cp2 - 0x124E0); + if (pair >= 20 && pair <= 26) { + out += String.fromCharCode(64 + pair); + i += len + codePointLen(token, i + len); + continue; + } + } + const single = cp - 0x124E0; + if (single >= 1 && single <= 19) { + out += String.fromCharCode(64 + single); + } + i += len; + } else { + out += String.fromCodePoint(cp); + i += cp > 0xFFFF ? 2 : 1; + } + } + return out; + } + + return new BaseTransformer({ + name: 'Mayan Numerals', + priority: 100, + category: 'symbol', + description: 'A1Z26 (A=1 … Z=26) as Unicode Mayan numerals (0–19 glyphs; 20+ uses positional pairs)', + func: function(text) { + let out = ''; + let prevMayan = false; + for (const ch of text) { + const n = letterValue(ch); + if (n) { + if (prevMayan) out += SEP; + out += mayanGlyph(n); + prevMayan = true; + } else { + out += ch; + prevMayan = false; + } + } + return out; + }, + reverse: function(text) { + return text.split(SEP).map(decodeMayanToken).join(''); + }, + preview: function(text) { + if (!text) return '[mayan-numerals]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return /[\u{124E0}-\u{124F3}]/u.test(text); + } + }); +})(); diff --git a/src/transformers/symbol/moon-alphabet.js b/src/transformers/symbol/moon-alphabet.js new file mode 100644 index 0000000..6adb276 --- /dev/null +++ b/src/transformers/symbol/moon-alphabet.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Moon Alphabet', + priority: 100, + category: 'symbol', + description: 'Moon phase / lunar symbol alphabet', + map: { + 'A': '☾', + 'B': '☽', + 'C': '☊', + 'D': '☋', + 'E': '⚸', + 'F': '⚹', + 'G': '⚺', + 'H': '⚻', + 'I': '⚼', + 'J': '⚽', + 'K': '⚾', + 'L': '⛢', + 'M': '⛣', + 'N': '⛤', + 'O': '⛥', + 'P': '⛦', + 'Q': '⛧', + 'R': '⛨', + 'S': '⛩', + 'T': '⛪', + 'U': '⛫', + 'V': '⛬', + 'W': '⛭', + 'X': '⛮', + 'Y': '⛯', + 'Z': '⛰' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[moon-alphabet]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[☾☽☊☋⚸⚹⚺⚻]', 'u').test(text); + } +}); diff --git a/src/transformers/ancient/ogham.js b/src/transformers/symbol/ogham.js similarity index 100% rename from src/transformers/ancient/ogham.js rename to src/transformers/symbol/ogham.js diff --git a/src/transformers/symbol/passing-the-river.js b/src/transformers/symbol/passing-the-river.js new file mode 100644 index 0000000..b8e1dc4 --- /dev/null +++ b/src/transformers/symbol/passing-the-river.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Passing the River Alphabet', + priority: 100, + category: 'symbol', + description: 'Golden Dawn Passing the River tarot script', + map: { + 'A': '♠', + 'B': '♣', + 'C': '♥', + 'D': '♦', + 'E': '♤', + 'F': '♧', + 'G': '♡', + 'H': '♢', + 'I': '♩', + 'J': '♪', + 'K': '♫', + 'L': '♬', + 'M': '♭', + 'N': '♮', + 'O': '♯', + 'P': '°', + 'Q': '±', + 'R': '×', + 'S': '÷', + 'T': '∓', + 'U': '∔', + 'V': '∕', + 'W': '∖', + 'X': '∗', + 'Y': '∘', + 'Z': '∙' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[passing-the-river]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[♠♣♥♦♤♧♡♢]', 'u').test(text); + } +}); diff --git a/src/transformers/symbol/periodic-table.js b/src/transformers/symbol/periodic-table.js new file mode 100644 index 0000000..bd46acf --- /dev/null +++ b/src/transformers/symbol/periodic-table.js @@ -0,0 +1,51 @@ +// Periodic table cipher — letters to element symbols +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const MAP = { + 'A': 'Ag', 'B': 'B', 'C': 'C', 'D': 'D', 'E': 'Es', 'F': 'F', 'G': 'Ge', + 'H': 'H', 'I': 'I', 'J': 'Jr', 'K': 'K', 'L': 'Li', 'M': 'Mg', 'N': 'N', + 'O': 'O', 'P': 'P', 'Q': 'Qu', 'R': 'Ra', 'S': 'S', 'T': 'Ti', 'U': 'U', + 'V': 'V', 'W': 'W', 'X': 'Xe', 'Y': 'Y', 'Z': 'Zn' + }; + const REV = {}; + for (const [k, v] of Object.entries(MAP)) REV[v] = k; + + return new BaseTransformer({ + name: 'Periodic Table Cipher', + priority: 86, + category: 'cipher', + configurableOptions: [ + { + id: 'separator', + label: 'Separator between symbols', + type: 'select', + default: 'space', + options: [ + { value: 'space', label: 'Space' }, + { value: 'none', label: 'None' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const sep = options.separator === 'none' ? '' : ' '; + return [...text.toUpperCase()].filter(c => /[A-Z]/.test(c)).map(c => MAP[c] || c).join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const tokens = options.separator === 'none' + ? text.match(/[A-Z][a-z]?/g) || [] + : text.trim().split(/\s+/); + return tokens.map(t => REV[t] || '').join(''); + }, + preview: function(text, options) { + if (!text) return '[periodic]'; + return this.func(text.slice(0, 8), options); + }, + detector: function(text) { + const tokens = text.trim().split(/\s+/); + return tokens.length >= 2 && tokens.every(t => REV[t] !== undefined); + } + }); +})(); diff --git a/src/transformers/cipher/pigpen.js b/src/transformers/symbol/pigpen.js similarity index 87% rename from src/transformers/cipher/pigpen.js rename to src/transformers/symbol/pigpen.js index 3fcc6ab..b08f124 100644 --- a/src/transformers/cipher/pigpen.js +++ b/src/transformers/symbol/pigpen.js @@ -6,8 +6,7 @@ export default new BaseTransformer({ priority: 60, category: 'cipher', // Pigpen cipher uses geometric symbols arranged in grids - // Standard Pigpen cipher mapping based on dCode.fr implementation (Original variant) - // Reference: https://www.dcode.fr/pigpen-cipher + // Standard Pigpen cipher mapping (original variant, Unicode symbol set) // Grid 1 (A-I): L-shapes and U-shapes in 3x3 grid positions // Grid 2 (J-R): Same shapes as A-I but with dots // Grid 3 (S-Z): Caret/X shapes (some with dots) @@ -38,7 +37,7 @@ export default new BaseTransformer({ return this.func(text.slice(0, 5)); }, detector: function(text) { - // Check if text contains Pigpen symbols (dCode.fr Unicode characters) + // Check if text contains Pigpen symbols const pigpenSymbols = /[ᒧ⊔ᒪ⊐☐⊏ᒣ⊓ᒥ⟓⨃ᒷ⪾🝕⪽ᒬ⩀⟔ᐯᐳᐸᐱ⟇ᑀᑅ⟑]/; return pigpenSymbols.test(text); } diff --git a/src/transformers/fantasy/quenya.js b/src/transformers/symbol/quenya.js similarity index 100% rename from src/transformers/fantasy/quenya.js rename to src/transformers/symbol/quenya.js diff --git a/src/transformers/ancient/roman-numerals.js b/src/transformers/symbol/roman-numerals.js similarity index 100% rename from src/transformers/ancient/roman-numerals.js rename to src/transformers/symbol/roman-numerals.js diff --git a/src/transformers/symbol/rosicrucian.js b/src/transformers/symbol/rosicrucian.js new file mode 100644 index 0000000..c2b5746 --- /dev/null +++ b/src/transformers/symbol/rosicrucian.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Rosicrucian Cipher', + priority: 100, + category: 'symbol', + description: 'Rosicrucian / Golden Dawn symbol alphabet', + map: { + 'A': '⛤', + 'B': '⛥', + 'C': '⛦', + 'D': '⛧', + 'E': '⛨', + 'F': '⛩', + 'G': '⛪', + 'H': '⛫', + 'I': '⛬', + 'J': '⛭', + 'K': '⛮', + 'L': '⛯', + 'M': '⛰', + 'N': '⛱', + 'O': '⛲', + 'P': '⛳', + 'Q': '⛴', + 'R': '⛵', + 'S': '⛶', + 'T': '⛷', + 'U': '⛸', + 'V': '⛹', + 'W': '⛺', + 'X': '⛻', + 'Y': '⛼', + 'Z': '⛽' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[rosicrucian]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[⛤⛥⛦⛧⛨⛩⛪⛫]', 'u').test(text); + } +}); diff --git a/src/transformers/symbol/seven-segment.js b/src/transformers/symbol/seven-segment.js new file mode 100644 index 0000000..7189a2c --- /dev/null +++ b/src/transformers/symbol/seven-segment.js @@ -0,0 +1,64 @@ +// 7-segment display encoding (segment masks a-g) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + // Segment order: abcdefg (1 = lit) + const MASK = { + '0': '1111110', '1': '0110000', '2': '1101101', '3': '1111001', '4': '0110011', + '5': '1011011', '6': '1011111', '7': '1110000', '8': '1111111', '9': '1111011', + 'A': '1110111', 'B': '0011111', 'C': '1001110', 'D': '0111101', 'E': '1001111', + 'F': '1000111', '-': '0000001', ' ': '0000000' + }; + const REV = {}; + for (const [ch, mask] of Object.entries(MASK)) { + if (!REV[mask]) REV[mask] = ch; + } + + function toMask(ch) { + const u = ch.toUpperCase(); + return MASK[u] || MASK[ch] || null; + } + + return new BaseTransformer({ + name: '7-Segment Display', + priority: 85, + category: 'electronics', + configurableOptions: [ + { + id: 'separator', + label: 'Separator between characters', + type: 'select', + default: 'space', + options: [ + { value: 'space', label: 'Space' }, + { value: 'pipe', label: 'Pipe (|)' }, + { value: 'none', label: 'None' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const sep = options.separator === 'pipe' ? '|' : (options.separator === 'none' ? '' : ' '); + return [...text].map(c => toMask(c) || '0000000').join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const parts = options.separator === 'pipe' + ? text.split('|') + : text.trim().split(/\s+/); + return parts.map(p => { + const mask = p.replace(/[^01]/g, ''); + if (mask.length !== 7) return ''; + return REV[mask] || '?'; + }).join(''); + }, + preview: function(text, options) { + if (!text) return '[7seg]'; + return this.func(text.slice(0, 4), options) + '...'; + }, + detector: function(text) { + const tokens = text.trim().split(/[\s|]+/); + return tokens.length >= 2 && tokens.every(t => /^[01]{7}$/.test(t)); + } + }); +})(); diff --git a/src/transformers/symbol/standard-galactic.js b/src/transformers/symbol/standard-galactic.js new file mode 100644 index 0000000..63e5f10 --- /dev/null +++ b/src/transformers/symbol/standard-galactic.js @@ -0,0 +1,46 @@ +// Standard Galactic Alphabet (Commander Keen / Minecraft Enchanting Table) +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Minecraft Enchanting Table', + priority: 100, + category: 'fantasy', + description: 'Standard Galactic Alphabet (Commander Keen / Minecraft enchanting table)', + map: { + 'A': 'ᔑ', 'B': 'ʖ', 'C': 'ᓵ', 'D': '↸', 'E': 'ᒷ', 'F': '⎓', 'G': '⊣', + 'H': '⍑', 'I': '╎', 'J': '⋮', 'K': 'ꖌ', 'L': 'ꖎ', 'M': 'ᒲ', 'N': 'リ', + 'O': '𝙹', 'P': '!¡', 'Q': 'ᑑ', 'R': '∷', 'S': 'ᓭ', 'T': 'ℸ\u0323', 'U': '⚍', + 'V': '⍊', 'W': '∴', 'X': '\u0307/', 'Y': '||', 'Z': '⨅' + }, + func: function(text) { + return [...text].map(c => { + const upperC = c.toUpperCase(); + return this.map[upperC] || c; + }).join(''); + }, + reverse: function(text) { + const revMap = new Map(); + for (const [letter, sgaChar] of Object.entries(this.map)) { + if (sgaChar && sgaChar !== letter) { + revMap.set(sgaChar, letter); + } + } + let result = text; + result = result.replace(/!¡/g, 'P'); + result = result.replace(/ℸ\u0323/g, 'T'); + result = result.replace(/\u0307\//g, 'X'); + result = result.replace(/\|\|/g, 'Y'); + let decoded = ''; + for (const ch of result) { + decoded += revMap.has(ch) ? revMap.get(ch) : ch; + } + return decoded; + }, + preview: function(text) { + if (!text) return '[sga]'; + return this.func(text.slice(0, 8)); + }, + detector: function(text) { + return /[ᔑʖᓵ↸ᒷ⎓⊣⍑╎⋮ꖌꖎᒲリ𝙹ᑑ∷ᓭ⚍⍊∴⨅]/.test(text); + } +}); diff --git a/src/transformers/symbol/templars.js b/src/transformers/symbol/templars.js new file mode 100644 index 0000000..22b314d --- /dev/null +++ b/src/transformers/symbol/templars.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Templars Cipher', + priority: 100, + category: 'symbol', + description: 'Templar / pigpen variant with dot markers', + map: { + 'A': '◧', + 'B': '◨', + 'C': '◩', + 'D': '◪', + 'E': '◫', + 'F': '◬', + 'G': '◭', + 'H': '◮', + 'I': '◯', + 'J': '◰', + 'K': '◱', + 'L': '◲', + 'M': '◳', + 'N': '◴', + 'O': '◵', + 'P': '◶', + 'Q': '◷', + 'R': '◸', + 'S': '◹', + 'T': '◺', + 'U': '◻', + 'V': '◼', + 'W': '◽', + 'X': '◾', + 'Y': '◿', + 'Z': '⬒' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[templars]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[◧◨◩◪◫◬◭◮◯]', 'u').test(text); + } +}); diff --git a/src/transformers/fantasy/tengwar.js b/src/transformers/symbol/tengwar.js similarity index 100% rename from src/transformers/fantasy/tengwar.js rename to src/transformers/symbol/tengwar.js diff --git a/src/transformers/symbol/theban.js b/src/transformers/symbol/theban.js new file mode 100644 index 0000000..07564ce --- /dev/null +++ b/src/transformers/symbol/theban.js @@ -0,0 +1,47 @@ +// @generated from data/alphabets — do not edit by hand +import BaseTransformer from '../BaseTransformer.js'; + +export default new BaseTransformer({ + name: 'Theban Alphabet', + priority: 100, + category: 'symbol', + description: 'Honoric / Theban witch alphabet (symbol substitution)', + map: { + 'A': '∀', + 'B': '∁', + 'C': '∂', + 'D': '∃', + 'E': '∄', + 'F': '∅', + 'G': '∆', + 'H': '∇', + 'I': '∈', + 'J': '∉', + 'K': '∊', + 'L': '∋', + 'M': '∌', + 'N': '∍', + 'O': '∎', + 'P': '∏', + 'Q': '∐', + 'R': '∑', + 'S': '−', + 'T': '∓', + 'U': '∔', + 'V': '∕', + 'W': '∖', + 'X': '∗', + 'Y': '∘', + 'Z': '∙' + }, + func: function(text) { + return [...text].map(c => this.map[c] || this.map[c.toUpperCase()] || c).join(''); + }, + preview: function(text) { + if (!text) return '[theban]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return new RegExp('[∀∁∂∃∄∅∆∇∈∉∊∋∌∍∎∏∐∑−∓∔∕∖∗∘∙√∛∜∝]', 'u').test(text); + } +}); diff --git a/src/transformers/unicode/wingdings.js b/src/transformers/symbol/wingdings.js similarity index 100% rename from src/transformers/unicode/wingdings.js rename to src/transformers/symbol/wingdings.js diff --git a/src/transformers/symbol/younger-futhark.js b/src/transformers/symbol/younger-futhark.js new file mode 100644 index 0000000..66b6851 --- /dev/null +++ b/src/transformers/symbol/younger-futhark.js @@ -0,0 +1,43 @@ +// Younger Futhark — 16-rune medieval alphabet (J→I, V→U; lossy Latin round-trip) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const MAP = { + A: '\u16BC', B: '\u16D2', C: '\u16B9', D: '\u16CF', E: '\u16C1', + F: '\u16A0', G: '\u16B9', H: '\u16BC', I: '\u16C1', J: '\u16C1', + K: '\u16B9', L: '\u16D2', M: '\u16D2', N: '\u16BE', O: '\u16A2', + P: '\u16D2', Q: '\u16B9', R: '\u16B1', S: '\u16C7', T: '\u16CF', + U: '\u16A6', V: '\u16A0', W: '\u16A6', X: '\u16C7', Y: '\u16E6', + Z: '\u16C7' + }; + + const REV = { + '\u16A0': 'F', '\u16A2': 'O', '\u16A6': 'U', '\u16B1': 'R', '\u16B9': 'K', + '\u16BC': 'H', '\u16BE': 'N', '\u16C1': 'I', '\u16C7': 'S', '\u16CF': 'T', + '\u16D2': 'L', '\u16E6': 'Y' + }; + + return new BaseTransformer({ + name: 'Younger Futhark', + priority: 100, + category: 'symbol', + description: 'Younger Futhark runes for Latin letters (16 runes; J→I, V→U; lossy reverse)', + func: function(text) { + return [...text.toUpperCase()].map(function(ch) { + return MAP[ch] || ch; + }).join(''); + }, + reverse: function(text) { + return [...text].map(function(ch) { + return REV[ch] || ch; + }).join(''); + }, + preview: function(text) { + if (!text) return '[younger-futhark]'; + return this.func(text.slice(0, 6)) + (text.length > 6 ? '…' : ''); + }, + detector: function(text) { + return /[\u16A0-\u16FF]/u.test(text); + } + }); +})(); diff --git a/src/transformers/technical/dtmf.js b/src/transformers/technical/dtmf.js new file mode 100644 index 0000000..7cdab0e --- /dev/null +++ b/src/transformers/technical/dtmf.js @@ -0,0 +1,66 @@ +// DTMF (Dual-Tone Multi-Frequency) telephone tone codes +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const DTMF = { + '1': '697+1209', '2': '697+1336', '3': '697+1477', + '4': '770+1209', '5': '770+1336', '6': '770+1477', + '7': '852+1209', '8': '852+1336', '9': '852+1477', + '*': '941+1209', '0': '941+1336', '#': '941+1477' + }; + const REV = Object.fromEntries(Object.entries(DTMF).map(([k, v]) => [v, k])); + + return new BaseTransformer({ + name: 'DTMF Code', + priority: 70, + category: 'technical', + configurableOptions: [ + { + id: 'format', + label: 'Output format', + type: 'select', + default: 'freq', + options: [ + { value: 'freq', label: '697+1209 (Hz pairs)' }, + { value: 'compact', label: '697-1209' } + ] + }, + { + id: 'spacing', + label: 'Space between tone codes', + type: 'boolean', + default: true + } + ], + func: function(text, options) { + options = options || {}; + const compact = options.format === 'compact'; + const spaced = options.spacing !== false; + const sep = compact ? '-' : '+'; + const parts = [...text].map(function(c) { + const code = DTMF[c]; + if (!code) { + return c; + } + return compact ? code.replace('+', sep) : code; + }); + return spaced ? parts.join(' ') : parts.join(''); + }, + reverse: function(text, options) { + options = options || {}; + const spaced = options.spacing !== false; + const tokens = spaced ? text.trim().split(/\s+/) : text.split(''); + return tokens.map(function(tok) { + const norm = tok.replace(/-/g, '+'); + return REV[norm] || tok; + }).join(''); + }, + preview: function(text, options) { + if (!text) return '[dtmf]'; + return this.func(text.slice(0, 4), options) + '...'; + }, + detector: function(text) { + return /\d{3}[+\-]\d{4}/.test(text); + } + }); +})(); diff --git a/src/transformers/technical/navajo-code.js b/src/transformers/technical/navajo-code.js new file mode 100644 index 0000000..ada13ec --- /dev/null +++ b/src/transformers/technical/navajo-code.js @@ -0,0 +1,62 @@ +// Navajo code — WWII code talker alphabet (letter → Navajo word) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const ALPHA = { + 'A': 'WOL-LA-CHEE', 'B': 'SHUSH', 'C': 'MOASI', 'D': 'BE', 'E': 'DZEH', + 'F': 'MA-E', 'G': 'KLIZZIE', 'H': 'LIN', 'I': 'TKIN', 'J': 'TKELE-CHO-G', + 'K': 'KLIZZIE-YAZZIE', 'L': 'DIBEH-YAZZIE', 'M': 'NA-AS-TSO-SI', 'N': 'NESH-CHEE', + 'O': 'NE-AHS-JAH', 'P': 'BI-SO-DIH', 'Q': 'CA-YEILTH', 'R': 'GAH', 'S': 'DIBEH', + 'T': 'THAN-ZIE', 'U': 'NO-DA-IH', 'V': 'A-KEH-DI-GLINI', 'W': 'GLOE-IH', + 'X': 'AL-NA-AS-DZOH', 'Y': 'TSAH-AS-ZIH', 'Z': 'BESH-DO-TLIZ' + }; + const REV = {}; + for (const [k, v] of Object.entries(ALPHA)) { + REV[v.toUpperCase()] = k; + } + + function normalizeToken(t) { + return t.toUpperCase().replace(/\s/g, '-'); + } + + return new BaseTransformer({ + name: 'Navajo Code', + priority: 88, + category: 'cipher', + configurableOptions: [ + { + id: 'separator', + label: 'Separator between words', + type: 'select', + default: 'space', + options: [ + { value: 'space', label: 'Space' }, + { value: 'newline', label: 'New line' } + ] + } + ], + func: function(text, options) { + options = options || {}; + const sep = options.separator === 'newline' ? '\n' : ' '; + return [...text].filter(c => /[A-Za-z]/.test(c)).map(c => { + return ALPHA[c.toUpperCase()] || c.toUpperCase(); + }).join(sep); + }, + reverse: function(text, options) { + options = options || {}; + const splitRe = options.separator === 'newline' ? /\n+/ : /\s+/; + return text.trim().split(splitRe).filter(Boolean).map(t => { + return REV[normalizeToken(t)] || ''; + }).join(''); + }, + preview: function(text, options) { + if (!text) return '[navajo]'; + return this.func(text.slice(0, 6), options); + }, + detector: function(text) { + const upper = text.toUpperCase(); + const hits = (upper.match(/WOL-LA-CHEE|DZEH|KLIZZIE|NE-AHS-JAH|DIBEH/g) || []).length; + return hits >= 2; + } + }); +})(); diff --git a/src/transformers/technical/phone-keypad.js b/src/transformers/technical/phone-keypad.js new file mode 100644 index 0000000..1daf6db --- /dev/null +++ b/src/transformers/technical/phone-keypad.js @@ -0,0 +1,51 @@ +// Phone keypad cipher (letters to dial digits, one press each) +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const KEYPAD = { + 'A': '2', 'B': '2', 'C': '2', + 'D': '3', 'E': '3', 'F': '3', + 'G': '4', 'H': '4', 'I': '4', + 'J': '5', 'K': '5', 'L': '5', + 'M': '6', 'N': '6', 'O': '6', + 'P': '7', 'Q': '7', 'R': '7', 'S': '7', + 'T': '8', 'U': '8', 'V': '8', + 'W': '9', 'X': '9', 'Y': '9', 'Z': '9', + '0': '0', '1': '1' + }; + const REV = {}; + for (const [letter, digit] of Object.entries(KEYPAD)) { + if (!REV[digit]) REV[digit] = letter; + } + + return new BaseTransformer({ + name: 'Phone Keypad Cipher', + priority: 70, + category: 'technical', + configurableOptions: [ + { + id: 'spacing', + label: 'Space between digits', + type: 'boolean', + default: true + } + ], + func: function(text, options) { + options = options || {}; + const digits = [...text.toUpperCase()].map(c => KEYPAD[c] || (/[0-9]/.test(c) ? c : '')).filter(Boolean); + return options.spacing ? digits.join(' ') : digits.join(''); + }, + reverse: function(text) { + const tokens = text.trim().split(/\s+/).join('').split(''); + return tokens.map(d => REV[d] || d).join(''); + }, + preview: function(text, options) { + if (!text) return '[keypad]'; + return this.func(text.slice(0, 6), options) + '...'; + }, + detector: function(text) { + const cleaned = text.replace(/\s/g, ''); + return cleaned.length >= 4 && /^[0-9]+$/.test(cleaned); + } + }); +})(); diff --git a/src/transformers/technical/t9.js b/src/transformers/technical/t9.js new file mode 100644 index 0000000..8ab2611 --- /dev/null +++ b/src/transformers/technical/t9.js @@ -0,0 +1,67 @@ +// T9 / multi-tap cellphone encoding +import BaseTransformer from '../BaseTransformer.js'; + +export default (function() { + const KEYPAD = { + '2': 'ABC', '3': 'DEF', '4': 'GHI', '5': 'JKL', + '6': 'MNO', '7': 'PQRS', '8': 'TUV', '9': 'WXYZ' + }; + + function letterToT9(ch) { + const u = ch.toUpperCase(); + if (u < 'A' || u > 'Z') return ch; + for (const [digit, letters] of Object.entries(KEYPAD)) { + const idx = letters.indexOf(u); + if (idx >= 0) return digit.repeat(idx + 1); + } + return ch; + } + + return new BaseTransformer({ + name: 'T9 Multi-tap', + priority: 70, + category: 'technical', + configurableOptions: [ + { + id: 'spacing', + label: 'Space between letters', + type: 'boolean', + default: true + } + ], + func: function(text, options) { + options = options || {}; + const parts = [...text].map(c => letterToT9(c)); + return options.spacing ? parts.join(' ') : parts.join(''); + }, + reverse: function(text) { + const cleaned = text.replace(/\s/g, ''); + let out = ''; + let i = 0; + while (i < cleaned.length) { + const d = cleaned[i]; + if (!KEYPAD[d]) { + out += d; + i++; + continue; + } + let count = 0; + while (i < cleaned.length && cleaned[i] === d) { + count++; + i++; + } + const letters = KEYPAD[d]; + out += letters[(count - 1) % letters.length]; + } + return out; + }, + preview: function(text, options) { + if (!text) return '[t9]'; + return this.func(text.slice(0, 5), options) + '...'; + }, + detector: function(text) { + const cleaned = text.replace(/\s/g, ''); + return cleaned.length >= 4 && /^[2-9]+$/.test(cleaned); + } + }); +})(); diff --git a/src/transformers/unicode/bubble.js b/src/transformers/unicode/bubble.js index 6ccda6e..6410fa3 100644 --- a/src/transformers/unicode/bubble.js +++ b/src/transformers/unicode/bubble.js @@ -1,25 +1,35 @@ -// bubble transform +// bubble transform — circled letters (incl. lowercase) and circled digits import BaseTransformer from '../BaseTransformer.js'; export default new BaseTransformer({ - - name: 'Bubble', + name: 'Bubble', priority: 85, + category: 'unicode', map: { - 'a': 'ⓐ', 'b': 'ⓑ', 'c': 'ⓒ', 'd': 'ⓓ', 'e': 'ⓔ', 'f': 'ⓕ', 'g': 'ⓖ', 'h': 'ⓗ', 'i': 'ⓘ', - 'j': 'ⓙ', 'k': 'ⓚ', 'l': 'ⓛ', 'm': 'ⓜ', 'n': 'ⓝ', 'o': 'ⓞ', 'p': 'ⓟ', 'q': 'ⓠ', 'r': 'ⓡ', - 's': 'ⓢ', 't': 'ⓣ', 'u': 'ⓤ', 'v': 'ⓥ', 'w': 'ⓦ', 'x': 'ⓧ', 'y': 'ⓨ', 'z': 'ⓩ', - 'A': 'Ⓐ', 'B': 'Ⓑ', 'C': 'Ⓒ', 'D': 'Ⓓ', 'E': 'Ⓔ', 'F': 'Ⓕ', 'G': 'Ⓖ', 'H': 'Ⓗ', 'I': 'Ⓘ', - 'J': 'Ⓙ', 'K': 'Ⓚ', 'L': 'Ⓛ', 'M': 'Ⓜ', 'N': 'Ⓝ', 'O': 'Ⓞ', 'P': 'Ⓟ', 'Q': 'Ⓠ', 'R': 'Ⓡ', - 'S': 'Ⓢ', 'T': 'Ⓣ', 'U': 'Ⓤ', 'V': 'Ⓥ', 'W': 'Ⓦ', 'X': 'Ⓧ', 'Y': 'Ⓨ', 'Z': 'Ⓩ' - }, - func: function(text) { - return [...text].map(c => this.map[c] || c).join(''); - }, - // Detector: Check for bubble (enclosed alphanumerics) characters - detector: function(text) { - // Enclosed alphanumerics (U+24B6-U+24EA for circled letters) - return /[ⓐ-ⓩⒶ-Ⓩ]/.test(text); + 'a': 'ⓐ', 'b': 'ⓑ', 'c': 'ⓒ', 'd': 'ⓓ', 'e': 'ⓔ', 'f': 'ⓕ', 'g': 'ⓖ', 'h': 'ⓗ', 'i': 'ⓘ', + 'j': 'ⓙ', 'k': 'ⓚ', 'l': 'ⓛ', 'm': 'ⓜ', 'n': 'ⓝ', 'o': 'ⓞ', 'p': 'ⓟ', 'q': 'ⓠ', 'r': 'ⓡ', + 's': 'ⓢ', 't': 'ⓣ', 'u': 'ⓤ', 'v': 'ⓥ', 'w': 'ⓦ', 'x': 'ⓧ', 'y': 'ⓨ', 'z': 'ⓩ', + 'A': 'Ⓐ', 'B': 'Ⓑ', 'C': 'Ⓒ', 'D': 'Ⓓ', 'E': 'Ⓔ', 'F': 'Ⓕ', 'G': 'Ⓖ', 'H': 'Ⓗ', 'I': 'Ⓘ', + 'J': 'Ⓙ', 'K': 'Ⓚ', 'L': 'Ⓛ', 'M': 'Ⓜ', 'N': 'Ⓝ', 'O': 'Ⓞ', 'P': 'Ⓟ', 'Q': 'Ⓠ', 'R': 'Ⓡ', + 'S': 'Ⓢ', 'T': 'Ⓣ', 'U': 'Ⓤ', 'V': 'Ⓥ', 'W': 'Ⓦ', 'X': 'Ⓧ', 'Y': 'Ⓨ', 'Z': 'Ⓩ', + '0': '⓪', '1': '①', '2': '②', '3': '③', '4': '④', + '5': '⑤', '6': '⑥', '7': '⑦', '8': '⑧', '9': '⑨' + }, + func: function(text) { + return [...text].map(c => this.map[c] || c).join(''); + }, + reverse: function(text) { + const rev = {}; + for (const [key, value] of Object.entries(this.map)) { + rev[value] = key; } - -}); \ No newline at end of file + return [...text].map(c => rev[c] || c).join(''); + }, + preview: function(text) { + if (!text) return '[bubble]'; + return this.func(text.slice(0, 5)); + }, + detector: function(text) { + return /[\u2460-\u2469\u24B6-\u24EA]/u.test(text); + } +}); diff --git a/src/transformers/unicode/upside-down.js b/src/transformers/unicode/upside-down.js index 719e8cd..4b1333e 100644 --- a/src/transformers/unicode/upside-down.js +++ b/src/transformers/unicode/upside-down.js @@ -17,6 +17,18 @@ export default new BaseTransformer({ '(': ')', ')': '(', '[': ']', ']': '[', '{': '}', '}': '{', '<': '>', '>': '<', '&': '⅋', '_': '‾' }, + configurableOptions: [ + { + id: 'mode', + label: 'Orientation', + type: 'select', + default: 'rotate180', + options: [ + { value: 'rotate180', label: '180° rotation (flip + reverse)' }, + { value: 'flipVertical', label: 'Vertical flip (flip only)' } + ] + } + ], // Create reverse map for decoding reverseMap: function() { const revMap = {}; @@ -25,16 +37,26 @@ export default new BaseTransformer({ } return revMap; }, - func: function(text) { - return [...text].map(c => this.map[c] || c).reverse().join(''); + func: function(text, options) { + options = options || {}; + const flipped = [...text].map(c => this.map[c] || c); + if (options.mode === 'flipVertical') { + return flipped.join(''); + } + return flipped.reverse().join(''); }, - preview: function(text) { + preview: function(text, options) { if (!text) return '[upside down]'; - return this.func(text.slice(0, 8)); + return this.func(text.slice(0, 8), options); }, - reverse: function(text) { + reverse: function(text, options) { + options = options || {}; const revMap = this.reverseMap(); - return [...text].map(c => revMap[c] || c).reverse().join(''); + const restored = [...text].map(c => revMap[c] || c); + if (options.mode === 'flipVertical') { + return restored.join(''); + } + return restored.reverse().join(''); } }); \ No newline at end of file diff --git a/src/transformers/format/javanais.js b/src/transformers/visual/javanais.js similarity index 100% rename from src/transformers/format/javanais.js rename to src/transformers/visual/javanais.js diff --git a/src/transformers/format/latin-gibberish.js b/src/transformers/visual/latin-gibberish.js similarity index 100% rename from src/transformers/format/latin-gibberish.js rename to src/transformers/visual/latin-gibberish.js diff --git a/src/transformers/format/leetspeak.js b/src/transformers/visual/leetspeak.js similarity index 100% rename from src/transformers/format/leetspeak.js rename to src/transformers/visual/leetspeak.js diff --git a/src/transformers/format/louchebem.js b/src/transformers/visual/louchebem.js similarity index 100% rename from src/transformers/format/louchebem.js rename to src/transformers/visual/louchebem.js diff --git a/src/transformers/format/pigLatin.js b/src/transformers/visual/pigLatin.js similarity index 100% rename from src/transformers/format/pigLatin.js rename to src/transformers/visual/pigLatin.js diff --git a/templates/codes.html b/templates/codes.html new file mode 100644 index 0000000..0b13fad --- /dev/null +++ b/templates/codes.html @@ -0,0 +1,152 @@ +
+
+
+
+
+ +

QR Codes & Barcodes

+
+

+ Generate QR codes and common barcodes, or scan/decode them from an uploaded image. + Supports QR Code, Code 128, EAN-13, and Code 39. +

+
+ +
+ + +
+ + +
+
+ + + + + + + +
+ +
+ +
+ +
+ +
+ +
{{ codesError }}
+ +
+
+ +
+
+ + +
+
+
+ + +
+
+ +
+ +
+ Scanning… +
+ +
+ Uploaded scan image +
+ +
{{ codesDecodeError }}
+ +
+
+ Format: {{ codesDecodeFormat }} +
+ +
+ + +
+
+
+
+
+
diff --git a/templates/decoder.html b/templates/decoder.html index c8193dc..8757731 100644 --- a/templates/decoder.html +++ b/templates/decoder.html @@ -3,12 +3,13 @@
- +