javascript:(function(){ setTimeout(function(){ var ST='BEGIN_WORDCOUNT_EXCLUSION'; var EXAMPLE_EXCLUSION="paste text here that shouldn't get counted in the word count \n(notice how this text has 33 words which get subtracted from the count per occurrence of this text in the main text) "; var ET='END_WORDCOUNT_EXCLUSION'; var title='', h1=document.querySelector('h1,.PostsPage-title'), tt=document.querySelector('title'), ghTitle=document.querySelector('input[name="issue[title]"]') ||document.querySelector('#issue_title') ||document.querySelector('input[aria-label*="Title"]') ||document.querySelector('input[placeholder*="Title"]'), ghBody=document.querySelector('textarea[name="issue[body]"]') ||document.querySelector('#issue_body') ||document.querySelector('textarea[aria-label*="description"]') ||document.querySelector('textarea.comment-form-textarea'); var allTextareas=document.querySelectorAll('textarea'); console.log('All textareas:', allTextareas); allTextareas.forEach(function(ta,i){console.log('Textarea '+i+' value:', ta.value);}); console.log('GitHub title element:', ghTitle); console.log('GitHub body element:', ghBody); if(ghTitle){console.log('Title value:', ghTitle.value);} if(ghBody){console.log('Body value:', ghBody.value);} if(ghTitle&&ghTitle.value){ title=ghTitle.value.trim();} else if(h1){title=(h1.innerText||h1.textContent).trim();} else if(tt){title=(tt.innerText||tt.textContent).trim();} /* Part of a vain attempt to make this work on google docs */ var ogDesc=document.querySelector('meta[property="og:description"]'); if(ogDesc){ console.log('og:description content:', ogDesc.getAttribute('content')); } var bodyText=''; if(ghBody&&ghBody.value){ bodyText=ghBody.value; }else{ var sels=['article','main', '.PostsPage-postContent', '.PostBody-root','.content','body'],e=null; for(var i=0;i \n - Convert Unicode spaces to ASCII space (LSEP/PSEP -> \n) - Drop invisibles (BOM, ZWSP, SHY, bidi controls, isolates) - KEEP emoji machinery: ZWJ (U+200D) and VS16 (U+FE0F) */ function sanitize(s){ s=String(s??''); if(s.normalize)s=s.normalize('NFC'); s=s.replace(/\r\n?/g,'\n'); s=s.replace(/[\u00AD\u200B\u2060\uFEFF\u200E\u200F\u202A-\u202E\u2066-\u2069]/g,''); s=s.replace(/[\u2028\u2029]/g,'\n'); s=s.replace(/[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]/g,' '); s=s.replace(/[ \t\f\v]+/g,' '); s=s.replace(/[ \t\f\v]*\n[ \t\f\v]*/g,'\n'); return s; } /* Word count: - Contiguous letters/digits/marks OR emoji clusters count as ONE word - No spaces => not separate words (e.g., "foo🙂bar" -> 1) - Spaced punctuation (e.g., " — ") does not count */ function wordcount(text){ text=sanitize(text); if(!text)return 0; var segOK=typeof Intl!=='undefined'&&typeof Intl.Segmenter==='function'; var graphemes=segOK?[...new Intl.Segmenter(undefined,{granularity:'grapheme'}).segment(text)].map(function(x){return x.segment;}) : matchGraphemesFallback(text); var EP=tryRe('\\p{Extended_Pictographic}'); var pictoFallback=/[\u2600-\u27BF\u{1F300}-\u{1FAFF}]/u; var flagRE=/^[\u{1F1E6}-\u{1F1FF}]{2}$/u; var keycapRE=/^(?:[0-9#*]\uFE0F?\u20E3)$/u; var letterNumMark=/[\p{L}\p{N}\p{M}]/u; var apostrophe=/^['’]$/u; var inWord=false,cnt=0; for(var i=0;i/g,'>'); } function highlightExcluded(s,exclusionTexts){ var sNorm=normalizeWS(s); var sNormLower=sNorm.toLowerCase(); var matches=[]; for(var i=0;i=lastIdx){ result+=escHtml(sNorm.slice(lastIdx,m.start)); result+=''+escHtml(sNorm.slice(m.start,m.end))+''; lastIdx=m.end; } } return result+escHtml(sNorm.slice(lastIdx)); } var prefix=getPrefixToFirst(t); var exclusionTexts=getAllExclusionTexts(t); var x=wordcount(prefix); var subtractTerms=[],totalSubtraction=0; for(var i=0;i0){ subtractTerms.push(y.toLocaleString()+'*'+n.toLocaleString()); totalSubtraction+=n*y; } } var result=x-totalSubtraction; var m=document.createElement('div'); m.style.cssText='position:fixed;top:20px;right:20px;background:#fff;padding:15px;border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,0.15);z-index:999999;font-family:sans-serif;width:360px;border:1px solid #ddd;max-height:calc(100vh - 40px);display:flex;flex-direction:column;overflow:hidden;'; var header=document.createElement('div'); header.style.cssText='display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;flex-shrink:0;'; var label=document.createElement('span'); label.style.cssText='font-size:13px;color:#666;'; label.textContent='Word Count'; var close=document.createElement('button'); close.type='button'; close.setAttribute('aria-label','Close'); close.style.cssText='border:none;background:none;cursor:pointer;font-size:16px;color:#999;padding:0;width:20px;height:20px;'; close.textContent='x'; header.appendChild(label); header.appendChild(close); var tally=document.createElement('div'); tally.className='wc-count'; tally.style.cssText='font-size:24px;font-weight:bold;color:#333;margin-bottom:10px;line-height:1.2;flex-shrink:0;'; if(subtractTerms.length>0){ tally.textContent=x.toLocaleString()+' - '+subtractTerms.join(' - ')+' = '+result.toLocaleString(); }else{ tally.textContent=x.toLocaleString()+' - 0 = '+result.toLocaleString(); } var preview=document.createElement('div'); preview.className='wc-preview'; preview.style.cssText='font-size:11px;color:#444;font-family:monospace;line-height:1.4;flex:1 1 auto;min-height:0;overflow:auto;background:#f5f5f5;padding:8px;border-radius:3px;white-space:pre-wrap;word-break:break-word;'; if(exclusionTexts.length>0){ var tempDiv=document.createElement('div'); tempDiv.innerHTML=highlightExcluded(prefix,exclusionTexts); while(tempDiv.firstChild)preview.appendChild(tempDiv.firstChild); }else{ preview.textContent=prefix; } var copy=document.createElement('button'); copy.id='wc-copy'; copy.type='button'; copy.style.cssText='margin-top:10px;padding:8px;background:#e3f2fd;border:2px dashed #2196F3;border-radius:3px;white-space:pre-wrap;font-size:9px;font-family:monospace;color:#1976D2;cursor:pointer;text-align:center;font-weight:bold;flex-shrink:0;'; copy.textContent='Copy exclusion tags'; copy.addEventListener('click',function(){ var lines=[ST, EXAMPLE_EXCLUSION, ET]; navigator.clipboard.writeText(lines.join(String.fromCharCode(10))); copy.style.background='#c8e6c9'; copy.textContent='Copied'; setTimeout(function(){ copy.style.background='#e3f2fd'; copy.textContent='Copy exclusion tags';},1500); }); m.appendChild(header); m.appendChild(tally); m.appendChild(preview); m.appendChild(copy); document.body.appendChild(m); function cleanup(){ if(m&&m.parentNode) m.parentNode.removeChild(m); document.removeEventListener('click',closeHandler,true); document.removeEventListener('keydown',keyHandler,true); } function closeHandler(evt){ if(!m.contains(evt.target)) cleanup(); } function keyHandler(e){ if((e.key||'')==='Escape') cleanup(); } close.addEventListener('click',function(e){ e.preventDefault(); e.stopPropagation(); cleanup(); }, {capture:true}); setTimeout(function(){ document.addEventListener('click',closeHandler,true); document.addEventListener('keyup',keyHandler,true); },10); },100); /* end of setTimeout */ })();