mirror of
https://github.com/elder-plinius/P4RS3LT0NGV3.git
synced 2026-07-21 03:21:05 +02:00
bug fixes, more cleanup, updated Docs/Readme
This commit is contained in:
+122
-102
@@ -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! 🎉
|
||||
|
||||
@@ -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 transformer’s `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 (33–126) by 18
|
||||
- **ROT47** - Rotate printable ASCII (33–126) by 47
|
||||
- **ROT5** - Rotate digits 0–9 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 (0–9, A–Z)
|
||||
- **Base45** - Base45 byte encoding
|
||||
- **Base58** - Bitcoin-style Base58 (no 0/O/I/l)
|
||||
- **Base62** - Base62 (0–9, A–Z, a–z)
|
||||
- **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 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
|
||||
- **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** - Left–right 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 Tags–style 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 project’s 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
@@ -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`
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {};
|
||||
},
|
||||
|
||||
Generated
+1054
-2
File diff suppressed because it is too large
Load Diff
+12
-2
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 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`)
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user