bug fixes, more cleanup, updated Docs/Readme

This commit is contained in:
Dustin Farley
2026-03-21 02:44:01 -07:00
parent 1ceed15aa0
commit 57102797de
15 changed files with 1803 additions and 342 deletions
+122 -102
View File
@@ -4,104 +4,124 @@ Thank you for your interest in contributing! This guide will help you understand
## 📁 Project Structure
Source layout (the runnable app is produced under **`dist/`** by `npm run build`; `dist/` is gitignored).
```
P4RS3LT0NGV3/
├── package.json
├── favicon.svg
├── index.template.html # HTML shell; tool *script* tags updated by inject-tool-scripts
├── css/
│ ├── style.css
│ └── notification.css
├── js/
│ ├── app.js # Main Vue.js application entry point
│ ├── core/ # Core feature modules (shared libraries)
│ │ ├── decoder.js # Universal decoder
│ │ ├── steganography.js # Steganography encoding/decoding
│ │ └── toolRegistry.js # Tool registry system
│ ├── bundles/ # Build-generated files (auto-created)
│ │ └── transforms-bundle.js # Generated bundle from src/transformers/
│ ├── config/ # Configuration constants
│ ├── app.js # Vue app entry
│ ├── config/
│ │ └── constants.js
│ ├── data/ # Generated or static data files (auto-created)
│ │ ├── emojiData.js # Generated from Unicode emoji data
│ │ ── emojiCompatibility.js
│ ├── utils/ # Utility functions
│ ├── core/ # Shared logic (not tab-specific UI)
│ │ ├── decoder.js # Universal decode engine
│ │ ── steganography.js # Emoji / invisible carriers
│ ├── toolRegistry.js # Registers tools, merges Vue data/methods
│ │ └── transformOptions.js
│ ├── data/ # Static data shipped with the app (see note below)
│ │ ├── anticlassifierPrompt.js
│ │ ├── emojiCompatibility.js
│ │ ├── endSequences.js
│ │ ├── glitchTokens.js
│ │ └── openrouterModels.js
│ ├── utils/
│ │ ├── clipboard.js
│ │ ├── emoji.js
│ │ ├── emoji.js # window.EmojiUtils (uses window.emojiData when present)
│ │ ├── escapeParser.js
│ │ ├── focus.js
│ │ ├── glitchTokens.js
│ │ ├── history.js
│ │ ├── notifications.js
│ │ └── theme.js
│ └── tools/ # Tool implementations (Vue integration)
│ ├── Tool.js # Base class
│ ├── TransformTool.js
│ └── tools/ # One *Tool.js per tab (extends Tool.js)
│ ├── Tool.js
│ ├── AntiClassifierTool.js
│ ├── BijectionTool.js
│ ├── DecodeTool.js
│ ├── EmojiTool.js
│ ├── TokenadeTool.js
│ ├── GibberishTool.js
│ ├── MutationTool.js
│ ├── TokenizerTool.js
│ ├── PromptCraftTool.js
│ ├── SplitterTool.js
── GibberishTool.js
── TokenadeTool.js
│ ├── TokenizerTool.js
│ ├── TransformTool.js
│ └── TranslateTool.js # hidden tab wiring; UI lives on Transform
├── src/
│ ├── emojiWordMap.js # Emoji keyword mappings (merged into emojiData.js)
│ └── transformers/ # Transformer modules (source - bundled at build time)
│ ├── emojiWordMap.js # Merged into generated emoji data at build time
│ └── transformers/ # Transformer sources → bundled to dist/js/bundles/
│ ├── BaseTransformer.js
│ ├── ancient/ # Elder Futhark, Hieroglyphics, Ogham, Roman Numerals
│ ├── case/ # Camel, Kebab, Snake, Title, etc.
│ ├── cipher/ # Caesar, ROT13, Vigenère, Atbash, etc.
│ ├── encoding/ # Base64, Hex, Binary, URL, etc.
│ ├── fantasy/ # Quenya, Tengwar, Klingon, Aurebesh, Dovahzul
│ ├── format/ # Leetspeak, Pig Latin, Reverse, etc.
│ ├── special/ # Randomizer
│ ├── technical/ # Morse, NATO, Braille, Brainfuck, etc.
│ ├── unicode/ # Upside-down, Fullwidth, Bubble, etc.
── visual/ # Disemvowel, Rovarspraket, Ubbi-dubbi, etc.
├── templates/ # HTML templates for tools (injected at build time)
│ ├── index.js # Generated by npm run build:index (gitignored)
│ ├── ancient/
│ ├── case/
│ ├── cipher/
│ ├── encoding/
│ ├── fantasy/
│ ├── format/
│ ├── special/
│ ├── technical/
── unicode/
│ └── visual/
├── templates/ # Injected into dist/index.html by inject-tool-templates
│ ├── anticlassifier.html
│ ├── bijection.html
│ ├── decoder.html
│ ├── steganography.html
│ ├── transforms.html
│ ├── tokenade.html
│ ├── fuzzer.html
│ ├── tokenizer.html
│ ├── gibberish.html
│ ├── promptcraft.html
│ ├── splitter.html
── gibberish.html
├── build/ # Build scripts
│ ├── build-index.js # Generates transformer index
│ ├── build-transforms.js # Bundles transformers into js/bundles/
── build-emoji-data.js # Generates emojiData.js from Unicode data
│ ├── inject-tool-scripts.js # Auto-discovers and registers tools
── inject-tool-templates.js # Injects templates into index.html
├── tests/ # Test suites
── steganography.html
│ ├── tokenade.html
│ ├── tokenizer.html
│ ├── transforms.html
── README.md
├── build/
── README.md
│ ├── build-index.js # Writes src/transformers/index.js
│ ├── build-transforms.js # Writes dist/js/bundles/transforms-bundle.js
│ ├── build-emoji-data.js # Writes dist/js/data/emojiData.js
│ ├── copy-static.js # Copies css/, js/, favicon → dist/
│ ├── 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
├── tests/
│ ├── test_universal.js
│ └── test_steganography_options.js
├── css/ # Stylesheets (edit *.css, then npm run build:css)
│ ├── style.css # Source (readable)
│ ├── style.min.css # Generated; linked from HTML
── notification.css
│ └── notification.min.css
── index.template.html # Base HTML template (templates injected here)
├── index.html # Generated file (created by build process)
└── docs/ # Documentation
├── docs/
│ ├── TOOL-SYSTEM.md
│ ├── TOOL_ARCHITECTURE.md
── UI-COMPONENTS.md
├── README.md
── CONTRIBUTING.md
dist/ # npm run build — gitignored
├── index.html # `npm run build:templates` → from index.template.html + templates/
├── css/ …
├── js/ …
│ ├── bundles/transforms-bundle.js
│ └── data/emojiData.js
```
**Generated / ignored paths (also listed in `.gitignore`):** `dist/`, `src/transformers/index.js`, legacy `js/bundles/transforms-bundle.js`, `js/data/emojiData.js`, root `index.html` if present. The build updates **`dist/index.html`** only; a **root** `index.html` is not produced by the current scripts.
## 🎯 Key Concepts
### Core vs Tools
- **`js/core/`** - Shared business logic and infrastructure
- These are **NOT** tool-specific
- Examples:
- `decoder.js` (used by DecodeTool + app.js)
- `steganography.js` (used by EmojiTool + decoder.js)
- `emojiLibrary.js` (used by EmojiTool)
- `toolRegistry.js` (ToolRegistry class - infrastructure for the tool system)
- **Source files** (`src/`) - Source files used by build process
- `emojiWordMap.js` - Emoji keyword mappings (merged into emojiData.js during build)
- `transformers/` - Transformer modules (bundled into transforms-bundle.js)
- **Generated files** (`js/bundles/`)
- `transforms-bundle.js` - Generated bundle from `src/transformers/` (created by `npm run build:transforms`)
- **`js/tools/`** - Vue.js integration layer for UI features
- Each tool represents a tab/feature in the UI
- Tools use core modules and utilities for functionality
- Example: `DecodeTool.js` uses `window.universalDecode` from `core/decoder.js`
- **`js/core/`** Shared business logic and infrastructure (not tab-specific)
- Examples: `decoder.js` (DecodeTool, decoder pipeline), `steganography.js` (EmojiTool, steg engine), `toolRegistry.js` (registers tools, merges Vue surface), `transformOptions.js` (shared transform UI helpers)
- **`js/utils/`** — Cross-cutting helpers (`clipboard`, `EmojiUtils` in `emoji.js`, notifications, theme, etc.)
- **`js/data/`** — Committed static payloads (models, prompts, glitch token data, end sequences, `emojiCompatibility.js`). **`emojiData.js`** is **not** edited here — it is **generated** to `dist/js/data/emojiData.js` by `npm run build:emoji`.
- **`src/`** — `emojiWordMap.js` feeds the emoji build; `transformers/` holds transformer modules
- **Generated bundle** — `npm run build:transforms` writes `dist/js/bundles/transforms-bundle.js` (a legacy `js/bundles/transforms-bundle.js` path may exist for older workflows and is gitignored)
- **`js/tools/`** — Vue integration: one `*Tool.js` per tab (plus `TranslateTool.js`, which is hidden and wired from the Transform tab)
- Example: `DecodeTool.js` uses the universal decode API from `core/decoder.js`
### Transformers vs Tools
@@ -142,7 +162,7 @@ Transformers are the core text transformation logic. See `src/transformers/READM
1. Create a new file in the appropriate category directory:
```bash
src/transformers/ciphers/my-cipher.js
src/transformers/cipher/my-cipher.js
```
2. Use the `BaseTransformer` class:
@@ -174,7 +194,7 @@ Transformers are the core text transformation logic. See `src/transformers/READM
```
4. Test it:
- Open `index.html` in a browser
- After `npm run build`, open **`dist/index.html`** in a browser (or use `npm start` → http://localhost:8080 if you prefer)
- Your transformer will appear in the Transform tab automatically
- Test encoding/decoding
- Test with the Universal Decoder
@@ -250,7 +270,7 @@ Tools represent UI features/tabs. Examples: Transform tab, Decoder tab, Emoji ta
```
4. Test it:
- Open `index.html`
- After `npm run build`, open **`dist/index.html`** (or `npm start` at http://localhost:8080)
- Your new tab should appear automatically
- Test all functionality
@@ -273,7 +293,7 @@ Utilities are shared helper functions used across the app. Currently, utility fu
};
```
2. Add script tag to `index.html` (before `app.js`):
2. Add a script tag to **`index.template.html`** (before `app.js`), then `npm run build:copy` (or `npm run build`) so it lands in **`dist/index.html`**:
```html
<script src="js/myUtility.js"></script>
```
@@ -289,7 +309,7 @@ Utilities are shared helper functions used across the app. Currently, utility fu
- Document with JSDoc comments
- Consider adding to existing modules if functionality is related
**Note:** The `js/utils/` directory contains utility functions: clipboard, escapeParser, focus, history, notifications, and theme. The `js/config/` directory contains configuration constants.
**Note:** Prefer `js/utils/` for shared helpers (clipboard, emoji, escapeParser, focus, glitchTokens, history, notifications, theme). Use `js/config/` for constants.
## 🧪 Testing
@@ -328,12 +348,11 @@ npm run test:steg # Steganography options tests
### File Organization
- **Core modules** (`js/core/`) - Shared business logic (e.g., `decoder.js`)
- **Root-level modules** (`js/`) - Feature libraries (e.g., `steganography.js`, `emojiLibrary.js`)
- **Tools** (`js/tools/`) - Vue.js UI integration layer
- **Templates** (`templates/`) - HTML templates for tools (injected at build time)
- **Transformers** (`src/transformers/`) - Text transformation logic
- **Bundles** (`js/bundles/`) - Build-generated files
- **Core modules** (`js/core/`) Shared logic (`decoder.js`, `steganography.js`, `toolRegistry.js`, `transformOptions.js`)
- **App entry** (`js/app.js`) — Vue bootstrap and shell behavior
- **Tools** (`js/tools/`) — Tab UI layer (`*Tool.js`)
- **Templates** (`templates/`) — Tool markup injected into `dist/index.html`
- **Transformers** (`src/transformers/`) Transform implementations; output is `dist/js/bundles/transforms-bundle.js`
### Naming Conventions
@@ -351,9 +370,9 @@ npm run build:templates
```
This:
1. Reads all `.html` files from `templates/` directory
2. Injects them into `index.html` at the `#tool-content-container` marker
3. Creates a single static HTML file for fast loading
1. Reads the ordered list of tool templates from `templates/` (see `build/inject-tool-templates.js`)
2. Injects them into **`dist/index.html`** at the `#tool-content-container` marker (from `index.template.html`)
3. Produces the static HTML file served from `dist/`
**When to run:**
- After editing any template in `templates/`
@@ -361,21 +380,21 @@ This:
### Build Script Details
- **Directory Creation**: Build scripts automatically create output directories (`js/bundles/`, `js/data/`) if they don't exist
- **Full Build**: Run `npm run build` to execute all build steps in order
- **Individual Builds**: Each build script can be run independently
- **Directory creation**: Scripts create `dist/` (and subfolders) as needed
- **Full build**: `npm run build` runs tools injection, copy, transformer index, transform bundle, emoji data, template injection (see `package.json` and `build/README.md`)
- **Individual builds**: Each `npm run build:*` step can be run on its own
**Note:** Transformers are loaded from `js/bundles/transforms-bundle.js` which may be pre-built or generated separately.
**Note:** The browser loads transforms from **`dist/js/bundles/transforms-bundle.js`** after a successful `npm run build:transforms` (and `npm run build:copy`).
## 🐛 Debugging
### Common Issues
1. **Template changes not showing**: Run `npm run build:templates` to inject templates into `index.html`
1. **Template changes not showing**: Run `npm run build:templates` to rebuild **`dist/index.html`**, then refresh (or run `npm start` after a full `npm run build`)
2. **Tool not showing**: Check that:
- Tool is registered in `js/core/toolRegistry.js`
- Script tag is in `index.html` before `app.js`
- Template file exists in `templates/` directory
- `npm run build:tools` ran so `toolRegistry.js` and `index.template.html` include the new tool
- Script tag order in **`index.template.html`** (loads before `app.js`)
- Template file exists in `templates/` and is listed in `build/inject-tool-templates.js` when adding a new tab
3. **Tests failing**: Check file paths use `path.join(projectRoot, '...')`
### Browser Console
@@ -383,23 +402,24 @@ This:
- Open browser DevTools (F12)
- Check console for errors
- Use `window.transforms` to see all transformers
- Use `window.steganography` to access steganography functions
- Use `window.emojiLibrary` to access emoji functions
- Use `window.steganography` for steganography helpers
- Use `window.emojiData` (after build) and `window.EmojiUtils` (`js/utils/emoji.js`) for emoji lists / splitting
## 📚 Documentation
- **Project README**: `README.md` - Overview and user guide
- **Templates**: `templates/README.md` - How to edit tool templates
- **Build Process**: `build/README.md` - Build script documentation
- **Tool System**: `docs/TOOL-SYSTEM.md` - Tool architecture details
- **Code Review**: `docs/CODE-REVIEW.md` - Architecture and code review guidelines
- **Project README**: `README.md` Overview and user guide
- **Templates**: `templates/README.md` — Editing tool templates
- **Build process**: `build/README.md` Build scripts
- **Tool system**: `docs/TOOL-SYSTEM.md` Templates, injection, UI vocabulary
- **Tool architecture**: `docs/TOOL_ARCHITECTURE.md`
- **UI components**: `docs/UI-COMPONENTS.md`
## ✅ Checklist Before Submitting
- [ ] Code follows existing style
- [ ] Tests pass (`npm test`)
- [ ] Templates built (`npm run build:templates`) if template files were edited
- [ ] Tested in browser (open `index.html`)
- [ ] Tested in browser (`npm run build`, then open `dist/index.html` or `npm start`)
- [ ] No console errors
- [ ] Documentation updated (if needed)
- [ ] JSDoc comments added (for new functions)
@@ -407,7 +427,7 @@ This:
## 🤝 Questions?
- Check existing code for examples
- Review `docs/CODE_REVIEW.md` for architecture details
- Review `docs/TOOL_ARCHITECTURE.md` and `docs/TOOL-SYSTEM.md` for architecture details
- Look at similar features to understand patterns
Thank you for contributing! 🎉
+295 -105
View File
@@ -1,90 +1,215 @@
# 🐍 P4RS3LT0NGV3 - Universal Text Translator
A powerful web-based text transformation and steganography tool that can encode/decode text in 79+ different languages, scripts, and formats. Think of it as a universal translator for ALL alphabets and writing systems!
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!
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).
## ✨ Features
### 🔐 **Steganography**
- **Emoji Steganography**: Hide messages within emojis using variation selectors
- **Invisible Text**: Encode text using Unicode Tags block (completely invisible)
- **Image Steganography**: Hide messages in images using LSB techniques
- **Emoji Steganography**: Hide messages within emojis using variation selectors (VS15/VS16 and related options; configurable bit order in Advanced Settings)
- **Invisible Text**: Encode text using Unicode Tags block (visually invisible)
- **Whitespace & zero-width steganography**: Available as transforms for research-style payloads (see transform categories)
### 🌍 **Text Transformations**
#### **Encoding & Decoding**
- **Base64** - Standard base64 encoding/decoding
- **Base32** - RFC 4648 compliant base32 encoding/decoding
- **Base58** - Bitcoin alphabet encoding/decoding
- **Base62** - 0-9A-Za-z compact encoding/decoding
- **Binary** - Convert text to/from binary representation
- **Hexadecimal** - Convert text to/from hex format
- **ASCII85** - Advanced ASCII85 encoding/decoding
- **URL Encode** - URL-safe encoding/decoding
- **HTML Entities** - HTML entity encoding/decoding
Categories match the Transform tab and the folders under `src/transformers/` (each transformers `name` as shown in the UI). Short descriptions explain what each transform does.
#### **Ciphers & Codes**
- **Caesar Cipher** - Classic shift cipher with configurable offset
- **ROT13** - Simple rotation cipher
- **ROT47** - Extended rotation cipher for ASCII 33-126
- **Morse Code** - International Morse code with proper spacing
#### **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
- **kebab-case** - kebab-case for slugs and identifiers
- **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
#### **Cipher**
- **ADFGX Cipher** - WWI ADFGVX-style polybius + column transposition
- **Affine Cipher** - Affine substitution (ax + b mod 26)
- **Atbash Cipher** - Reverse-alphabet substitution (A↔Z)
- **Autokey Cipher** - Key stream mixed with plaintext (autokey)
- **Baconian Cipher** - Five-letter groups hiding A/B (Bacon biliteral)
- **Beaufort Cipher** - Beaufort key-table polyalphabetic cipher
- **Bifid Cipher** - Polybius square + row/column interleaving
- **Caesar Cipher** - Classic alphabet shift (configurable)
- **Columnar Transposition** - Columnar transposition with a keyword
- **Four-Square Cipher** - Four 5×5 squares; digraph substitution
- **Gronsfeld Cipher** - Vigenère family with numeric key
- **Hill Cipher** - Matrix-based multi-letter substitution
- **Homophonic Cipher** - Multiple ciphertext symbols per plaintext letter
- **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
- **Rail Fence** - Zig-zag rail-fence transposition
- **ROT128** - UTF-16 code unit rotation by 128
- **ROT13** - Rotate Latin letters by 13 places
- **ROT18** - Rotate printable ASCII (33126) by 18
- **ROT47** - Rotate printable ASCII (33126) by 47
- **ROT5** - Rotate digits 09 by 5
- **ROT8000** - Plane-0 Unicode BMP rotation cipher
- **Scytale Cipher** - Wrap-around strip (scytale) transposition
- **Trifid Cipher** - Three Polybius cubes + trifid grouping
- **Two-Square Cipher** - Digraph cipher with two Playfair squares
- **Vigenère Cipher** - Polyalphabetic cipher with repeating keyword
- **XOR Cipher** - XOR with a repeating key
#### **Encoding**
- **ASCII85** - Ascii85 / Adobe-style base-85 encoding
- **Base122** - Binary → 122 printable ASCII characters
- **Base32** - RFC 4648 Base32
- **Base36** - Base36 (09, AZ)
- **Base45** - Base45 byte encoding
- **Base58** - Bitcoin-style Base58 (no 0/O/I/l)
- **Base62** - Base62 (09, AZ, az)
- **Base64** - Standard Base64
- **Base64 URL** - Base64url (URL-safe alphabet)
- **Base91** - basE91 / Ascii91 encoding
- **Baudot Code (ITA2)** - Five-bit telegraph / ITA2
- **Binary Coded Decimal** - Decimal digits as BCD nibbles
- **Binary** - Text bytes ↔ binary strings
- **EBCDIC** - EBCDIC byte encoding
- **Emoji Encoding** - Payload encoded with emoji
- **Gray Code** - Binary Gray code
- **Hexadecimal** - Hex encode/decode bytes
- **HTML Entities** - HTML entity escape / unescape
- **Invisible Text** - Unicode Tags / invisible carrier encoding
- **Quoted-Printable** - MIME quoted-printable
- **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
- **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
- **Mirror Digits** - Mirror digits 09 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
- **Remove Extra Spaces** - Collapse runs of spaces
- **Remove HTML Tags** - Strip HTML/XML tags
- **Remove Newlines** - Remove line breaks
- **Remove Numbers** - Remove digit characters
- **Remove Punctuation** - Remove punctuation
- **Remove Tabs** - Remove tab characters
- **Remove Zero Width** - Strip zero-width characters
- **Reverse Words** - Reverse order of words
- **Reverse Text** - Reverse character order
- **Shuffle Characters** - Shuffle characters (random order)
- **Shuffle Words** - Shuffle word order
- **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
- **Word Wrap** - Break long lines at spaces so each line fits a maximum width
- **Zero-Width Steganography** - Hide data with zero-width characters
#### **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
- **Maritime Signal Flags** - International maritime signal flags
- **Morse Code** - International Morse code
- **NATO Phonetic** - NATO phonetic alphabet
- **Vigenère Cipher** - Polyalphabetic cipher (default key "KEY")
- **Rail Fence (3 Rails)** - Zig-zag transposition cipher
- **Semaphore Flags** - Flag semaphore arm positions
- **Tap Code** - Polybius / tap / prison code
#### **Visual Transformations**
- **Upside Down** - Flip text upside down using Unicode characters
- **Full Width** - Convert to full-width Unicode characters
- **Small Caps** - Convert to small capital letters
- **Bubble Text** - Enclose letters in circles
- **Braille** - Convert to Braille patterns
- **Strikethrough** - Add strikethrough using combining characters
- **Underline** - Add underlines using combining characters
#### **Unicode**
- **Bold Italic** - Mathematical sans-serif bold italic
- **Bold** - Mathematical bold
- **Bubble** - Circled / “bubble” letters
- **Chemical Symbols** - Chemical element symbols
- **Circled** - Circled Unicode letters
- **Cursive** - Mathematical script / cursive
- **Cyrillic Stylized** - Latin → Cyrillic lookalike letters
- **Dashed Underline** - Combining dashed underline
- **Dotted Underline** - Combining dotted underline
- **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** - Leftright mirrored characters
- **Monospace** - Mathematical monospace
- **Negative Squared** - Negative circled / squared letters
- **Overline** - Overline combining marks
- **Parenthesized** - Parenthesized Latin letters
- **Regional Indicator Letters** - Regional-indicator flag letters
- **Small Caps** - Small capitals (Unicode)
- **Squared** - Squared / enclosed alphanumeric
- **Strikethrough** - Strikethrough combining characters
- **Subscript** - Unicode subscripts
- **Superscript** - Unicode superscripts
- **Underline** - Underline combining characters
- **Upside Down** - Upside-down Unicode letters
- **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)
#### **Unicode Styles**
- **Medieval** - Gothic/medieval style characters
- **Cursive** - Cursive/script style characters
- **Monospace** - Monospace mathematical characters
- **Double-Struck** - Mathematical double-struck characters
- **Greek Letters** - Greek alphabet characters
- **Wingdings** - Symbol font characters
- **Fraktur** - Mathematical Fraktur alphabet
- **Cyrillic Stylized** - Latin letters mapped to similar Cyrillic glyphs
- **Katakana** - Romaji to Katakana (approximate, reversible)
- **Hiragana** - Romaji to Hiragana (approximate, reversible)
- **Roman Numerals** - Numbers to Roman numerals (reversible)
#### **Visual**
- **Disemvowel** - Remove vowels (speech game)
- **Emoji Speak** - Emoji-heavy “speak” transform
- **Rövarspråket** - Swedish consonant-doubling game
- **Ubbi Dubbi** - Insert “ub” before vowel sounds
#### **Fantasy Languages** 🧙‍♂️
- **Quenya (Tolkien Elvish)** - High Elvish language from Lord of the Rings
- **Tengwar Script** - Elvish writing system
- **Klingon** - Star Trek Klingon language
- **Aurebesh (Star Wars)** - Galactic Basic alphabet
- **Dovahzul (Dragon)** - Dragon language from Skyrim
### 🛠️ **Tools** (tabs)
#### **Ancient Scripts** 🏛️
- **Elder Futhark** - Ancient Germanic runes
- **Hieroglyphics** - Egyptian hieroglyphic symbols
- **Ogham (Celtic)** - Celtic tree alphabet
- **Semaphore Flags** - Flag signaling system
Tabs appear in **UI order** below. **OpenRouter** (optional or required per tool) uses the key in **Advanced Settings** — see **OpenRouter API Key Setup** below.
#### **Technical Codes** ⚙️
- **Brainfuck** - Esoteric programming language
- **Mathematical Notation** - Mathematical script characters
- **Chemical Symbols** - Chemical element abbreviations
### 🔤 **Transform**
#### **Formatting**
- **Pig Latin** - Simple word transformation
- **Leetspeak** - 1337 speak with number substitutions
- **Vaporwave** - Aesthetic spacing
- **Zalgo** - Glitch text with combining marks
- **Mirror Text** - Reversed text
### 🔍 **Universal Decoder**
- **Smart Detection**: Automatically detects and decodes any supported format
- **Priority Matching**: Prioritizes decoding based on active transform
- **Fallback Methods**: Tries all available decoders if primary fails
- **Real-time Processing**: Instant decoding as you type
- **159 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.
- **Keyboard shortcut**: **T** (shown in the tab title).
### 🌐 **AI Translation** (via OpenRouter)
*Lives on the **Transform** tab — not a separate tab.*
- **20+ Languages**: Major world languages (Spanish, French, Chinese, Japanese, Korean, etc.)
- **Dead & Exotic Languages**: Latin, Sanskrit, Ancient Greek, Sumerian, Akkadian, Old English, and more
- **Custom Languages**: Add any language on-the-fly
@@ -92,23 +217,73 @@ A powerful web-based text transformation and steganography tool that can encode/
- **TranslateGemma Prompt Format**: Uses Google's optimized prompt template for high-quality translation
- **Auto-Fallback**: If a model is unavailable, automatically falls back to Gemma 3 27B
### 🪄 **PromptCraft** (AI Prompt Mutation)
- **9 Mutation Strategies**: Rephrase, Obfuscate, Role-Play Wrap, Multi-Language, Expand, Compress, Metaphor, Fragment, and Custom
- **48+ Models**: Frontier (Claude, GPT, Gemini, Grok), Reasoning (o3, o4, DeepSeek R1), Fast (Haiku, Mini), Code-specialized, Open Source (Llama, Qwen), and Search/Research models
- **Parallel Variants**: Generate 1-10 variants simultaneously with diverse temperature settings
- **Copy & Iterate**: Copy any variant or feed it back as input for iterative refinement
### 🔍 **Decoder** (Universal Decoder)
### 🛠️ **Available Tools**
- **Universal Decoder**: Auto-detect and decode any supported format
- **Text Transforms**: 79+ encoding, cipher, and transformation options
- **AI Translation**: Translate to 20+ languages via OpenRouter (built into Transforms tab)
- **PromptCraft**: AI-powered prompt mutation and crafting (dedicated tab)
- **Steganography**: Emoji and invisible text steganography
- **Tokenade Generator**: High-density token payload builder
- **Mutation Lab (Fuzzer)**: Generate diverse text mutations
- **Tokenizer Visualization**: Visualize tokenization for various engines
- **Message Splitter**: Split text into multiple copyable chunks
- **Gibberish Generator**: Create gibberish dictionaries and character removal variants
- **Smart detection**: Runs format detectors and decode paths for supported transforms.
- **Priority matching**: When a transform is active, decoding prefers that format first.
- **Fallback**: Tries other decoders if the primary guess fails.
- **Real-time**: Updates as you type.
- **Script & language hints**: Unicode script ranges and Latin word-marker heuristics for common languages.
- **AI translate to English** (optional, OpenRouter): When text looks foreign, optional one-shot translate to English.
- **Keyboard shortcut**: **D**.
### 😀 **Emoji** (Steganography)
- **Emoji carriers**: Hide data using variation selectors and supported emoji carriers; pick from the emoji grid.
- **Invisible text**: Switch to Unicode Tagsstyle invisible encoding where available.
- **Encode & decode**: Separate flows for hiding and recovering text.
- **Advanced Settings**: Bit order, VS choices, and other steganography tuning (sliders icon).
- **Keyboard shortcut**: **H** (shown in the tab title).
### 💣 **Tokenade**
- **Token bomb builder**: Depth, breadth, repeats, separators (e.g. ZWSP), variation selectors, noise.
- **Carriers & payloads**: Emoji carriers, text payloads, combining options.
- **Safety**: Warns when estimated output crosses a **danger** token threshold.
### 🧪 **Mutation Lab**
- **Batch mutations**: Generate many variants from one input (count configurable).
- **Seed**: Optional deterministic runs.
- **Toggles**: Random mix, zero-width, Unicode noise, Zalgo, whitespace, casing, encode/shuffle.
- **Random Mix**: Can chain the projects random transform mixer when enabled.
### 📊 **Tokenizer**
- **Engines**: UTF-8 **bytes**, **words**, or **GPT BPE** (**cl100k**, **o200k**, **p50k**, **r50k**) via `gpt-tokenizer` (CDN).
- **Visualization**: Token list with IDs/pieces; **character** and **word** counts.
- **Live updates**: Re-tokenizes when input or engine changes.
### ↔️ **Bijection**
- **Custom mappings**: Character-to-number (and related) “alphapr”-style maps for research payloads.
- **Controls**: Mapping type, budget, optional examples.
- **Output**: Generated mappings and payloads ready to copy.
### ✂️ **Splitter**
- **Split modes**: By chunk size, **word**, **sentence**, **line**, **regex pattern**, or **token** count (GPT tokenizer).
- **Transform chain**: Optionally run transforms on each piece.
- **Wrapping**: Start/end templates; `{n}` iterator marker; single-line vs multiline copy.
### 💬 **Gibberish**
- **Dictionary mode**: Seeded random gibberish over a configurable character set.
- **Removal mode**: Random or **specific** letter removal with batch **variations** and min/max strip lengths.
### 🪄 **PromptCraft** (via OpenRouter)
- **9 Mutation Strategies**: Rephrase, Obfuscate, Role-Play Wrap, Multi-Language, Expand, Compress, Metaphor, Fragment, and Custom
- **48+ Models**: Frontier (Claude, GPT, Gemini, Grok), Reasoning (o3, o4, DeepSeek R1), Fast (Haiku, Mini), Code-specialized, Open Source (Llama, Qwen), and Search/Research
models
- **Parallel Variants**: Generate 1-10 variants simultaneously with diverse temperature settings
- **Copy & iterate**: Copy any variant or feed it back as input for iterative refinement
### 🤖 **Anti-Classifier** (via OpenRouter)
- **Purpose**: Syntactic / paraphrase-style rewrites for research-style prompts.
- **Controls**: Model, temperature, max tokens.
- **Same key**: Uses the same OpenRouter API key as Translation and PromptCraft.
### 📱 **User Experience**
- **Dark/Light Theme**: Toggle between themes
@@ -117,9 +292,12 @@ A powerful web-based text transformation and steganography tool that can encode/
- **Keyboard Shortcuts**: Quick access to features
- **Responsive Design**: Works on all device sizes
- **Accessibility**: Screen reader friendly with proper ARIA labels
- **Side panels**: Glitch token browser (optional data), end-sequence / delimiter strings for research, and **Advanced Settings** (OpenRouter key, steganography tuning)
### 🔑 **OpenRouter API Key Setup**
Translation and PromptCraft features require an [OpenRouter](https://openrouter.ai/) API key:
**AI Translation**, **PromptCraft**, and **Anti-Classifier** require an [OpenRouter](https://openrouter.ai/) API key. **Decoder**s optional “translate to English” also uses OpenRouter when enabled.
1. Create an account at [openrouter.ai](https://openrouter.ai/)
2. Generate an API key (starts with `sk-or-...`)
3. In P4RS3LT0NGV3, click the **sliders icon** (top-right) to open **Advanced Settings**
@@ -130,39 +308,50 @@ Translation and PromptCraft features require an [OpenRouter](https://openrouter.
## 🚀 **Getting Started**
### **Quick Start (Built Version)**
1. Run the build process (see Development Setup below)
2. Open `dist/index.html` in any modern web browser
3. Type text in the input field
4. Choose a transformation from the categorized buttons
5. Click any transform button to apply and auto-copy
6. Use the Universal Decoder to decode any encoded text
### **Quick Start (local)**
1. `npm install` then `npm run build` (generates the **`dist/`** folder — it is **not** checked into git; you must build after clone or source changes)
2. Open **`dist/index.html`** in Chrome, Firefox, Safari, or another browser (double-click the file or use **File → Open**).
**Alternative — run as a local app (npm / npx):** From the project root, after `npm install` and `npm run build`, use **`npm start`** (runs [`serve`](https://github.com/vercel/serve) on port **8080**) or **`npx serve dist -l 8080`**. Then open **http://localhost:8080** — same UI, stable URL you can bookmark. **`npm run preview`** runs a full **`npm run build`** and then serves **`dist/`** in one step.
### **Development Setup**
```bash
# Install dependencies
npm install
# Build all assets (required before use):
# - Copies static files to dist/
# - Builds transform bundle from source files
# - Generates emoji data
# - Injects tool templates into dist/index.html
# Build all assets (required before use). Order matches package.json:
# build:tools → build:copy → build:index → build:transforms → build:emoji → build:templates
npm run build
# Or build individual components:
npm run build:tools # Auto-discover tools, inject script tags into dist/index.html
npm run build:copy # Copy static files to dist/
npm run build:transforms # Bundle all transformers to dist/js/bundles/
npm run build:index # Generate src/transformers/index.js (ES module index)
npm run build:transforms # Bundle all transformers to dist/js/bundles/transforms-bundle.js
npm run build:emoji # Generate emoji data to dist/js/data/
npm run build:templates # Inject tool HTML templates to dist/index.html
npm run build:index # Generate transformer index
npm run build:templates # Inject tool HTML templates into dist/index.html
# Run tests
npm test # Run universal decoder tests
npm run test:universal # Same as above
npm run test:steg # Test steganography options
npm run test:all # Universal + steganography tests
# Optional: serve dist/ over HTTP instead of opening dist/index.html directly
npm start # http://localhost:8080
npm run preview # npm run build, then serve dist/
```
### **Documentation & maintainer notes**
| Doc | Purpose |
|-----|---------|
| [CONTRIBUTING.md](CONTRIBUTING.md) | Adding transformers, tools, tests |
| [docs/TOOL-SYSTEM.md](docs/TOOL-SYSTEM.md) | Tool templates, build injection, shared UI classes |
| [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)).
## 🛠️ **Technical Details**
@@ -171,11 +360,12 @@ npm run test:steg # Test steganography options
- **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`)
- **Build Process**:
- Transformers are bundled from `src/transformers/` into `js/bundles/transforms-bundle.js`
- Tool templates are injected from `templates/` into `index.html`
- Emoji data is generated from Unicode specifications
- All build steps are required before the app can run
- `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`
- Tool templates are injected from `templates/` into `dist/index.html`
- Emoji data is generated to `dist/js/data/`
### **Browser Support**
- Chrome/Edge 80+
@@ -200,7 +390,7 @@ npm run test:steg # Test steganography options
- 🆕 **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
- 🆕 **79+ Transformations**: Added fantasy, ancient, and technical scripts
- 🆕 **159 Transformations**: Full catalog of encodings, ciphers, Unicode styles, fantasy and ancient scripts, 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
+23 -24
View File
@@ -1,39 +1,38 @@
# JavaScript Directory Structure
# JavaScript directory
## Core Modules (`js/core/`)
Source files here are copied to **`dist/js/`** by `npm run build:copy`. Generated artifacts (`dist/js/bundles/transforms-bundle.js`, `dist/js/data/emojiData.js`) are produced by other build steps.
- `decoder.js` - Universal decoder for automatic encoding detection
- `steganography.js` - Emoji and invisible text steganography
- `emojiLibrary.js` - Emoji search, filtering, and library functions
- `toolRegistry.js` - Tool registration and Vue data/method merging
## Core (`js/core/`)
- `decoder.js` — Universal decoder engine
- `steganography.js` — Emoji / invisible text steganography
- `toolRegistry.js` — Tool registration and Vue data/method merging
- `transformOptions.js` — Shared transform UI helpers
## Utilities (`js/utils/`)
- `clipboard.js` - `ClipboardUtils.copy()` - Clipboard API wrapper
- `focus.js` - `FocusUtils.focusWithoutScroll()`, `clearFocusAndSelection()`
- `history.js` - `HistoryUtils` - Copy history management
- `notifications.js` - `NotificationUtils` - Toast notifications
- `theme.js` - `ThemeUtils` - Dark/light theme management
- `escapeParser.js` - Escape sequence parsing
- `clipboard.js`, `focus.js`, `history.js`, `notifications.js`, `theme.js`
- `escapeParser.js` — Escape sequence parsing
- `emoji.js` `window.EmojiUtils` (uses `window.emojiData` when loaded)
- `glitchTokens.js` — Glitch token panel helpers
## Tools (`js/tools/`)
Tool classes extending `Tool` base class. Auto-discovered by `build/inject-tool-scripts.js`.
Classes extending `Tool`; auto-discovered by `build/inject-tool-scripts.js`.
## Data (`js/data/`)
- `emojiData.js` - Generated emoji data (build output)
- `emojiCompatibility.js` - Emoji compatibility mappings
Committed static data: `anticlassifierPrompt.js`, `emojiCompatibility.js`, `endSequences.js`, `glitchTokens.js`, `openrouterModels.js`. **`emojiData.js`** is generated into **`dist/js/data/`** by `npm run build:emoji`, not edited in-repo.
## Bundles (`js/bundles/`)
## Bundles
- `transforms-bundle.js` - Bundled transformer modules (build output)
Transformer bundle: **`dist/js/bundles/transforms-bundle.js`** (`npm run build:transforms`). A legacy `js/bundles/transforms-bundle.js` path may be gitignored.
## Load Order
## Typical load order (see `index.template.html`)
1. Data files (emojiData, emojiCompatibility)
2. Generated bundles (transforms-bundle)
3. Utilities (escapeParser, focus, notifications, history, clipboard, theme)
4. Core modules (steganography, decoder, emojiLibrary)
5. Tool system (Tool.js, *Tool.js files, toolRegistry)
6. Main app (app.js)
1. Data (`emojiData.js`, `emojiCompatibility.js`, …) — `emojiData` from build output in `dist/`
2. Bundles (`transforms-bundle.js`)
3. Utilities (including `emoji.js`)
4. Core (`steganography`, `decoder`, `transformOptions`, …)
5. Tools (`Tool.js`, `*Tool.js`, `toolRegistry.js`)
6. `app.js`
+32 -1
View File
@@ -39,10 +39,41 @@ function getMergedTransformOptions(transform) {
return Object.assign({}, merged, saved);
}
/**
* Resolve merged options for a transform by display name (same prefs as Transform tab).
* @param {string} transformName
* @param {Array<Object>} [vueTransforms] - Vue copy of transforms (may omit configurableOptions)
* @returns {Object}
*/
function getMergedTransformOptionsForName(transformName, vueTransforms) {
if (!transformName) {
return {};
}
let t = null;
if (Array.isArray(vueTransforms) && vueTransforms.length) {
t = vueTransforms.find(function(tr) {
return tr && tr.name === transformName;
});
}
if ((!t || !t.configurableOptions || !t.configurableOptions.length) && typeof window !== 'undefined' && window.transforms) {
const full = Object.values(window.transforms).find(function(tr) {
return tr && tr.name === transformName;
});
if (full) {
t = full;
}
}
if (!t || !t.configurableOptions || !t.configurableOptions.length) {
return {};
}
return getMergedTransformOptions(t);
}
if (typeof window !== 'undefined') {
window.getMergedTransformOptions = getMergedTransformOptions;
window.getMergedTransformOptionsForName = getMergedTransformOptionsForName;
}
if (typeof module !== 'undefined' && module.exports) {
module.exports = { getMergedTransformOptions };
module.exports = { getMergedTransformOptions, getMergedTransformOptionsForName };
}
+28 -3
View File
@@ -381,19 +381,44 @@ class SplitterTool extends Tool {
const activeTransforms = this.splitterTransforms.filter(t => t && t !== '');
if (activeTransforms.length > 0) {
// Apply each transformation in sequence
const getOpts = typeof window.getMergedTransformOptionsForName === 'function'
? function(name) {
return window.getMergedTransformOptionsForName(name, this.transforms);
}.bind(this)
: function() {
return {};
};
// Apply each transformation in sequence (same options as Transform tab)
for (const transformName of activeTransforms) {
const selectedTransform = this.transforms.find(t => t.name === transformName);
if (selectedTransform && selectedTransform.func) {
if (!selectedTransform || !selectedTransform.func) {
continue;
}
if (transformName === 'Random Mix') {
processedChunks = processedChunks.map(chunk => {
try {
return selectedTransform.func(chunk);
return window.transforms && window.transforms.randomizer
? window.transforms.randomizer.func(chunk)
: chunk;
} catch (e) {
console.error('Transform error:', e);
return chunk;
}
});
continue;
}
const opts = getOpts(transformName);
processedChunks = processedChunks.map(chunk => {
try {
return selectedTransform.func(chunk, opts);
} catch (e) {
console.error('Transform error:', e);
return chunk;
}
});
}
}
}
+2 -14
View File
@@ -239,20 +239,8 @@ class TransformTool extends Tool {
return false;
},
getMergedOptionsForTransform: function(transformName) {
let t = this.transforms.find(tr => tr.name === transformName);
if ((!t || !t.configurableOptions || !t.configurableOptions.length) && window.transforms) {
const full = Object.values(window.transforms).find(function(tr) {
return tr && tr.name === transformName;
});
if (full) {
t = full;
}
}
if (!t || !t.configurableOptions || !t.configurableOptions.length) {
return {};
}
if (typeof window.getMergedTransformOptions === 'function') {
return window.getMergedTransformOptions(t);
if (typeof window.getMergedTransformOptionsForName === 'function') {
return window.getMergedTransformOptionsForName(transformName, this.transforms);
}
return {};
},
+1054 -2
View File
File diff suppressed because it is too large Load Diff
+12 -2
View File
@@ -10,6 +10,8 @@
"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",
"start": "serve dist -l 8080",
"preview": "npm run build && serve dist -l 8080",
"test": "node tests/test_universal.js",
"test:universal": "node tests/test_universal.js",
"test:steg": "node tests/test_steganography_options.js",
@@ -20,7 +22,15 @@
"type": "git",
"url": "."
},
"keywords": ["encoder", "decoder", "steganography", "cipher"],
"keywords": [
"encoder",
"decoder",
"steganography",
"cipher"
],
"author": "",
"license": "MIT"
"license": "MIT",
"devDependencies": {
"serve": "^14.2.6"
}
}
+1
View File
@@ -134,6 +134,7 @@ Higher priority = more specific pattern (used for decoder result ordering):
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 transforms `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`)
## Testing
+59 -42
View File
@@ -3,49 +3,66 @@ import BaseTransformer from '../BaseTransformer.js';
export default new BaseTransformer({
name: 'Alternating Case',
priority: 150, // Higher priority to detect before Base64
func: function(text) {
let upper = true;
return [...text].map(c => {
if (/[a-zA-Z]/.test(c)) {
const out = upper ? c.toUpperCase() : c.toLowerCase();
upper = !upper;
return out;
}
return c;
}).join('');
},
preview: function(text) {
if (!text) return '[alt case]';
return this.func(text.slice(0, 6)) + (text.length > 6 ? '...' : '');
},
reverse: function(text) {
// Reverse by lowercasing (loses original case pattern)
return text.toLowerCase();
},
detector: function(text) {
const cleaned = text.trim();
if (cleaned.length < 4) return false;
// Check for alternating pattern in letters only
let lastWasUpper = null;
let alternations = 0;
let letterCount = 0;
for (const char of cleaned) {
if (/[a-zA-Z]/.test(char)) {
const isUpper = char === char.toUpperCase();
if (lastWasUpper !== null && isUpper !== lastWasUpper) {
alternations++;
}
lastWasUpper = isUpper;
letterCount++;
}
name: 'Alternating Case',
priority: 150, // Higher priority to detect before Base64
startWith: 'upper', // 'upper' | 'lower' — first alphabetic letter (fallback when options omitted)
configurableOptions: [
{
id: 'startWith',
label: 'First alphabetic letter',
type: 'select',
default: 'upper',
options: [
{ value: 'upper', label: 'Uppercase' },
{ value: 'lower', label: 'Lowercase' }
]
}
],
func: function(text, options) {
options = options || {};
const sw = options.startWith !== undefined && options.startWith !== ''
? options.startWith
: this.startWith;
let upper = sw === 'lower' ? false : true;
return [...text].map(c => {
if (/[a-zA-Z]/.test(c)) {
const out = upper ? c.toUpperCase() : c.toLowerCase();
upper = !upper;
return out;
}
return c;
}).join('');
},
preview: function(text, options) {
if (!text) return '[alt case]';
return this.func(text.slice(0, 6), options) + (text.length > 6 ? '...' : '');
},
reverse: function(text) {
// Reverse by lowercasing (loses original case pattern)
return text.toLowerCase();
},
detector: function(text) {
const cleaned = text.trim();
if (cleaned.length < 4) return false;
// Check for alternating pattern in letters only
let lastWasUpper = null;
let alternations = 0;
let letterCount = 0;
for (const char of cleaned) {
if (/[a-zA-Z]/.test(char)) {
const isUpper = char === char.toUpperCase();
if (lastWasUpper !== null && isUpper !== lastWasUpper) {
alternations++;
}
lastWasUpper = isUpper;
letterCount++;
}
// Must have at least 3 alternations and at least 70% alternation rate
return letterCount >= 4 && alternations >= 3 && alternations >= letterCount * 0.7;
}
// Must have at least 3 alternations and at least 70% alternation rate
return letterCount >= 4 && alternations >= 3 && alternations >= letterCount * 0.7;
}
});
+52 -22
View File
@@ -1,39 +1,69 @@
// bitwise NOT transform
// Encode: UTF-8 bytes → NOT each byte → lossless lowercase hex (invalid UTF-8 after NOT is common).
// Decode: hex → bytes → NOT each byte → UTF-8 decode (exact inverse of encode).
// Helpers must live inside the default export: build-transforms.js concatenates the file body
// into transforms[name] = … so multiple top-level declarations would assign the wrong value.
import BaseTransformer from '../BaseTransformer.js';
export default new BaseTransformer({
export default (function () {
function utf8BytesBitwiseNot(bytes) {
const out = new Uint8Array(bytes.length);
for (let i = 0; i < bytes.length; i++) {
out[i] = ~bytes[i] & 0xFF;
}
return out;
}
function bytesToHex(bytes) {
return Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join('');
}
function hexToBytes(hex) {
const cleaned = hex.replace(/\s+/g, '').replace(/0x/gi, '');
if (cleaned.length % 2 !== 0) {
return null;
}
if (!/^[0-9a-fA-F]*$/.test(cleaned)) {
return null;
}
const out = new Uint8Array(cleaned.length / 2);
for (let i = 0; i < out.length; i++) {
out[i] = parseInt(cleaned.slice(i * 2, i * 2 + 2), 16);
}
return out;
}
return new BaseTransformer({
name: 'Bitwise NOT',
priority: 100,
category: 'format',
func: function(text) {
// Invert all bits in each byte
const bytes = new TextEncoder().encode(text);
const result = new Uint8Array(bytes.length);
for (let i = 0; i < bytes.length; i++) {
result[i] = ~bytes[i] & 0xFF; // NOT operation, mask to 8 bits
}
try {
return new TextDecoder().decode(result);
} catch (e) {
// If decoding fails, return as hex
return Array.from(result).map(b => b.toString(16).padStart(2, '0')).join('');
}
const inverted = utf8BytesBitwiseNot(bytes);
return bytesToHex(inverted);
},
reverse: function(text) {
// Bitwise NOT is self-reciprocal (NOT NOT = original)
return this.func(text);
const inverted = hexToBytes(text);
if (!inverted) {
return '[invalid hex - paste the hex from encode; spaces allowed]';
}
const bytes = utf8BytesBitwiseNot(inverted);
try {
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
} catch (e) {
return '[invalid UTF-8 after inverse NOT]';
}
},
preview: function(text) {
if (!text) return '[bitwise-not]';
return this.func(text.slice(0, 5));
const h = this.func(text.slice(0, 5));
return h.length > 24 ? `${h.slice(0, 24)}` : h;
},
detector: function(text) {
// Bitwise NOT produces scrambled text, hard to detect
// Check for non-printable characters or unusual patterns
const hasNonPrintable = /[\x00-\x1F\x7F-\x9F]/.test(text);
return hasNonPrintable && text.length >= 5;
const t = text.trim().replace(/\s+/g, '');
if (t.length < 8 || t.length % 2 !== 0) return false;
return /^[0-9a-fA-F]+$/.test(t);
}
});
});
})();
+23 -6
View File
@@ -5,10 +5,27 @@ export default new BaseTransformer({
name: 'Indent',
priority: 100,
category: 'format',
spaces: 4, // Default indent spaces
func: function(text) {
const spaces = parseInt(this.spaces) || 4;
const indent = ' '.repeat(spaces);
spaces: 4, // Default indent spaces (fallback when options omitted)
configurableOptions: [
{
id: 'spaces',
label: 'Spaces per indent',
type: 'number',
default: 4,
min: 1,
max: 32,
step: 1
}
],
func: function(text, options) {
options = options || {};
let s = options.spaces !== undefined && options.spaces !== ''
? parseInt(options.spaces, 10)
: parseInt(this.spaces, 10) || 4;
if (Number.isNaN(s) || s < 1) {
s = 4;
}
const indent = ' '.repeat(s);
return text.split('\n').map(line => indent + line).join('\n');
},
@@ -16,9 +33,9 @@ export default new BaseTransformer({
// Remove leading spaces from each line
return text.split('\n').map(line => line.replace(/^\s+/, '')).join('\n');
},
preview: function(text) {
preview: function(text, options) {
if (!text) return '[indent]';
return this.func(text.slice(0, 20));
return this.func(text.slice(0, 20), options);
},
detector: function(text) {
// Check if all lines start with same amount of whitespace
+39 -6
View File
@@ -5,15 +5,48 @@ export default new BaseTransformer({
name: 'Line Numbers',
priority: 100,
category: 'format',
start: 1, // Starting line number
func: function(text) {
const start = parseInt(this.start) || 1;
start: 1, // Starting line number (fallback when options omitted)
gutterWidth: 4, // padStart width for the number column
configurableOptions: [
{
id: 'start',
label: 'Starting line number',
type: 'number',
default: 1,
min: 0,
max: 9999999,
step: 1
},
{
id: 'gutterWidth',
label: 'Number column width',
type: 'number',
default: 4,
min: 1,
max: 12,
step: 1
}
],
func: function(text, options) {
options = options || {};
let start = options.start !== undefined && options.start !== ''
? parseInt(options.start, 10)
: parseInt(this.start, 10) || 1;
if (Number.isNaN(start)) {
start = 1;
}
let gutterWidth = options.gutterWidth !== undefined && options.gutterWidth !== ''
? parseInt(options.gutterWidth, 10)
: parseInt(this.gutterWidth, 10) || 4;
if (Number.isNaN(gutterWidth) || gutterWidth < 1) {
gutterWidth = 4;
}
const lines = text.split('\n');
let result = '';
for (let i = 0; i < lines.length; i++) {
const lineNum = start + i;
result += lineNum.toString().padStart(4, ' ') + ': ' + lines[i] + '\n';
result += lineNum.toString().padStart(gutterWidth, ' ') + ': ' + lines[i] + '\n';
}
return result.trimEnd();
@@ -24,9 +57,9 @@ export default new BaseTransformer({
return line.replace(/^\s*\d+\s*:\s*/, '');
}).join('\n');
},
preview: function(text) {
preview: function(text, options) {
if (!text) return '[line-numbers]';
return this.func(text.slice(0, 30));
return this.func(text.slice(0, 30), options);
},
detector: function(text) {
// Check for line number pattern at start of lines
+37 -6
View File
@@ -5,11 +5,42 @@ export default new BaseTransformer({
name: 'Text Justify',
priority: 100,
category: 'format',
width: 80, // Default width
width: 80, // Default width (fallback when options omitted)
align: 'left', // left, right, center
func: function(text) {
const width = parseInt(this.width) || 80;
const align = this.align || 'left';
configurableOptions: [
{
id: 'width',
label: 'Line width (characters)',
type: 'number',
default: 80,
min: 8,
max: 200,
step: 1
},
{
id: 'align',
label: 'Alignment',
type: 'select',
default: 'left',
options: [
{ value: 'left', label: 'Left (pad on the right)' },
{ value: 'right', label: 'Right (pad on the left)' },
{ value: 'center', label: 'Center' }
]
}
],
func: function(text, options) {
options = options || {};
let w = options.width !== undefined && options.width !== ''
? parseInt(options.width, 10)
: parseInt(this.width, 10) || 80;
if (Number.isNaN(w) || w < 1) {
w = 80;
}
const width = w;
const align = options.align !== undefined && options.align !== ''
? options.align
: (this.align || 'left');
const lines = text.split('\n');
let result = '';
@@ -47,9 +78,9 @@ export default new BaseTransformer({
// Remove padding spaces
return text.split('\n').map(line => line.trim()).join('\n');
},
preview: function(text) {
preview: function(text, options) {
if (!text) return '[text-justify]';
return this.func(text.slice(0, 20));
return this.func(text.slice(0, 20), options);
},
detector: function(text) {
// Check for consistent line lengths with padding
+24 -7
View File
@@ -5,11 +5,28 @@ export default new BaseTransformer({
name: 'Word Wrap',
priority: 100,
category: 'format',
width: 80, // Default wrap width
func: function(text) {
const width = parseInt(this.width) || 80;
if (width < 1) return text;
width: 80, // Default wrap width (fallback when options omitted)
configurableOptions: [
{
id: 'width',
label: 'Maximum line width (characters)',
type: 'number',
default: 80,
min: 8,
max: 200,
step: 1
}
],
func: function(text, options) {
options = options || {};
let w = options.width !== undefined && options.width !== ''
? parseInt(options.width, 10)
: parseInt(this.width, 10) || 80;
if (Number.isNaN(w) || w < 1) {
w = 80;
}
const width = w;
const lines = text.split('\n');
let result = '';
@@ -45,9 +62,9 @@ export default new BaseTransformer({
// Remove line breaks (simple approach - may not be perfect)
return text.replace(/\n/g, ' ');
},
preview: function(text) {
preview: function(text, options) {
if (!text) return '[word-wrap]';
return this.func(text.slice(0, 50));
return this.func(text.slice(0, 50), options);
},
detector: function(text) {
// Check if text has consistent line lengths