Download index.html from aitrainingdatabroker/pii-pattern-scanner: direct link, hf CLI and curl.
- Browser
- Download file 5.25 kB
-
https://huggingface.co/spaces/aitrainingdatabroker/pii-pattern-scanner/resolve/main/index.html
- Command line
-
hf download hf://spaces/aitrainingdatabroker/pii-pattern-scanner/index.html
-
curl -L -o index.html https://huggingface.co/spaces/aitrainingdatabroker/pii-pattern-scanner/resolve/main/index.html
5.25 kB
| <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>PII Pattern Scanner</title><meta name="description" content="Paste text to highlight patterns that look like personal or secret details. It only finds patterns; names and free-form details need a model or a person."><style> | |
| :root{--navy:#14213d;--yellow:#f5c518;--ink:#1d2433;--muted:#5b6475;--line:#d9dde5;--bg:#fff;--soft:#f4f6f9} | |
| @media (prefers-color-scheme:dark){:root{--ink:#e8ebf2;--muted:#9aa3b5;--line:#2c3547;--bg:#10151f;--soft:#182030}} | |
| *{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:16px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif} | |
| main{max-width:860px;margin:0 auto;padding:28px 16px 48px}h1{margin:0 0 6px;font-size:1.7rem}h2{font-size:1.1rem;margin:22px 0 8px} | |
| p{margin:0 0 12px}.note{color:var(--muted);font-size:.95rem}label{display:block;font-weight:600;margin:16px 0 6px} | |
| input,select,textarea{width:100%;padding:10px;border:1px solid var(--line);border-radius:6px;font:inherit;background:var(--bg);color:var(--ink)} | |
| textarea{min-height:140px;resize:vertical}input:focus,select:focus,textarea:focus,button:focus-visible{outline:3px solid var(--yellow);outline-offset:1px} | |
| button{font:inherit;border:1px solid var(--ink);border-radius:6px;padding:8px 14px;cursor:pointer;background:var(--bg);color:var(--ink)} | |
| button.primary{background:var(--navy);color:#fff;border-color:var(--navy)} | |
| .cols{display:grid;grid-template-columns:1fr 1fr;gap:14px}@media (max-width:640px){.cols{grid-template-columns:1fr}} | |
| .card{background:var(--soft);border:1px solid var(--line);border-radius:8px;padding:12px 14px;margin:0 0 10px}.card b{display:block} | |
| .tag{display:inline-block;font-size:.8rem;border:1px solid var(--line);border-radius:99px;padding:1px 8px;margin-right:6px;color:var(--muted)} | |
| mark{background:var(--yellow);color:#14213d;border-radius:3px;padding:0 2px}.out{white-space:pre-wrap;word-wrap:anywhere} | |
| .links{margin-top:28px;padding-top:14px;border-top:1px solid var(--line)}.links a{display:block;margin:4px 0} | |
| a{color:#1d4ed8}@media (prefers-color-scheme:dark){a{color:#8ab4ff}}footer{margin-top:24px;color:var(--muted);font-size:.9rem} | |
| </style></head> | |
| <body><main> | |
| <h1>PII Pattern Scanner</h1> | |
| <p class="note">Paste text to highlight patterns that look like personal or secret details. It only finds patterns; names and free-form details need a model or a person. Runs in your browser; what you type is not sent anywhere.</p> | |
| <label for="t">Text</label><textarea id="t"></textarea><p><button class="primary" id="b">Scan</button> <button id="c">Mask matches</button></p><div id="o"></div> | |
| <div class="links"><b>Read more on AITrainingDataBroker.com</b><a href="https://aitrainingdatabroker.com/data/team-chat/?utm_source=huggingface&utm_medium=space&utm_campaign=pii-pattern-scanner" rel="noopener">Can you license team chat to AI companies?</a><a href="https://aitrainingdatabroker.com/data/quickbooks-data-export/?utm_source=huggingface&utm_medium=space&utm_campaign=pii-pattern-scanner" rel="noopener">QuickBooks data export for AI licensing</a><a href="https://aitrainingdatabroker.com/de-identification/?utm_source=huggingface&utm_medium=space&utm_campaign=pii-pattern-scanner" rel="noopener">De-identification checklists</a></div> | |
| <footer>By <a href="https://aitrainingdatabroker.com/?utm_source=huggingface&utm_medium=space&utm_campaign=pii-pattern-scanner" rel="noopener">AI Training Data Broker</a>. General information, not legal advice and not a certification.</footer> | |
| </main> | |
| <script> | |
| const esc = s => String(s).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); | |
| const P=[['EMAIL',/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi],['PHONE',/(?:\+?\d{1,2}[ .-]?)?(?:\(\d{3}\)|\d{3})[ .-]?\d{3}[ .-]?\d{4}/g],['SSN_LIKE',/\b\d{3}-\d{2}-\d{4}\b/g], | |
| ['IP_ADDRESS',/\b(?:\d{1,3}\.){3}\d{1,3}\b/g],['KEY_LIKE',/\b(?:sk|pk|key|token|demo_key)[_-][A-Za-z0-9_-]{12,}\b/g],['CARD_LIKE',/\b(?:\d[ -]?){13,19}\b/g]]; | |
| function luhn(s){const d=s.replace(/\D/g,'');if(d.length<13||d.length>19)return false;let t=0,a=false;for(let i=d.length-1;i>=0;i--){let n=+d[i];if(a){n*=2;if(n>9)n-=9}t+=n;a=!a}return t%10===0} | |
| function find(t){const f=[];for(const [k,re] of P){for(const m of t.matchAll(re)){if(k==='CARD_LIKE'&&!luhn(m[0]))continue;f.push({k,s:m.index,e:m.index+m[0].length})}} | |
| f.sort((a,b)=>a.s-b.s||b.e-a.e);const o=[];let end=-1;for(const x of f){if(x.s>=end){o.push(x);end=x.e}}return o} | |
| function render(mask){const t=document.getElementById('t').value;const f=find(t);let out='',p=0; | |
| for(const x of f){out+=esc(t.slice(p,x.s))+(mask?`<mark>[${x.k}]</mark>`:`<mark title="${x.k}">${esc(t.slice(x.s,x.e))}</mark>`);p=x.e}out+=esc(t.slice(p)); | |
| const c={};f.forEach(x=>c[x.k]=(c[x.k]||0)+1);document.getElementById('o').innerHTML=`<div class="card out">${out||'Nothing pasted.'}</div><p>${f.length?Object.entries(c).map(([k,v])=>`<span class="tag">${k} ${v}</span>`).join(''):'No pattern matched. Names and free-form details are not covered.'}</p>`} | |
| document.getElementById('b').onclick=()=>render(false);document.getElementById('c').onclick=()=>render(true); | |
| </script></body></html> | |