PageSourceSearch

https://wordcounter.world/js/case.js

js wordcounter.world collected 2026-09-25 22:53:35 UTC 4,755 bytes, 154 lines download raw bytes

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.