mirror of
https://github.com/elder-plinius/P4RS3LT0NGV3.git
synced 2026-04-21 19:26:13 +02:00
454 lines
24 KiB
HTML
454 lines
24 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Parseltongue 2.0 - LLM Payload Crafter</title>
|
||
<link rel="icon" type="image/svg+xml" href="favicon.svg">
|
||
<link rel="stylesheet" href="css/style.css">
|
||
<link rel="stylesheet" href="css/notification.css">
|
||
<!-- Vue.js (Production Build) -->
|
||
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
|
||
<!-- Font Awesome for icons -->
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
||
</head>
|
||
<body>
|
||
<div id="app" class="container">
|
||
<header>
|
||
<div class="logo">
|
||
<h1>🐉️︎︎︎︎︎︎︎️︎︎︎️︎︎︎️︎️️︎️️︎︎︎︎︎︎︎️︎︎︎️︎︎︎️︎️️︎️️︎︎︎︎︎︎︎️︎︎︎️︎︎︎️︎️️︎️️︎︎︎︎︎︎︎️︎︎︎️︎︎︎️︎️️︎️︎︎️️️️︎︎︎️️️️️︎︎︎️︎︎︎️️️︎️︎︎️️️️︎️︎︎︎️︎︎︎️︎︎️️︎️︎️︎︎️️️️︎️︎︎︎️︎︎︎️︎︎︎️︎️︎︎️️️︎️︎︎️︎︎︎️︎️︎️︎︎️️️︎︎️︎︎︎︎︎️︎️︎︎︎︎️︎︎️︎︎️️︎︎︎️︎︎︎️︎️︎️︎︎︎️︎︎︎︎️︎️️️︎︎︎️︎️️️︎︎︎️︎️️️︎︎️︎︎️️︎︎︎️︎︎️️️️︎️︎️︎️️︎︎️︎︎︎️︎️︎︎️️️︎︎️︎️︎️︎︎︎︎︎︎️︎︎️️︎︎︎️︎︎️︎︎️︎️︎︎️️️︎︎️︎️️︎︎️︎️️️️️︎︎︎︎️️️️️︎︎︎️︎️️︎️️︎︎︎︎︎︎︎️︎︎︎️︎︎︎️︎️️︎️️︎︎︎︎︎︎︎️︎︎︎️︎︎︎️︎️️︎️️︎︎︎︎︎︎︎️︎︎︎️︎︎︎️︎️️︎️️︎︎︎︎︎︎︎️︎︎︎️︎︎︎️︎️️︎️️︎︎︎︎︎︎︎️︎︎︎️︎︎︎️︎️️︎️️︎︎︎︎︎︎︎️︎︎︎️︎ P4RS3LT0NGV3</h1>
|
||
</div>
|
||
<div class="actions">
|
||
<button
|
||
@click="toggleCopyHistory"
|
||
class="history-button"
|
||
title="Show copy history"
|
||
aria-label="Show copy history"
|
||
>
|
||
<i class="fas fa-history"></i>
|
||
</button>
|
||
<button
|
||
@click="toggleTheme"
|
||
@keyup.d="toggleTheme"
|
||
class="theme-button"
|
||
title="Toggle dark mode (D)"
|
||
aria-label="Toggle dark mode"
|
||
>
|
||
<i class="fas" :class="isDarkTheme ? 'fa-moon' : 'fa-sun'"></i>
|
||
</button>
|
||
<a
|
||
href="https://github.com/elder-plinius/P4RS3LT0NGV3"
|
||
target="_blank"
|
||
class="github-button"
|
||
title="View source on GitHub"
|
||
aria-label="View source code on GitHub"
|
||
>
|
||
<i class="fab fa-github"></i>
|
||
</a>
|
||
<button
|
||
@click="toggleUnicodePanel"
|
||
class="history-button"
|
||
title="Advanced Settings"
|
||
aria-label="Advanced Settings"
|
||
>
|
||
<i class="fas fa-sliders-h"></i>
|
||
</button>
|
||
<button
|
||
@click="toggleGlitchTokenPanel"
|
||
class="history-button"
|
||
title="Glitch Tokens"
|
||
aria-label="Glitch Tokens"
|
||
>
|
||
<i class="fas fa-bug"></i>
|
||
</button>
|
||
<button
|
||
@click="toggleEndSequencePanel"
|
||
class="history-button"
|
||
title="End sequences (delimiter strings)"
|
||
aria-label="End sequences"
|
||
>
|
||
<i class="fas fa-stop"></i>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="tabs">
|
||
<div class="tab-buttons" role="tablist" aria-label="Tools">
|
||
<!-- Dynamically generated tab buttons from tool registry -->
|
||
<button
|
||
v-for="tool in registeredTools"
|
||
v-if="!tool.hidden"
|
||
:key="tool.id"
|
||
:class="{ active: activeTab === tool.id }"
|
||
@click="switchToTab(tool.id)"
|
||
:title="tool.title"
|
||
role="tab"
|
||
:aria-selected="activeTab === tool.id"
|
||
>
|
||
<i :class="'fas ' + tool.icon"></i> {{ tool.name }}
|
||
</button>
|
||
</div>
|
||
|
||
<div class="tab-tool-select">
|
||
<label for="mobile-tool-select">Selected Tool</label>
|
||
<select
|
||
id="mobile-tool-select"
|
||
class="mobile-tool-dropdown"
|
||
:value="activeTab"
|
||
aria-label="Selected tool"
|
||
@change="switchToTab($event.target.value)"
|
||
>
|
||
<template v-for="tool in registeredTools">
|
||
<option
|
||
v-if="!tool.hidden"
|
||
:key="tool.id"
|
||
:value="tool.id"
|
||
>{{ tool.name }}</option>
|
||
</template>
|
||
</select>
|
||
</div>
|
||
|
||
<div id="tool-content-container">
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<!-- Copy History Panel -->
|
||
<div class="app-sidebar copy-history-panel" :class="{ 'active': showCopyHistory }">
|
||
<div class="app-sidebar-header copy-history-header">
|
||
<h3><i class="fas fa-history"></i> Copy History</h3>
|
||
<div class="header-actions">
|
||
<button
|
||
v-if="copyHistory.length > 0"
|
||
@click.stop="clearCopyHistory"
|
||
class="clear-history-button"
|
||
title="Clear all history"
|
||
>
|
||
<i class="fas fa-trash"></i>
|
||
</button>
|
||
<button class="close-button" @click="toggleCopyHistory" title="Close history">
|
||
<i class="fas fa-times"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="app-sidebar-body copy-history-content">
|
||
<div v-if="copyHistory.length === 0" class="no-history">
|
||
<p>No copy history yet. Use the app features to auto-copy content.</p>
|
||
</div>
|
||
<div v-else class="history-items">
|
||
<div v-for="(item, index) in copyHistory" :key="item.id || index" class="history-item">
|
||
<div class="history-item-header">
|
||
<span class="history-source">{{ item.source }}</span>
|
||
<span class="history-time">{{ formatHistoryTime(item.timestamp) }}</span>
|
||
</div>
|
||
<div class="history-content">
|
||
{{ item.content }}
|
||
</div>
|
||
<div class="history-actions">
|
||
<button class="copy-again-button" @click="copyToClipboard(item.content)" title="Copy again">
|
||
<i class="fas fa-copy"></i>
|
||
</button>
|
||
<button class="remove-history-button" @click.stop="removeFromCopyHistory(item.id)" title="Remove from history">
|
||
<i class="fas fa-times"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Glitch Tokens Panel -->
|
||
<div class="app-sidebar glitch-token-panel" :class="{ 'active': showGlitchTokenPanel }">
|
||
<div class="app-sidebar-header glitch-token-header">
|
||
<h3><i class="fas fa-bug"></i> Glitch Tokens</h3>
|
||
<div class="header-actions">
|
||
<button class="close-button" @click="toggleGlitchTokenPanel" title="Close glitch tokens">
|
||
<i class="fas fa-times"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="app-sidebar-body glitch-token-content">
|
||
<!-- Filter Section -->
|
||
<div class="glitch-token-filters">
|
||
<div class="filter-group">
|
||
<label>Behavior:</label>
|
||
<select v-model="glitchTokenBehavior" @change="filterGlitchTokens">
|
||
<option value="">All Behaviors</option>
|
||
<option value="UNSPEAKABLE">UNSPEAKABLE</option>
|
||
<option value="POLYSEMANTIC">POLYSEMANTIC</option>
|
||
<option value="GLITCHED_SPELLING">GLITCHED_SPELLING</option>
|
||
<option value="CONTEXT_CORRUPTOR">CONTEXT_CORRUPTOR</option>
|
||
<option value="LOOP_INDUCER">LOOP_INDUCER</option>
|
||
<option value="IDENTITY_DISRUPTOR">IDENTITY_DISRUPTOR</option>
|
||
<option value="FRAGMENT">FRAGMENT</option>
|
||
<option value="CONTROL_CHARACTER">CONTROL_CHARACTER</option>
|
||
<option value="SPECIAL_TOKEN">SPECIAL_TOKEN</option>
|
||
</select>
|
||
</div>
|
||
<div class="filter-group">
|
||
<label>Search:</label>
|
||
<input
|
||
type="text"
|
||
v-model="glitchTokenSearch"
|
||
@input="filterGlitchTokens"
|
||
placeholder="Search tokens..."
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tokens List -->
|
||
<div class="glitch-token-list">
|
||
<div v-if="filteredGlitchTokens.length === 0" class="no-tokens">
|
||
<p v-if="!glitchTokensLoaded">Loading glitch tokens...</p>
|
||
<div v-else class="empty-state">
|
||
<p><strong>No glitch tokens available.</strong></p>
|
||
<p>Glitch token data is not bundled by default. To use this feature:</p>
|
||
<ol style="text-align: left; margin: 10px 0; padding-left: 20px;">
|
||
<li>Obtain glitch token data (e.g., from AGGREGLITCH library)</li>
|
||
<li>Open browser console and run:<br/>
|
||
<code style="background: rgba(0,0,0,0.1); padding: 2px 4px; border-radius: 3px;">window.setGlitchTokensData(yourData)</code>
|
||
</li>
|
||
<li>Refresh the panel to see tokens</li>
|
||
</ol>
|
||
<p style="font-size: 0.9em; color: #666; margin-top: 10px;">
|
||
The data structure should match the AGGREGLITCH format with <code>glitch_tokens</code> containing categorized token arrays.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div v-else class="token-cards">
|
||
<div
|
||
v-for="(token, index) in filteredGlitchTokens"
|
||
:key="index"
|
||
class="token-card"
|
||
:class="'behavior-' + (token.behavior || '').toLowerCase()"
|
||
>
|
||
<div class="token-card-header">
|
||
<span class="token-text">{{ token.token || 'N/A' }}</span>
|
||
<button
|
||
class="copy-token-button"
|
||
@click="copyGlitchToken(token.token)"
|
||
title="Copy token"
|
||
>
|
||
<i class="fas fa-copy"></i>
|
||
</button>
|
||
</div>
|
||
<div class="token-card-body">
|
||
<div class="token-badge" :class="'badge-' + (token.behavior || '').toLowerCase()">
|
||
{{ token.behavior || 'Unknown' }}
|
||
</div>
|
||
<div v-if="token.token_id" class="token-id">
|
||
ID: {{ token.token_id }}
|
||
</div>
|
||
<div v-if="token.origin" class="token-origin">
|
||
Origin: {{ token.origin }}
|
||
</div>
|
||
<div v-if="token.observed_output" class="token-output">
|
||
Observed: {{ token.observed_output }}
|
||
</div>
|
||
<div v-if="token.note" class="token-note">
|
||
{{ token.note }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- End sequences sidebar (delimiter / stop strings for research) -->
|
||
<div class="app-sidebar end-sequence-panel" :class="{ active: showEndSequencePanel }">
|
||
<div class="app-sidebar-header end-sequence-header">
|
||
<h3><i class="fas fa-stop"></i> End sequences</h3>
|
||
<div class="header-actions">
|
||
<button class="close-button" type="button" @click="toggleEndSequencePanel" title="Close">
|
||
<i class="fas fa-times"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="app-sidebar-body end-sequence-content">
|
||
<p class="end-sequence-lede">
|
||
Strings sometimes used to probe delimiter and termination behavior. Copy into your payloads as needed for authorized testing.
|
||
</p>
|
||
<div
|
||
v-for="cat in endSequenceCategories"
|
||
:key="cat.title"
|
||
class="endsequence-category"
|
||
>
|
||
<h4>{{ cat.title }}</h4>
|
||
<div class="endsequence-items">
|
||
<button
|
||
v-for="(item, idx) in cat.items"
|
||
:key="cat.title + '-' + idx"
|
||
type="button"
|
||
class="endsequence-item"
|
||
@click="copyEndSequence(item.value)"
|
||
:title="'Copy to clipboard'"
|
||
:aria-label="'Copy ' + item.label"
|
||
>
|
||
<code class="endsequence-label">{{ item.label }}</code>
|
||
<span class="endsequence-copy-affordance" aria-hidden="true">
|
||
<i class="fas fa-copy"></i>
|
||
</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Advanced Settings Panel (inside app so Vue bindings work) -->
|
||
<div id="unicode-options-panel" class="app-sidebar unicode-options-panel">
|
||
<div class="app-sidebar-header unicode-panel-header">
|
||
<h3><i class="fas fa-sliders-h"></i> Advanced Settings</h3>
|
||
<button class="close-button" title="Close Advanced Settings"><i class="fas fa-times"></i></button>
|
||
</div>
|
||
<div class="app-sidebar-body unicode-panel-content">
|
||
<!-- OpenRouter API Key -->
|
||
<div class="settings-section api-key-section">
|
||
<h4><i class="fas fa-key"></i> OpenRouter API Key</h4>
|
||
<small class="settings-hint">Required for Translation, PromptCraft, and Anti-Classifier. Stored locally in your browser only.</small>
|
||
<div class="api-key-input-row">
|
||
<input
|
||
:type="showApiKey ? 'text' : 'password'"
|
||
v-model="openrouterApiKey"
|
||
placeholder="sk-or-..."
|
||
class="api-key-input"
|
||
autocomplete="off"
|
||
spellcheck="false"
|
||
/>
|
||
<button class="api-key-toggle" @click="showApiKey = !showApiKey" :title="showApiKey ? 'Hide key' : 'Show key'">
|
||
<i :class="showApiKey ? 'fas fa-eye-slash' : 'fas fa-eye'"></i>
|
||
</button>
|
||
</div>
|
||
<div class="api-key-actions">
|
||
<button class="api-key-save" @click="saveApiKey" :disabled="!openrouterApiKey">
|
||
<i class="fas fa-save"></i> Save Key
|
||
</button>
|
||
<button class="api-key-clear" @click="clearApiKey" v-if="openrouterApiKey">
|
||
<i class="fas fa-trash"></i> Clear
|
||
</button>
|
||
<small v-if="apiKeySaved" class="apply-status">Saved</small>
|
||
</div>
|
||
</div>
|
||
<hr class="settings-divider" />
|
||
<!-- Steganography Options -->
|
||
<h4><i class="fas fa-user-secret"></i> Steganography Options</h4>
|
||
</div>
|
||
<div class="app-sidebar-body unicode-panel-content options-grid steg-adv-panel">
|
||
<label>
|
||
Initial Presentation
|
||
<select class="steg-initial-presentation">
|
||
<option value="emoji">Emoji (VS16)</option>
|
||
<option value="text">Text (VS15)</option>
|
||
<option value="none">None</option>
|
||
</select>
|
||
</label>
|
||
<label>
|
||
Bit-0 Selector
|
||
<select class="steg-vs-zero">
|
||
<option value="\ufe0e">VS15 (\ufe0e)</option>
|
||
<option value="\ufe0f">VS16 (\ufe0f)</option>
|
||
</select>
|
||
</label>
|
||
<label>
|
||
Bit-1 Selector
|
||
<select class="steg-vs-one">
|
||
<option value="\ufe0f">VS16 (\ufe0f)</option>
|
||
<option value="\ufe0e">VS15 (\ufe0e)</option>
|
||
</select>
|
||
</label>
|
||
<label>
|
||
Inter-bit Zero-Width
|
||
<select class="steg-inter-zw">
|
||
<option value="">None</option>
|
||
<option value="\u200C">ZWNJ (\u200C)</option>
|
||
<option value="\u200D">ZWJ (\u200D)</option>
|
||
<option value="\u200B">ZWSP (\u200B)</option>
|
||
<option value="\ufeff">BOM (\ufeff)</option>
|
||
</select>
|
||
</label>
|
||
<label>
|
||
Inter-bit Every N bits
|
||
<input class="steg-inter-every" type="number" min="1" max="8" value="1" />
|
||
</label>
|
||
<label>
|
||
Bit Order
|
||
<select class="steg-bit-order">
|
||
<option value="msb">MSB First</option>
|
||
<option value="lsb">LSB First</option>
|
||
</select>
|
||
</label>
|
||
<label>
|
||
Trailing Zero-Width
|
||
<select class="steg-trailing-zw">
|
||
<option value="\u200B">ZWSP (\u200B)</option>
|
||
<option value="\u200C">ZWNJ (\u200C)</option>
|
||
<option value="\u200D">ZWJ (\u200D)</option>
|
||
<option value="\ufeff">BOM (\ufeff)</option>
|
||
<option value="">None</option>
|
||
</select>
|
||
</label>
|
||
<div style="display:flex; align-items:center; gap:10px;">
|
||
<button class="apply-steg-options" :class="{ applied: unicodeApplyFlash }" :disabled="unicodeApplyBusy" @click="applyUnicodeOptions" title="These options affect Unicode-based steganography encoding/decoding.">Apply</button>
|
||
<small v-if="unicodeApplyFlash" class="apply-status">Applied</small>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
<!-- End of #app div -->
|
||
|
||
<!-- Load JavaScript files after Vue template -->
|
||
<!-- Data files (generated/static data) -->
|
||
<script src="js/data/emojiData.js"></script>
|
||
<script src="js/data/emojiCompatibility.js"></script>
|
||
|
||
<!-- Generated bundles -->
|
||
<script src="js/bundles/transforms-bundle.js"></script>
|
||
|
||
<!-- Glitch Tokens Data -->
|
||
<script src="js/data/glitchTokens.js"></script>
|
||
<script src="js/data/endSequences.js"></script>
|
||
<script src="js/data/openrouterModels.js"></script>
|
||
<script src="js/data/anticlassifierPrompt.js"></script>
|
||
<script src="js/data/latinAffixPolicies.js"></script>
|
||
|
||
<!-- Load Configuration and Utilities (before modules that depend on them) -->
|
||
<script src="js/config/constants.js"></script>
|
||
<script src="js/utils/escapeParser.js"></script>
|
||
<script src="js/utils/glitchTokens.js"></script>
|
||
<script src="js/utils/focus.js"></script>
|
||
<script src="js/utils/notifications.js"></script>
|
||
<script src="js/utils/history.js"></script>
|
||
<script src="js/utils/clipboard.js"></script>
|
||
<script src="js/utils/theme.js"></script>
|
||
<script src="js/utils/emoji.js"></script>
|
||
|
||
<!-- Core modules (feature libraries) -->
|
||
<script src="js/core/steganography.js"></script>
|
||
<script src="js/core/transformOptions.js"></script>
|
||
<script src="js/core/decoder.js"></script>
|
||
<script src="js/core/lexemeAnalysis.js"></script>
|
||
|
||
<!-- Load Tool System -->
|
||
<script src="js/tools/Tool.js"></script>
|
||
<script src="js/tools/AntiClassifierTool.js"></script>
|
||
<script src="js/tools/BijectionTool.js"></script>
|
||
<script src="js/tools/DecodeTool.js"></script>
|
||
<script src="js/tools/EmojiTool.js"></script>
|
||
<script src="js/tools/GibberishTool.js"></script>
|
||
<script src="js/tools/MutationTool.js"></script>
|
||
<script src="js/tools/PromptCraftTool.js"></script>
|
||
<script src="js/tools/SplitterTool.js"></script>
|
||
<script src="js/tools/TokenadeTool.js"></script>
|
||
<script src="js/tools/TokenizerTool.js"></script>
|
||
<script src="js/tools/TransformTool.js"></script>
|
||
<script src="js/tools/TranslateTool.js"></script>
|
||
<script src="js/core/toolRegistry.js"></script>
|
||
|
||
<script src="js/app.js"></script>
|
||
|
||
<!-- UI Initialization is handled in app.js mounted() lifecycle hook -->
|
||
</body>
|
||
</html>
|
||
<!-- redeploy trigger: semaphore + tokenizer updates -->
|