Files
P4RS3LT0NGV3/index.template.html
2026-04-05 15:23:09 -04:00

454 lines
24 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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 -->