1(function() { 2 const input = document.getElementById('input'); 3 const output = document.getElementById('output'); 4 const outChars = document.getElementById('out-chars'); 5 6 const TITLE_EXCLUDE = new Set(['a','an','the','and','but','or','nor','for','yet','so','of','in','on','at','to','by','with','from','as','is','was','are','were','been','be','have','has','had','do','does','did','will','would','could','should','may','might','must','can']); 7 8 function toSentenceCase(t) { 9 return t.toLowerCase().replace(/(^\s*\w|[.!?]\s*\w)/g, m => m.toUpperCase()); 10 } 11 12 function toTitleCase(t) { 13 return t.toLowerCase().replace(/\b\w+/g, (word, offset, str) => { 14 if (offset > 0 && TITLE_EXCLUDE.has(word)) return word; 15 return word.charAt(0).toUpperCase() + word.slice(1); 16 }); 17 } 18 19 function toAlternatingCase(t) { 20 let i = 0; 21 return t.replace(/[a-zA-Z]/g, c => (i++ % 2 === 0 ? c.toLowerCase() : c.toUpperCase())); 22 } 23 24 function toInverseCase(t) { 25 return t.replace(/[a-zA-Z]/g, c => c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase()); 26 } 27 28 function toCamelCase(t) { 29 const words = t.toLowerCase().replace(/[^\p{L}\p{N}\s-]/gu, ' ').split(/\s+/).filter(Boolean); 30 return words.map((w, i) => i === 0 ? w : w.charAt(0).toUpperCase() + w.slice(1)).join(''); 31 } 32 33 function toPascalCase(t) { 34 const words = t.toLowerCase().replace(/[^\p{L}\p{N}\s-]/gu, ' ').split(/\s+/).filter(Boolean);
35 return words.map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(''); 36 } 37 38 function toSnakeCase(t) { 39 const words = t.replace(/[^\p{L}\p{N}\s-]/gu, ' ').split(/\s+/).filter(Boolean); 40 return words.map(w => w.toLowerCase()).join('_'); 41 } 42 43 function toKebabCase(t) { 44 const words = t.replace(/[^\p{L}\p{N}\s-]/gu, ' ').split(/\s+/).filter(Boolean); 45 return words.map(w => w.toLowerCase()).join('-'); 46 } 47 48 let lastMode = 'upper'; 49 50 const modes = { 51 upper: t => t.toUpperCase(), 52 lower: t => t.toLowerCase(), 53 sentence: toSentenceCase, 54 title: toTitleCase, 55 capitalize: t => t.toLowerCase().replace(/\b\w/g, c => c.toUpperCase()), 56 alternating: toAlternatingCase, 57 inverse: toInverseCase, 58 camel: toCamelCase, 59 pascal: toPascalCase, 60 snake: toSnakeCase, 61 kebab: toKebabCase 62 }; 63 64 function apply(mode) { 65 const fn = modes[mode]; 66 if (fn) { 67 lastMode = mode; 68 output.value = fn(input.value); 69 } 70 updateStats(); 71 } 72 73 function updateStats() { 74 if (outChars) outChars.textContent = output.value.length; 75 } 76 77 function clearAll() { 78 input.value = ''; 79 output.value = ''; 80 updateStats(); 81 } 82 83 function showToast(msg) { 84 const t = document.createElement('div'); 85 t.className = 'toast'; 86 t.textContent = msg; 87 document.body.appendChild(t); 88 requestAnimationFrame(() => t.classList.add('toast-visible')); 89 setTimeout(() => { 90 t.classList.remove('toast-visible'); 91 setTimeout(() => t.remove(), 300); 92 }, 2000); 93 } 94 95 function copyOutput() { 96 output.select(); 97 try { 98 navigator.clipboard.writeText(output.value); 99 showToast('СкопиÑовано!'); 100 } catch (e) { 101 document.execCommand('copy'); 102 showToast('СкопиÑовано!'); 103 } 104 } 105 106 document.querySelectorAll('[data-mode]').forEach(btn => { 107 btn.addEventListener('click', () => apply(btn.dataset.mode)); 108 }); 109 110 function insertSample() { 111 const el = document.getElementById('sample-text'); 112 if (el) { 113 input.value = el.textContent || ''; 114 updateStats(); 115 const firstMode = document.querySelector('[data-mode]'); 116 if (firstMode) apply(firstMode.dataset.mode); 117 } 118 } 119 120 function setupUpload() { 121 const fileInput = document.getElementById('file-input'); 122 const btnUpload = document.getElementById('btn-upload'); 123 if (fileInput && btnUpload) { 124 btnUpload.addEventListener('click', () => fileInput.click()); 125 fileInput.addEventListener('change', function() { 126 const f = this.files && this.files[0]; 127 if (!f) return; 128 const r = new FileReader(); 129 r.onload = function() { 130 input.value = r.result; 131 updateStats(); 132 apply(lastMode); 133 }; 134 r.readAsText(f, 'UTF-8'); 135 fileInput.value = ''; 136 }); 137 } 138 } 139 140 document.addEventListener('keydown', function(e) { 141 if (e.ctrlKey && e.key === 'Enter') { 142 e.preventDefault(); 143 apply(lastMode); 144 } 145 }); 146 147 document.getElementById('btn-sample')?.addEventListener('click', insertSample); 148 document.getElementById('btn-clear')?.addEventListener('click', clearAll); 149 document.getElementById('btn-copy')?.addEventListener('click', copyOutput); 150 setupUpload(); 151 152 input.addEventListener('input', updateStats); 153 updateStats(); 154})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.