Skip to content

Instantly share code, notes, and snippets.

@derekmc
Last active January 7, 2025 15:19
Show Gist options
  • Save derekmc/19bc63b1c270b8fc3a5afa69a3722747 to your computer and use it in GitHub Desktop.
Save derekmc/19bc63b1c270b8fc3a5afa69a3722747 to your computer and use it in GitHub Desktop.
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
/* CSS */
body{
font-family: sans-serif;
text-align: center;
}
input[type=number]{
width: 35px;
}
#wordchecker{
display: inline-block;
font-size: 20px;
background: #00a;
color: #fff;
padding: 20px;
width: 250px;
text-align: center;
}
#wordindex{
display: inline-block;
font-size: 20px;
background: #235;
color: #fff;
padding: 20px;
width: 60px;
text-align: center;
}
button{
background: #000;
color: #fff;
font-size: 16px;
border-radius: 10px;
padding: 8px 16px;
border: none;
font-weight: bold;
}
#excludelist, #includelist{
font-family: monospace;
width: 400px;
}
/* END */
</style>
</head>
<body>
<div class="markdown-src">
<!-- HTML -->
# Dictionary Filter Tool <hr>
## Load Dictionary
Dictionary URL&emsp;
<input type="text" id='dicturl_input'
value="https://raw.githubusercontent.com/first20hours/google-10000-english/refs/heads/master/20k.txt">
<br><br>
<button onclick='loadDict()'>Load</button>
<br><br>
<hr>
## Filter
Min Length <input id='minlen' type='number' value='2' onchange='updateWords()'>
&emsp;Max Length <input id='maxlen' type='number' value='5' onchange='updateWords()'>
<br><br>
<span id="wordindex">000</span>
<span id="wordchecker">Test Word</span>
<br><br>
<button onclick="prev()" title="Left Arrow">Prev</button>
<button onclick="reject()" title="Space">Reject</button>
<button onclick="accept()" title="Enter">Next</button>
<br>
&nbsp;Left &emsp; &emsp; Enter &emsp;&emsp; Right
<hr>
<h3> Exclude List </h3>
<span id='excludelist'>
The quick brown fox
</span>
<br><br>
<button onclick='copyExclude()'>Copy Exclude</button>
<hr>
<h3> Include List </h3>
<span id="includelist"></span>
<br><br>
<button onclick='copyInclude()'>Copy Include</button>
<!-- END -->
</div>
<div style="display: none;"></div>
<script>
let datakey = "__HTML_NOTES__:notedataid=KsfJOvIznj"
let inframe = (window!=window.top)
window.Note = {}
window.Note.data =
/* JSON */
{"exclude":["re","pm","jan","uk","non","rss","faq","feb","sep","et","st","aug","apr","en","jul","ny","eur","usr","nj","em","rw","ne","du","nt","es","gb","pr","fr","aa","var","mt","usd","mg","les","ch","sd","rs","avg","src","pda","dsl","sql","ss","ap","nm","mn","nd","op","acc","tn","ce","der","tm","sp","nh","mysql","pdt","db","ia","pt","ds","und","lg","nw","ff","ky","dont","br","ml","res","cs","sf","ut","ag","edt","pmid","cr","pg","ee","ing","ks","sw","hd","er","gcc","asp","nv","su","exp","nr","mp","def","nl","tr","bb","nz","te","av","nsw","pci","cst","twiki","ec","rm","pdas","cf","vt","urw","nec","gm","ri","rt","cp","dd","pl","crm","rf","ak","td","sb","sm","wv","ns","bs","hrs","img","rpm","ll","cl","ieee","ae","hs","yr","ic","mx","gr","xhtml","ext","ts","ge","pe","tt","dv","val","fy","rr","ef","jp","bt","rfc","sl","ins","hb","tc","oem","zdnet","oclc","plc","msg","cb","fc","fw","gs","bp","std","oo","fs","nn","kde","vb","dl","ls","phpbb","je","cms","sg","nav","ist","lc","sys","icq","scsi","cu","pty","ws","np","tft","jvc","dt","gc","ci","yn","vii","cfr","pmc","nb","rx","ddr","this","dec","ii","ca","oct","nov","jun","mon","fri","cnet","ltd","hp","ip","tue","thu","tx","iii","gmt","fl","il","az","th","pp","au","nc","va","rd","sc","se","ga","sa","wi","ct","eq","jd","oe","wy","pd","uc","ld","mf","mw","nu","dp","ht","za","ve","rh","fg","bk","dx","sk","yu","oc","wp","jm","cn","rn","cg","ix","tb","bm","rj","ka","rp","hc","fp","jj","rl","gl","dh","df","pf","uw","bd","hh","fd","wm","pk","wb","sn","dk","fu","wn","sv","zu","dg","vg","ul","js","pn","wt","mv","rb","mh","ww","bw","lf","wr","rg","bl","wx","bg","kw","lm","hl","zus","cet","ppc","ons","tgp","ati","ict","asn","qld","llp","sbjct","apnic","cdna","qt","dts","pgp","cz","ob","aaa","an","we","us","if","my","do","no","he","up","so","am","me","mediawiki","wto","ccd","aud","fcc","eds","gpl","ac","af","gmc","gtk","loc","oxley","arxiv","ru","lu","tg","pv","vw","dw","jl","mk","wl","sz","bf","sj","ij","xd","wh","xr","bn","wk","jb","jw","xt","fb","ua","kc","kt","tw","gw","ao","tl","lr","nf","pw","wg","lv","hf","wd","lj","ke","lx","bv","tk","gf","vm","jh","uu","kr","jt","dn","hw","xm","fn","ib","gh","gn","yy","gu","ay","jf","kk","bh","kl","pu","px","cy","lh","kd","xv","ji","hj","sx","rk","ux","vu","sy","ik","hx","ov","cx","fh","ej","dy","qb","jg","xf","hn","vv","wf","oa","iu","vf","zz","kj","kv","kx","eo","lw","ju","vo","xy","uf","kh","vn","wj","lq","hy","ih","nk","ud","lk","kp","vx","gk","hv","aq","gx","fj","gj","gz","tz","xa","ue","kn","py","vl","dq","pq","ub","xu","bx","jn","dz","zh","kz","cq","xb","qd","iz","gv","ck","ki","bj","ku","vid","bbw","wal","rrp","ooo","ste","tba","boc","tmp","ala","cio","enb","ata","wma","cir","dsc","wan","sen","dat","ind","qui","slr","rel","ign","att","ffl","ppp","ies","xsl","ctr","vcd","mst","dmx","str","obj","auf","pkg","sch","mfg","blk","bsd","adv","imc","pcr","mmc","rms","ont","hsn","sgh","een","rdf","liu","gta","abt","svn","twp","atx","bst","nsf","dcr","kvm","sts","goa","thr","emi","dst","msa","pcb","crc","chf","clr","dba","cdr","agp","exc","fra","rcw","aps","iis","jsp","dlp","afp","nfs","lac","edi","pid","xii","emc","aix","psc","icc","iec","esa","uml","spi","ppl","hcl","abn","mfr","afb","tcl","qos","dmc","asc","nsu","wks","rbi","ics","apa","phe","ses","bsc","bbb","nws","ngc","kos","psu","ogg","tyr","lsu","uid","umd","gdb","rpc","thb","idg","dds","cpc","alr","cme","ecc","crs","ssi","aac","cbd","rfp","sle","scr","pdb","svc","dcp","pte","ors","cps","fte","stl","gsa","otc","ssa","itu","mpi","mps","nwt","ths","hgh","oss","wmv","mgm","csa","nrc","chr","scm","fno","spd","adc","ubc","csu","fsa","xiv","sgd","ftd","smb","bse","itk","kms","thn","kpx","spp","mfc","nmr","mso","htm","dhs","msu","fsb","cns","omb","cpl","sbs","swf","ipb","tsn","bdd","csc","gln","stp","avr","cts","wmd","cfs","ffi","tcm","prc","afc","srl","thx","xvi","ttl","bmp","dss","ssk","dsm","spc","pcg","snp","adm","snr","pps","ntp","opp","lps","pdp","gpo","cpp","crn","mmf","rtf","bmc","csr","dvb","cdp","mev","sdn","mta","esd","gnd","osu","utp","jpy","ccm","bmg","jbl","pcm","dtd","hpa","pvt","atp","tec","doi","dsp","dll","iss","cmp","ich","sbc","dei","gsm","buf","pts","sst","teh","acct","adsl","cdrw","cdma","dmoz","divx","embl","exif","hklm","incl","msdn","mpls","ngos","staa","uefa","undp","wolverhampton","commentsblog","verzeichnis","viewpicture","christchurch","oscommerce","viewsonic","ret","xtc","addr","attr","ostg","xnxx","xxxx","xvid","xslt","xiii","yyyy","devel","endif","fomit","bizkit","bibtex","fulfil","xenical","zoofilia","gcse","engl","mgmt","odbc","wwii","sublimedirectory","registerregister","starsmerchant","powerseller","websphere","smugmug","xpress","xtreme","xemacs","webmin","zshops","xoops","vioxx","adp","adr","aff","afl","eia","fpo","gst","isd","tdk","astm","auch","caa","hipaa","sgi","mcsg","mcse","sgml","msgid","secsg","msgstr","newsgator"],"wordIndex":799,"minlen":3,"maxlen":17};
/* END */
(function(){
window.Note.save = saveData
window.Note.load = loadData
window.Note.autoSave = autoSave
function getNoteModule(){
if(!window['Note']) window.Note = {}
return window.Note
}
function loadData(){
let note = getNoteModule()
if(!inframe){
try{
let savedata = localStorage.getItem(datakey)
if(savedata && savedata.length){
note.data = JSON.parse(savedata)
}
window.addEventListener("message", onMessage)
} catch(e){
console.log("No local data")
console.log(e)
}
} else {
return note.data
}
}
let firstLogCall = true
let originalLogFunc = console.log
function log(x, ...rest){
if(firstLogCall)
document.body.appendChild(document.createElement("hr"))
else
document.body.appendChild(document.createElement("br"))
document.body.appendChild(
document.createTextNode(x + " " + rest.join(" ")))
firstLogCall = false
originalLogFunc(x, ...rest)
}
console.log = log
let SaveInterval = 500
window.addEventListener("load", ()=>{
convertMarkdown()
autoSave()
loadData() // dont wait for async
})
let saveIntervalRef = null
function autoSave(enable){
if(enable === undefined) enable = true
clearInterval(saveIntervalRef)
if(enable){
saveIntervalRef = window.setInterval(saveData, SaveInterval)
}
}
// this is preferred over a 'localstorage' polyfill for a frame,
// so the programmer doesn't assume this is the browsers localstorage
function saveData(){
let note = getNoteModule()
if(inframe){
let msg_obj = {
action: "saveData",
data: JSON.stringify(note['data'])
}
let message = JSON.stringify(msg_obj)
window.parent.postMessage(message)
} else {
localStorage.setItem(datakey, JSON.stringify(note['data']))
}
}
let md_subs = [
/(\n|^)\s*######\s([^\s#].*)\n*/g, "\n<h6 id=\"$2\">$2</h6>\n",
/(\n|^)\s*#####\s([^\s#].*)\n*/g, "\n<h5 id=\"$2\">$2</h5>\n",
/(\n|^)\s*####\s*([^\s#].*)\n*/g, "\n<h4 id=\"$2\">$2</h4>\n",
/(\n|^)\s*###\s*([^\s#].*)\n*/g, "\n<h3 id=\"$2\">$2</h3>\n",
/(\n|^)\s*##\s*([^\s#].*)\n*/g, "\n<h2 id=\"$2\">$2</h2>\n",
/(\n|^)\s*#\s*([^\s#].*)\n*/g, "\n<h1 id=\"$2\">$2</h1>\n",
/\n(\s*)[\*\-](.*)/g, '\n<ul><li>$2</li></ul>',
/\n+\n(?=[^#\n])/g, "\n\n<br><br>",
/\n+\n/g, "\n",
/__([^_\n]*)__/g, "<b>$1</b>",
/\*\*([^_\n]*)\*\*/g, "<b>$1</b>",
/_([^_\n]*)_/g, "<i>$1</i>",
/\*([^_\n]*)\*/g, "<i>$1</i>",
/\!\[([^\]\n]*)\]\(([^\)\n]*)\)/g, "<img src=\"$2\" alt=\"$1\"></img>",
/\[([^\]\n]*)\]\(([^\)\n]*)\)/g, "<a href=\"$2\" target=\"_blank\">$1</a>",
]
function onMessage(){
try{
let message = JSON.parse(e.data)
// console.log('received message', message)
if(message.hasOwnProperty("event")){
if(message.event == "keydown" && typeof keydown != "undefined"){
keydown(message)
}
if(message.event == "keyup" && typeof keyup != "undefined"){
keydown(message)
}
}
} catch(e){
console.warn("error processing message: " + e.data)
}
}
function convertMarkdown(){
let containers = document.getElementsByClassName("markdown-src")
for(let j=0; j<containers.length; ++j){
let container = containers[j]
let src = container.innerHTML
for(var i=0; i<md_subs.length-1; i += 2){
var search = md_subs[i]
var replace = md_subs[i+1]
src = src.replace(search, replace)
}
container.innerHTML = src
}
}
})()
//window.addEventListener('load', htmlNotesMainFunc)
//function htmlNotesMainFunc(){
/* JS */
let data = Note.data
let temp = {}
let maxlist = 50*1000
window.addEventListener('load', main)
async function loadDict(){
let url = id('dicturl_input').value
let text = await (await fetch(url)).text()
// console.info('load dictionary', text)
if(text){
temp.dictionary = text
updateWords()
}
update()
}
function unexcludeWord(word){
let index = data.exclude.indexOf(word)
if(index >= 0){
data.exclude.splice(index, 1)
temp.dictionary += ' ' + word
if(temp.words.indexOf(word) == -1){
temp.words.push(word)
}
}
update()
}
function excludeWord(word){
let index = data.exclude.push(word)
update()
}
function updateWords(){
let min = data.minlen = parseInt(id('minlen').value)
let max = data.maxlen = parseInt(id('maxlen').value)
if(max < min){
max = min
id('maxlen').value = max
}
temp.words = temp.dictionary.split(/\s+/).filter(wordFilter)
update()
}
function main(){
if(data.hasOwnProperty('minlen'))
id('minlen').value = "" + data.minlen
if(data.hasOwnProperty('maxlen'))
id('maxlen').value = "" + data.maxlen
init()
window.addEventListener('keydown', keydown)
}
async function init(){
if(!data.hasOwnProperty('exclude')) data.exclude = []
if(!data.hasOwnProperty('minlen')) data.minlen = 2
if(!data.hasOwnProperty('maxlen')) data.maxlen = 5
if(!data.hasOwnProperty('wordIndex')) data.wordIndex = 0
if(!temp.dictionary)
temp.dictionary = "a from look say time about get make see"
if(id('dicturl_input').value.length > 0){
await loadDict()
}
updateWords()
}
function text(_id, _text){
id(_id).innerHTML = ''
id(_id).appendChild(document.createTextNode(_text))
}
function html(_id, _html){
id(_id).innerHTML = _html
}
function update(skiplists){
if(temp.words && temp.words.length > 0 && data.wordIndex >= temp.words.length){
console.trace('updating wordIndex', data.wordIndex)
data.wordIndex = (temp.words ?? [0]).length - 1
console.trace('updated wordIndex', data.wordIndex)}
if(!skiplists){
html('excludelist', excludeListTemplate())
html('includelist', includeListTemplate())
}
text('wordindex', data.wordIndex + 1)
text('wordchecker', temp.words[data.wordIndex])
}
function sortLenAlpha(a, b){
if(a.length == b.length)
return a < b? -1 : 1
return a.length - b.length
}
function includeListTemplate(){
let src = ""
let include = temp.words.filter(wordFilter)
include = include.sort(sortLenAlpha)
if(include.length > maxlist){
include = include.slice(0, maxlist)}
include = include.filter(x=>data.exclude.indexOf(x) == -1)
for(let i=0; i<include.length; ++i){
let word = include[i]
if(data.exclude.indexOf(word) != -1) continue
src += ` <span onclick='excludeWord("${word}")'
style="text-decoration: underline; cursor: pointer;">${word}</span>`
}
return src
}
function excludeListTemplate(){
let src = ""
let exclude = data.exclude.toSorted(sortLenAlpha)
for(let i=0; i<exclude.length; ++i){
let word = exclude[i]
src += ` <span onclick='unexcludeWord("${word}")'
style="text-decoration: underline; cursor: pointer;">${word}</span>`
}
return src
}
function prev(){
nextWord(true)
}
function nextWord(back){
let {words} = temp
if(!words.length) return
for(let i=0; Math.abs(i)!=words.length-1; back? --i : ++i){
if(back? --data.wordIndex < 0 : ++data.wordIndex >= words.length){
data.wordIndex = back? 0: words.length - 1 }
if(data.exclude.indexOf(words[data.wordIndex]) < 0){
break}
}
update('skiplists')
}
function accept(){
nextWord()
}
function wordFilter(word){
let min = parseInt(id('minlen').value)
let max = parseInt(id('maxlen').value)
if(max < min){
max = min
id('maxlen').value = max
}
if(word.length < min || word.length > max) return false
return true
}
function reject(){
data.exclude.push(temp.words[data.wordIndex])
nextWord()
}
function copyExclude(){
let text = data.exclude.join(' ')
if(navigator.clipboard){
navigator.clipboard.writeText(text)
}
}
function copyInclude(){
let include = temp.words.filter(wordFilter)
include = include.filter(x=>data.exclude.indexOf(x) == -1)
let text = include.join(' ')
if(navigator.clipboard){
navigator.clipboard.writeText(text)
}
}
function keydown(e){
let k = e.key
if(k == 'ArrowRight'){
accept()
}
if(k == 'Enter'){
reject()
}
if(k == "ArrowLeft"){
prev()
}
}
function id(x){
return document.getElementById(x)
}
/* END */
//}
</script>
</body>
<html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment