1/* Shared text transformation library â used by: 2 * - Word Counter toolbar ("apply transformation" buttons) 3 * - Any tool that wants to expose multiple transforms 4 * 5 * Public API: window.WCT_TRANSFORMS â { name: fn(string) => string, ... } 6 */ 7(function () { 8 if (window.WCT_TRANSFORMS) return; 9 10 // ---------- Unicode style maps ---------- 11 // Mathematical Bold: A-Z = 0x1D400, a-z = 0x1D41A, 0-9 = 0x1D7CE 12 function mathBold(c) { 13 const o = c.charCodeAt(0); 14 if (o >= 65 && o <= 90) return String.fromCodePoint(0x1D400 + o - 65); 15 if (o >= 97 && o <= 122) return String.fromCodePoint(0x1D41A + o - 97); 16 if (o >= 48 && o <= 57) return String.fromCodePoint(0x1D7CE + o - 48); 17 return c; 18 } 19 // Mathematical Italic: A-Z = 0x1D434, a-z = 0x1D44E (h is special at 0x210E) 20 function mathItalic(c) { 21 const o = c.charCodeAt(0); 22 if (c === "h") return "â"; 23 if (o >= 65 && o <= 90) return String.fromCodePoint(0x1D434 + o - 65); 24 if (o >= 97 && o <= 122) return String.fromCodePoint(0x1D44E + o - 97); 25 return c; 26 } 27 // Script (cursive): A-Z = 0x1D4D0, a-z = 0x1D4EA 28 function script(c) { 29 const o = c.charCodeAt(0); 30 if (o >= 65 && o <= 90) return String.fromCodePoint(0x1D4D0 + o - 65); 31 if (o >= 97 && o <= 122) return String.fromCodePoint(0x1D4EA + o - 97); 32 return c; 33 } 34 // Enclosed alphanumerics (bubble): A-Z = 0x24B6, a-z = 0x24D0, 0 = 0x24EA, 1-9 = 0x2460 35 function bubble(c) { 36 const o = c.charCodeAt(0); 37 if (o >= 65 && o <= 90) return String.fromCodePoint(0x24B6 + o - 65); 38 if (o >= 97 && o <= 122) return String.fromCodePoint(0x24D0 + o - 97); 39 if (c === "0") return "âª"; 40 if (o >= 49 && o <= 57) return String.fromCodePoint(0x2460 + o - 49); 41 return c; 42 } 43 const SMALL_CAPS = {a:"á´",b:"Ê",c:"á´",d:"á´ ",e:"á´",f:"ê°",g:"É¢",h:"Ê",i:"ɪ",j:"á´",k:"á´",l:"Ê",m:"á´",n:"É´",o:"á´",p:"á´",q:"Ç«",r:"Ê",s:"s",t:"á´",u:"á´",v:"á´ ",w:"á´¡",x:"x",y:"Ê",z:"á´¢"}; 44 const UPSIDE = {a:"É",b:"q",c:"É",d:"p",e:"Ç",f:"É",g:"Æ",h:"É¥",i:"á´",j:"ɾ",k:"Ê",l:"l",m:"ɯ",n:"u",o:"o",p:"d",q:"b",r:"ɹ",s:"s",t:"Ê",u:"n",v:"Ê",w:"Ê",x:"x",y:"Ê",z:"z","?":"¿","!":"¡",".":"Ë",",":"'","'":",","(":")",")":"(","<":">",">":"<","[":"]","]":"["}; 45 46 function unicodeMap(s, mapFn) { 47 let out = ""; 48 for (const c of s) out += mapFn(c); 49 return out; 50 } 51 function dictMap(s, dict) { 52 let out = ""; 53 for (const c of s.toLowerCase()) out += (dict[c] || c); 54 return out; 55 } 56 57 // ---------- Public transforms ---------- 58 const T = window.WCT_TRANSFORMS = { 59 bold: s => unicodeMap(s, mathBold), 60 italic: s => unicodeMap(s, mathItalic), 61 strike: s => [...s].map(c => c + "̶").join(""), 62 smallcaps: s => dictMap(s, SMALL_CAPS), 63 cursive: s => unicodeMap(s, script), 64 bubble: s => unicodeMap(s, bubble), 65 upside: s => [...s.toLowerCase()].reverse().map(c => UPSIDE[c] || c).join(""), 66 bionic: s => { 67 // Pseudo-bionic in plain text: wrap first half of each word in Unicode bold. 68 return s.replace(/[A-Za-zÃ-ÿ]+/g, w => { 69 const cut = Math.max(1, Math.ceil(w.length / 2)); 70 return unicodeMap(w.slice(0, cut), mathBold) + w.slice(cut); 71 }); 72 }, 73 reverse: s => s.split(/(\s+)/).reverse().join(""), 74 trim: s => s.split("\n").map(l => l.replace(/^\s+|\s+$/g, "").replace(/\s+/g, " ")).join("\n").replace(/\n{3,}/g, "\n\n"), 75 dedupe: s => { 76 const seen = new Set(), out = []; 77 for (const line of s.split("\n")) if (!seen.has(line)) { seen.add(line); out.push(line); } 78 return out.join("\n"); 79 }, 80 sort: s => s.split("\n").sort((a, b) => a.localeCompare(b, undefined, {sensitivity: "base"})).join("\n"), 81 snake: s => s.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, ""), 82 kebab: s => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""), 83 camel: s => { 84 const words = s.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter(Boolean); 85 return words.map((w, i) => i === 0 ? w : w[0].toUpperCase() + w.slice(1)).join(""); 86 }, 87 pascal: s => { 88 const words = s.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter(
88Boolean); 89 return words.map(w => w[0].toUpperCase() + w.slice(1)).join(""); 90 }, 91 constant: s => s.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_|_$/g, ""), 92 }; 93})();
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.