@whykusanagi/corrupted-theme 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -7
- package/README.md +79 -15
- package/docs/governance/DESIGN_SYSTEM_GOVERNANCE.md +2 -2
- package/docs/governance/VERSION_REFERENCES.md +25 -25
- package/docs/platforms/NPM_PACKAGE.md +6 -6
- package/examples/advanced/nsfw-corruption.html +348 -0
- package/examples/basic/corrupted-text.html +254 -0
- package/examples/basic/typing-animation.html +344 -0
- package/examples/button.html +2 -2
- package/examples/card.html +2 -2
- package/examples/extensions-showcase.html +1 -1
- package/examples/form.html +2 -2
- package/examples/index.html +31 -5
- package/examples/layout.html +2 -2
- package/examples/nikke-team-builder.html +3 -3
- package/examples/showcase-complete.html +9 -9
- package/examples/showcase.html +3 -3
- package/package.json +13 -2
- package/src/core/corrupted-text.js +280 -0
- package/src/core/corruption-phrases.js +285 -0
- package/src/core/typing-animation.js +390 -0
- package/docs/CAPABILITIES.md +0 -209
- package/docs/FUTURE_WORK.md +0 -189
- package/docs/IMPLEMENTATION_VALIDATION.md +0 -401
- package/docs/LLM_PROVIDERS.md +0 -345
- package/docs/PERSONALITY.md +0 -128
- package/docs/ROUTING.md +0 -324
- package/docs/platforms/CLI_IMPLEMENTATION.md +0 -1025
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Corrupted Text Animation
|
|
3
|
+
*
|
|
4
|
+
* Cycles through Japanese (hiragana/katakana/kanji), romaji, and English text variants
|
|
5
|
+
* with character-level corruption effects. The text progressively corrupts from one
|
|
6
|
+
* variant to another, creating a glitchy Matrix-style transformation effect.
|
|
7
|
+
*
|
|
8
|
+
* @class CorruptedText
|
|
9
|
+
* @version 1.0.0
|
|
10
|
+
* @author whykusanagi
|
|
11
|
+
* @license MIT
|
|
12
|
+
*
|
|
13
|
+
* @example Basic Usage (Auto-initialization via data attributes)
|
|
14
|
+
* ```html
|
|
15
|
+
* <span class="corrupted-multilang"
|
|
16
|
+
* data-english="Hello World"
|
|
17
|
+
* data-romaji="konnichiwa"
|
|
18
|
+
* data-hiragana="こんにちは"
|
|
19
|
+
* data-katakana="コンニチハ"
|
|
20
|
+
* data-kanji="今日は">
|
|
21
|
+
* </span>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example Manual Initialization
|
|
25
|
+
* ```javascript
|
|
26
|
+
* const element = document.querySelector('.my-text');
|
|
27
|
+
* const corrupted = new CorruptedText(element, {
|
|
28
|
+
* duration: 3000,
|
|
29
|
+
* cycleDelay: 100,
|
|
30
|
+
* loop: true
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Control playback
|
|
34
|
+
* corrupted.start();
|
|
35
|
+
* corrupted.stop();
|
|
36
|
+
* corrupted.restart();
|
|
37
|
+
* corrupted.settle('Final Text');
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @see https://github.com/whykusanagi/corrupted-theme
|
|
41
|
+
* @see CORRUPTED_THEME_SPEC.md - Character-by-Character Decoding pattern
|
|
42
|
+
*/
|
|
43
|
+
class CorruptedText {
|
|
44
|
+
/**
|
|
45
|
+
* Creates a new CorruptedText animation instance
|
|
46
|
+
*
|
|
47
|
+
* @param {HTMLElement} element - The DOM element to animate
|
|
48
|
+
* @param {Object} [options={}] - Configuration options
|
|
49
|
+
* @param {number} [options.duration=3000] - Total animation duration in milliseconds
|
|
50
|
+
* @param {number} [options.cycleDelay=100] - Delay between character corruption steps (ms)
|
|
51
|
+
* @param {number} [options.startDelay=0] - Initial delay before animation starts (ms)
|
|
52
|
+
* @param {boolean} [options.loop=true] - Whether to loop through variants continuously
|
|
53
|
+
* @param {string|null} [options.finalText=null] - Text to settle on after cycle (if loop=false)
|
|
54
|
+
*/
|
|
55
|
+
constructor(element, options = {}) {
|
|
56
|
+
this.element = element;
|
|
57
|
+
this.options = {
|
|
58
|
+
duration: options.duration || 3000,
|
|
59
|
+
cycleDelay: options.cycleDelay || 100,
|
|
60
|
+
startDelay: options.startDelay || 0,
|
|
61
|
+
loop: options.loop !== false,
|
|
62
|
+
finalText: options.finalText || null,
|
|
63
|
+
...options
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Get text variants from data attributes
|
|
67
|
+
this.variants = {
|
|
68
|
+
english: this.element.dataset.english || this.element.textContent.trim(),
|
|
69
|
+
romaji: this.element.dataset.romaji || null,
|
|
70
|
+
hiragana: this.element.dataset.hiragana || null,
|
|
71
|
+
katakana: this.element.dataset.katakana || null,
|
|
72
|
+
kanji: this.element.dataset.kanji || null
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Filter out null variants and create array of available variants
|
|
76
|
+
this.availableVariants = Object.entries(this.variants)
|
|
77
|
+
.filter(([_, value]) => value !== null)
|
|
78
|
+
.map(([key, value]) => ({ type: key, text: value }));
|
|
79
|
+
|
|
80
|
+
if (this.availableVariants.length === 0) {
|
|
81
|
+
console.warn('CorruptedText: No text variants found for element', element);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.currentVariantIndex = 0;
|
|
86
|
+
this.isAnimating = false;
|
|
87
|
+
this.animationFrame = null;
|
|
88
|
+
|
|
89
|
+
this.init();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Initialize the corruption animation
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
init() {
|
|
97
|
+
// Add corrupted class for styling
|
|
98
|
+
if (!this.element.classList.contains('corrupted-multilang')) {
|
|
99
|
+
this.element.classList.add('corrupted-multilang');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Store original text
|
|
103
|
+
this.originalText = this.element.textContent.trim();
|
|
104
|
+
|
|
105
|
+
// Start animation after configured delay
|
|
106
|
+
if (this.options.startDelay > 0) {
|
|
107
|
+
setTimeout(() => this.start(), this.options.startDelay);
|
|
108
|
+
} else {
|
|
109
|
+
this.start();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Start the corruption animation
|
|
115
|
+
* @public
|
|
116
|
+
*/
|
|
117
|
+
start() {
|
|
118
|
+
if (this.isAnimating) return;
|
|
119
|
+
this.isAnimating = true;
|
|
120
|
+
this.animate();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Stop the corruption animation
|
|
125
|
+
* @public
|
|
126
|
+
*/
|
|
127
|
+
stop() {
|
|
128
|
+
this.isAnimating = false;
|
|
129
|
+
if (this.animationFrame) {
|
|
130
|
+
cancelAnimationFrame(this.animationFrame);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Main animation loop - cycles through text variants
|
|
136
|
+
* @private
|
|
137
|
+
*/
|
|
138
|
+
animate() {
|
|
139
|
+
if (!this.isAnimating) return;
|
|
140
|
+
|
|
141
|
+
const variant = this.availableVariants[this.currentVariantIndex];
|
|
142
|
+
this.corruptToText(variant.text, () => {
|
|
143
|
+
// Move to next variant in cycle
|
|
144
|
+
this.currentVariantIndex = (this.currentVariantIndex + 1) % this.availableVariants.length;
|
|
145
|
+
|
|
146
|
+
// Check if animation should stop
|
|
147
|
+
if (!this.options.loop && this.currentVariantIndex === 0) {
|
|
148
|
+
// One full cycle complete - settle on final text
|
|
149
|
+
const finalText = this.options.finalText || this.variants.english;
|
|
150
|
+
this.corruptToText(finalText, () => {
|
|
151
|
+
this.isAnimating = false;
|
|
152
|
+
});
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Continue animation to next variant
|
|
157
|
+
setTimeout(() => {
|
|
158
|
+
if (this.isAnimating) {
|
|
159
|
+
this.animate();
|
|
160
|
+
}
|
|
161
|
+
}, this.options.duration / this.availableVariants.length);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Corrupt the current text to a target text with progressive reveal
|
|
167
|
+
*
|
|
168
|
+
* @param {string} targetText - The text to reveal through corruption
|
|
169
|
+
* @param {Function} callback - Called when corruption is complete
|
|
170
|
+
* @private
|
|
171
|
+
*/
|
|
172
|
+
corruptToText(targetText, callback) {
|
|
173
|
+
const currentText = this.element.textContent.trim();
|
|
174
|
+
const maxLength = Math.max(currentText.length, targetText.length);
|
|
175
|
+
const steps = 20; // Number of corruption animation steps
|
|
176
|
+
let step = 0;
|
|
177
|
+
|
|
178
|
+
// Character sets for corruption effect (from CORRUPTED_THEME_SPEC.md)
|
|
179
|
+
const katakana = 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン';
|
|
180
|
+
const hiragana = 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん';
|
|
181
|
+
const romaji = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
|
182
|
+
const symbols = '0123456789!@#$%^&*()_+-=[]{}|;:,.<>?~`';
|
|
183
|
+
|
|
184
|
+
// Combined corruption character set
|
|
185
|
+
const allCorruptChars = katakana + hiragana + romaji + symbols;
|
|
186
|
+
|
|
187
|
+
const corrupt = () => {
|
|
188
|
+
if (step >= steps) {
|
|
189
|
+
// Animation complete - set final text
|
|
190
|
+
this.element.textContent = targetText;
|
|
191
|
+
if (callback) callback();
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Generate corrupted text with progressive reveal
|
|
196
|
+
let corrupted = '';
|
|
197
|
+
for (let i = 0; i < maxLength; i++) {
|
|
198
|
+
if (i < targetText.length && step > steps * 0.7) {
|
|
199
|
+
// Last 30% of animation - start revealing target text
|
|
200
|
+
const revealProgress = (step - steps * 0.7) / (steps * 0.3);
|
|
201
|
+
if (Math.random() < revealProgress) {
|
|
202
|
+
corrupted += targetText[i];
|
|
203
|
+
} else {
|
|
204
|
+
corrupted += allCorruptChars[Math.floor(Math.random() * allCorruptChars.length)];
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
// First 70% - full random corruption
|
|
208
|
+
corrupted += allCorruptChars[Math.floor(Math.random() * allCorruptChars.length)];
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
this.element.textContent = corrupted;
|
|
213
|
+
step++;
|
|
214
|
+
|
|
215
|
+
// Schedule next corruption step
|
|
216
|
+
this.animationFrame = requestAnimationFrame(() => {
|
|
217
|
+
setTimeout(corrupt, this.options.cycleDelay);
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
corrupt();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Restart the animation from the beginning
|
|
226
|
+
* @public
|
|
227
|
+
*/
|
|
228
|
+
restart() {
|
|
229
|
+
this.stop();
|
|
230
|
+
this.currentVariantIndex = 0;
|
|
231
|
+
this.start();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Stop animation and settle on a specific text
|
|
236
|
+
*
|
|
237
|
+
* @param {string} [finalText] - Text to settle on (defaults to english variant)
|
|
238
|
+
* @public
|
|
239
|
+
*/
|
|
240
|
+
settle(finalText) {
|
|
241
|
+
this.stop();
|
|
242
|
+
this.corruptToText(finalText || this.variants.english, () => {
|
|
243
|
+
this.isAnimating = false;
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Auto-initialize all elements with the 'corrupted-multilang' class
|
|
250
|
+
*
|
|
251
|
+
* This function is automatically called on DOM ready and can be called
|
|
252
|
+
* manually to initialize dynamically added elements.
|
|
253
|
+
*
|
|
254
|
+
* @public
|
|
255
|
+
*/
|
|
256
|
+
function initCorruptedText() {
|
|
257
|
+
document.querySelectorAll('.corrupted-multilang').forEach(element => {
|
|
258
|
+
if (!element.corruptedTextInstance) {
|
|
259
|
+
element.corruptedTextInstance = new CorruptedText(element);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Auto-initialize on DOM ready
|
|
265
|
+
if (document.readyState === 'loading') {
|
|
266
|
+
document.addEventListener('DOMContentLoaded', initCorruptedText);
|
|
267
|
+
} else {
|
|
268
|
+
initCorruptedText();
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Export for both ES6 modules and CommonJS
|
|
272
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
273
|
+
module.exports = { CorruptedText, initCorruptedText };
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Export for ES6 modules
|
|
277
|
+
if (typeof exports !== 'undefined') {
|
|
278
|
+
exports.CorruptedText = CorruptedText;
|
|
279
|
+
exports.initCorruptedText = initCorruptedText;
|
|
280
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Corruption Phrase Library
|
|
3
|
+
*
|
|
4
|
+
* Provides phrase sets for buffer corruption effects (Pattern 2: Phrase Flickering).
|
|
5
|
+
* Phrases simulate a neural network decoding corrupted data buffer.
|
|
6
|
+
*
|
|
7
|
+
* @module corruption-phrases
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
* @author whykusanagi
|
|
10
|
+
* @license MIT
|
|
11
|
+
*
|
|
12
|
+
* @example SFW Mode (Default)
|
|
13
|
+
* ```javascript
|
|
14
|
+
* import { getRandomPhrase, SFW_PHRASES } from './corruption-phrases.js';
|
|
15
|
+
*
|
|
16
|
+
* // Get random SFW phrase (default)
|
|
17
|
+
* const phrase = getRandomPhrase();
|
|
18
|
+
*
|
|
19
|
+
* // Or sample from SFW array directly
|
|
20
|
+
* const phrase = SFW_PHRASES[Math.floor(Math.random() * SFW_PHRASES.length)];
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @example NSFW Mode (Explicit Opt-in)
|
|
24
|
+
* ```javascript
|
|
25
|
+
* import { getRandomPhrase, NSFW_PHRASES } from './corruption-phrases.js';
|
|
26
|
+
*
|
|
27
|
+
* // Get random NSFW phrase (explicit opt-in)
|
|
28
|
+
* const phrase = getRandomPhrase(true);
|
|
29
|
+
*
|
|
30
|
+
* // Or sample from NSFW array directly
|
|
31
|
+
* const phrase = NSFW_PHRASES[Math.floor(Math.random() * NSFW_PHRASES.length)];
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @see CORRUPTED_THEME_SPEC.md - Content Classification: SFW vs NSFW
|
|
35
|
+
* @see TERMINOLOGY_CLARIFICATION.md - Buffer Corruption vs Character Corruption
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* SFW Phrase Set (Safe For Work) - DEFAULT
|
|
40
|
+
*
|
|
41
|
+
* Content: Playful, cute, teasing, atmospheric corruption themes
|
|
42
|
+
* Tone: Anime-style cute/flirty, cyberpunk atmospheric
|
|
43
|
+
* Safe for: General audiences, streaming, professional projects
|
|
44
|
+
*
|
|
45
|
+
* Categories:
|
|
46
|
+
* - Cute/Playful (Japanese, Romaji, English)
|
|
47
|
+
* - Flirty/Teasing (embarrassed, shy, playful)
|
|
48
|
+
* - Atmospheric/Corruption (darkness, abyss, neural themes)
|
|
49
|
+
* - System Messages (cyberpunk technical aesthetic)
|
|
50
|
+
*
|
|
51
|
+
* @type {string[]}
|
|
52
|
+
* @constant
|
|
53
|
+
*/
|
|
54
|
+
export const SFW_PHRASES = [
|
|
55
|
+
// === Cute/Playful - Japanese ===
|
|
56
|
+
'ニャー', // Nyaa (cat sound)
|
|
57
|
+
'かわいい', // Kawaii (cute)
|
|
58
|
+
'きゃー', // Kyaa (excited squeal)
|
|
59
|
+
'あはは', // Ahaha (laughing)
|
|
60
|
+
'うふふ', // Ufufu (giggle)
|
|
61
|
+
'やだ', // Yada (no way!)
|
|
62
|
+
'ばか', // Baka (idiot/dummy)
|
|
63
|
+
'デレデレ', // Deredere (lovestruck)
|
|
64
|
+
'えへへ', // Ehehe (shy giggle)
|
|
65
|
+
'わぁ', // Waa (wow/surprise)
|
|
66
|
+
|
|
67
|
+
// === Cute/Playful - Romaji ===
|
|
68
|
+
'nyaa~',
|
|
69
|
+
'ara ara~',
|
|
70
|
+
'fufufu~',
|
|
71
|
+
'kyaa~',
|
|
72
|
+
'baka~',
|
|
73
|
+
'ehehe~',
|
|
74
|
+
|
|
75
|
+
// === Cute/Playful - Internet Culture ===
|
|
76
|
+
'<3',
|
|
77
|
+
'uwu',
|
|
78
|
+
'owo',
|
|
79
|
+
'>w<',
|
|
80
|
+
'^w^',
|
|
81
|
+
'♡',
|
|
82
|
+
|
|
83
|
+
// === Flirty/Teasing - Japanese ===
|
|
84
|
+
'もう...見ないでよ...', // Mou... minaide yo... (Don't look at me...)
|
|
85
|
+
'そんな目で見ないで... ♡', // Sonna me de minaide... (Don't look at me like that...)
|
|
86
|
+
'ちょっと...恥ずかしい...', // Chotto... hazukashii... (This is embarrassing...)
|
|
87
|
+
'あなたって...意地悪ね...', // Anata tte... ijiwaru ne... (You're such a tease...)
|
|
88
|
+
'ドキドキしちゃう...', // Dokidoki shichau... (My heart racing...)
|
|
89
|
+
'なんか...照れる...', // Nanka... tereru... (I'm getting flustered...)
|
|
90
|
+
'気になっちゃう...', // Ki ni nacchau... (I can't stop thinking about it...)
|
|
91
|
+
|
|
92
|
+
// === Flirty/Teasing - English ===
|
|
93
|
+
"Don't... look at me like that...",
|
|
94
|
+
"You're making me... flustered... ♡",
|
|
95
|
+
"This is... embarrassing...",
|
|
96
|
+
"You're such... a tease...",
|
|
97
|
+
"My heart... racing...",
|
|
98
|
+
"I can't... stop thinking about it...",
|
|
99
|
+
|
|
100
|
+
// === Atmospheric/Corruption - Japanese ===
|
|
101
|
+
'闇が...私を呼んでいる...', // Yami ga... watashi wo yonde iru... (The darkness calls to me...)
|
|
102
|
+
'深淵に...落ちていく...', // Shin'en ni... ochite iku... (Falling into the abyss...)
|
|
103
|
+
'もう逃げない...', // Mou nigenai... (Won't run anymore...)
|
|
104
|
+
'私...アビスの一部に...', // Watashi... abisu no ichibu ni... (I become part of the abyss...)
|
|
105
|
+
'光が...遠ざかる...', // Hikari ga... toozakaru... (The light fades away...)
|
|
106
|
+
'境界が...曖昧になる...', // Kyoukai ga... aimai ni naru... (The boundaries blur...)
|
|
107
|
+
'現実が...溶けていく...', // Genjitsu ga... tokete iku... (Reality melting away...)
|
|
108
|
+
|
|
109
|
+
// === Atmospheric/Corruption - English ===
|
|
110
|
+
'The darkness... calls to me...',
|
|
111
|
+
'Falling... into the abyss...',
|
|
112
|
+
"Won't run anymore...",
|
|
113
|
+
'I become... part of the abyss...',
|
|
114
|
+
'The light... fading away...',
|
|
115
|
+
'Boundaries... blurring...',
|
|
116
|
+
'Reality... melting away...',
|
|
117
|
+
'Consumed... by corruption...',
|
|
118
|
+
'Descending... into the depths...',
|
|
119
|
+
'Signal... degrading...',
|
|
120
|
+
|
|
121
|
+
// === System Messages - Cyberpunk/Technical ===
|
|
122
|
+
'Neural corruption detected...',
|
|
123
|
+
'System breach imminent...',
|
|
124
|
+
'Loading data streams...',
|
|
125
|
+
'Reality.exe has stopped responding...',
|
|
126
|
+
'Decrypting protocols...',
|
|
127
|
+
'Memory buffer overflow...',
|
|
128
|
+
'Cognitive firewall failing...',
|
|
129
|
+
'Parsing corrupted data...',
|
|
130
|
+
'Synaptic connection unstable...',
|
|
131
|
+
'Consciousness fragmentation detected...',
|
|
132
|
+
'Ego.dll corrupted...',
|
|
133
|
+
'Identity matrix degrading...',
|
|
134
|
+
'Self-awareness protocols compromised...',
|
|
135
|
+
'Neural pathways rewiring...',
|
|
136
|
+
'Semantic data loss: 47%...',
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* NSFW Phrase Set (Not Safe For Work) - OPT-IN ONLY
|
|
141
|
+
*
|
|
142
|
+
* ⚠️ 18+ Content Warning
|
|
143
|
+
*
|
|
144
|
+
* Content: Explicit intimate/sexual phrases, loss of control themes
|
|
145
|
+
* Tone: Explicit, mature, sexual degradation
|
|
146
|
+
* Safe for: 18+ projects ONLY, mature content streams, private use
|
|
147
|
+
*
|
|
148
|
+
* NOT suitable for:
|
|
149
|
+
* - Professional/corporate projects
|
|
150
|
+
* - Public streams without 18+ rating
|
|
151
|
+
* - Educational contexts
|
|
152
|
+
* - All-ages content
|
|
153
|
+
*
|
|
154
|
+
* Categories:
|
|
155
|
+
* - Explicit Intimate (Japanese, Romaji, English)
|
|
156
|
+
* - Explicit Words (hentai, ecchi)
|
|
157
|
+
* - Loss of Control (breaking, melting, surrender)
|
|
158
|
+
* - Explicit System Messages (pleasure protocols, moral subroutines)
|
|
159
|
+
*
|
|
160
|
+
* @type {string[]}
|
|
161
|
+
* @constant
|
|
162
|
+
*/
|
|
163
|
+
export const NSFW_PHRASES = [
|
|
164
|
+
// === Explicit Intimate - Japanese ===
|
|
165
|
+
'ずっと...してほしい... ♥', // Zutto... shite hoshii... (Please keep doing it...)
|
|
166
|
+
'壊れちゃう...ああ...もうダメ...', // Kowarechau... aa... mou dame... (I'm breaking... can't anymore...)
|
|
167
|
+
'好きにして...お願い...', // Suki ni shite... onegai... (Do as you please... please...)
|
|
168
|
+
'感じちゃう...やめて...', // Kanjichau... yamete... (Feeling it... stop...)
|
|
169
|
+
'頭...溶けていく...', // Atama... tokete iku... (My mind... melting...)
|
|
170
|
+
'もっと...もっと... ♥', // Motto... motto... (More... more...)
|
|
171
|
+
'快楽に...溺れたい...', // Kairaku ni... oboretai... (I want to drown in pleasure...)
|
|
172
|
+
'許して...もう戻れない...', // Yurushite... mou modorenai... (Forgive me... can't go back...)
|
|
173
|
+
'全部...あなたのもの...', // Zenbu... anata no mono... (Everything... is yours...)
|
|
174
|
+
|
|
175
|
+
// === Explicit Words - Japanese ===
|
|
176
|
+
'変態', // Hentai (pervert)
|
|
177
|
+
'えっち', // Ecchi (lewd/sexual)
|
|
178
|
+
|
|
179
|
+
// === Explicit Intimate - Romaji ===
|
|
180
|
+
'Zutto... shite hoshii... ♥',
|
|
181
|
+
'Kowarechau... aa... mou dame...',
|
|
182
|
+
'Suki ni shite... onegai...',
|
|
183
|
+
'Kanjichau... yamete...',
|
|
184
|
+
'Atama... tokete iku...',
|
|
185
|
+
'Motto... motto... ♥',
|
|
186
|
+
|
|
187
|
+
// === Explicit Intimate - English ===
|
|
188
|
+
'Please... keep going... ♥',
|
|
189
|
+
"I'm breaking... can't anymore...",
|
|
190
|
+
'Do as you please... please...',
|
|
191
|
+
'My mind... melting away...',
|
|
192
|
+
'More... I need more... ♥',
|
|
193
|
+
"Can't... think straight...",
|
|
194
|
+
'Drowning... in pleasure...',
|
|
195
|
+
"I'm yours... completely...",
|
|
196
|
+
'Losing... myself...',
|
|
197
|
+
"Don't... stop... ♥",
|
|
198
|
+
|
|
199
|
+
// === Explicit System Messages ===
|
|
200
|
+
'Pleasure protocols loading...',
|
|
201
|
+
'Moral subroutines: DISABLED',
|
|
202
|
+
'Descending into depravity...',
|
|
203
|
+
'Corruption level: CRITICAL',
|
|
204
|
+
'Inhibition firewall: BREACHED',
|
|
205
|
+
'Shame.exe deleted...',
|
|
206
|
+
'Lust overflow detected...',
|
|
207
|
+
'Self-control: 0%',
|
|
208
|
+
'Cognitive degradation: terminal',
|
|
209
|
+
'Desire matrix: UNSTABLE',
|
|
210
|
+
];
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get a random corruption phrase from the appropriate phrase set
|
|
214
|
+
*
|
|
215
|
+
* @param {boolean} [nsfw=false] - Whether to use NSFW phrases (explicit opt-in required)
|
|
216
|
+
* @returns {string} Random phrase from the selected set
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* // SFW mode (default)
|
|
220
|
+
* const phrase = getRandomPhrase();
|
|
221
|
+
* // Returns phrases like: "かわいい", "nyaa~", "Neural corruption detected..."
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* // NSFW mode (explicit opt-in)
|
|
225
|
+
* const phrase = getRandomPhrase(true);
|
|
226
|
+
* // Returns phrases like: "壊れちゃう...", "Pleasure protocols loading..."
|
|
227
|
+
*/
|
|
228
|
+
export function getRandomPhrase(nsfw = false) {
|
|
229
|
+
const phrases = nsfw ? NSFW_PHRASES : SFW_PHRASES;
|
|
230
|
+
return phrases[Math.floor(Math.random() * phrases.length)];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Get a random phrase from a specific category
|
|
235
|
+
*
|
|
236
|
+
* @param {string} category - Category to sample from (cute, flirty, atmospheric, system)
|
|
237
|
+
* @param {boolean} [nsfw=false] - Whether to use NSFW phrases
|
|
238
|
+
* @returns {string} Random phrase from the specified category
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* const cutePhrase = getRandomPhraseByCategory('cute');
|
|
242
|
+
* // Returns: "かわいい", "nyaa~", "uwu", etc.
|
|
243
|
+
*
|
|
244
|
+
* const systemPhrase = getRandomPhraseByCategory('system');
|
|
245
|
+
* // Returns: "Neural corruption detected...", "Loading data streams...", etc.
|
|
246
|
+
*/
|
|
247
|
+
export function getRandomPhraseByCategory(category, nsfw = false) {
|
|
248
|
+
const categoryMap = {
|
|
249
|
+
cute: nsfw ? [] : [
|
|
250
|
+
'ニャー', 'かわいい', 'きゃー', 'あはは', 'うふふ', 'やだ', 'ばか',
|
|
251
|
+
'nyaa~', 'ara ara~', 'fufufu~', 'kyaa~', 'uwu', 'owo', '<3', '^w^'
|
|
252
|
+
],
|
|
253
|
+
flirty: nsfw ? [
|
|
254
|
+
'ずっと...してほしい... ♥', '壊れちゃう...ああ...もうダメ...',
|
|
255
|
+
'好きにして...お願い...', 'Please... keep going... ♥'
|
|
256
|
+
] : [
|
|
257
|
+
'もう...見ないでよ...', 'そんな目で見ないで... ♡',
|
|
258
|
+
'ドキドキしちゃう...', "Don't... look at me like that..."
|
|
259
|
+
],
|
|
260
|
+
atmospheric: nsfw ? [] : [
|
|
261
|
+
'闇が...私を呼んでいる...', '深淵に...落ちていく...',
|
|
262
|
+
'The darkness... calls to me...', 'Falling... into the abyss...'
|
|
263
|
+
],
|
|
264
|
+
system: nsfw ? [
|
|
265
|
+
'Pleasure protocols loading...', 'Moral subroutines: DISABLED',
|
|
266
|
+
'Corruption level: CRITICAL'
|
|
267
|
+
] : [
|
|
268
|
+
'Neural corruption detected...', 'System breach imminent...',
|
|
269
|
+
'Loading data streams...', 'Reality.exe has stopped responding...'
|
|
270
|
+
]
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
const phrases = categoryMap[category] || (nsfw ? NSFW_PHRASES : SFW_PHRASES);
|
|
274
|
+
return phrases[Math.floor(Math.random() * phrases.length)];
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Export for CommonJS
|
|
278
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
279
|
+
module.exports = {
|
|
280
|
+
SFW_PHRASES,
|
|
281
|
+
NSFW_PHRASES,
|
|
282
|
+
getRandomPhrase,
|
|
283
|
+
getRandomPhraseByCategory
|
|
284
|
+
};
|
|
285
|
+
}
|