try-grammar / index.html
Imperatore's picture
Try Proofbird Grammar: the five models running in the browser (ONNX Runtime Web + a JS port of quickstart.py)
d7da9d3 verified
Raw History Blame Contribute Delete
7.11 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Try Proofbird Grammar</title>
<meta name="description" content="Proofbird's on-device grammar models (English, Italian, Spanish, French, German) running in your browser. Your text never leaves your computer.">
<link rel="icon" type="image/svg+xml" href="mark.svg">
<style>
:root { --violet: #534AB7; --violet-ink: #3C3489; --violet-tint: #EEEDFE; --violet-line: #AFA9EC; --mark: #7F77DD;
--bg: #F4F3EF; --card: #FFFFFF; --soft: #F4F3EF; --text: #1F2328; --text-2: #5F5E5A; --muted: #888780;
--line: rgba(0,0,0,.12); --line-2: rgba(0,0,0,.2); --danger: #A32D2D; }
@media (prefers-color-scheme: dark) { :root { --violet-ink: #CECBF6; --violet-tint: #26215C; --violet-line: #534AB7;
--bg: #161616; --card: #1F1F1E; --soft: #2A2A28; --text: #ECEBE6; --text-2: #B4B2A9; --muted: #888780;
--line: rgba(255,255,255,.12); --line-2: rgba(255,255,255,.22); --danger: #F09595; } }
* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); color: var(--text); font: 16px/1.6 "Segoe UI", system-ui, -apple-system, sans-serif; }
main { max-width: 760px; margin: 0 auto; padding: 24px 16px 40px; }
.card { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 20px 24px; }
.head { display: flex; align-items: center; gap: 12px; margin-bottom: 4px; }
.logo { width: 38px; height: 38px; border-radius: 9px; background: var(--violet); color: #fff; display: flex; align-items: center; justify-content: center; flex: none; }
.logo svg { width: 28px; height: 28px; }
h1 { font-size: 19px; font-weight: 600; margin: 0; }
.sub { margin: 0; font-size: 13px; color: var(--text-2); }
.langs { display: flex; flex-wrap: wrap; gap: 6px; margin: 18px 0 12px; }
.lang { font: inherit; font-size: 13px; padding: 5px 12px; border-radius: 8px; border: 1px solid var(--line-2); background: transparent; color: var(--text-2); cursor: pointer; }
.lang[aria-pressed="true"] { background: var(--violet-tint); color: var(--violet-ink); border-color: var(--violet-line); }
.dl { background: var(--soft); border-radius: 8px; padding: 10px 12px; margin-bottom: 12px; }
.dl-row { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; color: var(--text-2); margin-bottom: 6px; }
.bar { height: 6px; background: var(--line); border-radius: 3px; overflow: hidden; }
.bar > div { height: 6px; width: 0; background: var(--violet); border-radius: 3px; transition: width .2s; }
.dl p { margin: 6px 0 0; font-size: 12px; color: var(--muted); }
textarea { width: 100%; min-height: 84px; font: inherit; font-size: 15px; line-height: 1.6; color: var(--text); background: var(--card); border: 1px solid var(--line-2); border-radius: 8px; padding: 10px 12px; resize: vertical; }
textarea:focus { outline: 2px solid var(--violet-line); outline-offset: 0; }
.row { display: flex; align-items: center; gap: 8px; margin: 8px 0 18px; flex-wrap: wrap; }
.try { font-size: 12px; color: var(--muted); }
.chip { font: inherit; font-size: 12px; padding: 3px 8px; border-radius: 8px; background: var(--soft); color: var(--text-2); border: 0; cursor: pointer; }
.grow { flex: 1; }
.check { font: inherit; font-size: 14px; padding: 7px 18px; border-radius: 8px; border: 0; background: var(--violet); color: #fff; cursor: pointer; }
.check:disabled { opacity: .6; cursor: progress; }
.err { color: var(--danger); font-size: 13px; margin: -10px 0 14px; }
.meta { margin: 0 0 6px; font-size: 13px; color: var(--text-2); }
.result { background: var(--soft); border-radius: 8px; padding: 12px 14px; font-size: 15px; line-height: 1.9; white-space: pre-wrap; }
.ch { border-bottom: 2px solid var(--mark); color: var(--violet-ink); background: var(--violet-tint); padding: 0 2px; border-radius: 3px; }
.sugs { margin: 10px 0 14px; }
.sug { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 14px; flex-wrap: wrap; }
.sug:last-child { border-bottom: 0; }
.old { color: var(--muted); text-decoration: line-through; }
.new { font-weight: 600; }
.tag { margin-left: auto; font-size: 12px; color: var(--muted); font-family: ui-monospace, Consolas, monospace; }
details { border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; margin-bottom: 14px; }
summary { font-size: 14px; font-weight: 600; cursor: pointer; }
.pass { font-size: 12px; color: var(--text-2); margin: 10px 0 4px; }
.ptab { display: grid; grid-template-columns: 1.2fr .8fr 2fr .8fr; gap: 2px 10px; font-size: 12px; color: var(--text-2); }
.ptab .h { color: var(--muted); }
.ptab .e { color: var(--violet-ink); font-family: ui-monospace, Consolas, monospace; }
.foot { margin: 0; font-size: 12px; color: var(--muted); line-height: 1.6; }
.foot a { color: var(--text-2); }
[hidden] { display: none !important; }
</style>
</head>
<body>
<main>
<div class="card">
<div class="head">
<div class="logo" aria-hidden="true">
<svg viewBox="0 0 100 100" fill="currentColor"><polyline points="12,60 34,82 60,48" fill="none" stroke="currentColor" stroke-width="13" stroke-linecap="round" stroke-linejoin="round"/><path fill-rule="evenodd" d="M49 36 a19 19 0 1 0 38 0 a19 19 0 1 0 -38 0 Z M69.5 31 a3.5 3.5 0 1 0 7 0 a3.5 3.5 0 1 0 -7 0 Z"/><polygon points="84,31 99,36 84,42"/></svg>
</div>
<div>
<h1>Proofbird grammar, in your browser</h1>
<p class="sub">The model runs on this page. Your text never leaves your computer.</p>
</div>
</div>
<div class="langs" id="langs" role="group" aria-label="Language"></div>
<div class="dl" id="dl" hidden>
<div class="dl-row"><span id="dl-label">Downloading the model, once</span><span id="dl-count"></span></div>
<div class="bar"><div id="dl-bar"></div></div>
<p>Kept by your browser afterwards, so the next check starts at once.</p>
</div>
<textarea id="text" spellcheck="false" aria-label="Text to check"></textarea>
<div class="row">
<span class="try">Try:</span>
<span id="chips"></span>
<span class="grow"></span>
<button class="check" id="check">Check</button>
</div>
<p class="err" id="err" hidden></p>
<div id="out" hidden>
<p class="meta" id="meta"></p>
<div class="result" id="result"></div>
<div class="sugs" id="sugs"></div>
<details id="steps">
<summary>How the model got there, pass by pass</summary>
<div id="passes"></div>
</details>
</div>
<p class="foot">This is the model on its own, as in <code>quickstart.py</code>. The <a href="https://proofbird.app" target="_blank" rel="noopener">Proofbird</a> app adds guards, a spell checker and an explanation for each change.
<a id="card" href="https://huggingface.co/proofbird" target="_blank" rel="noopener">Model card</a> · <span id="licence">Apache-2.0</span> · <a href="https://proofbird.app" target="_blank" rel="noopener">proofbird.app</a></p>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/ort.min.js"></script>
<script type="module" src="app.js"></script>
</body>
</html>