/install takes a reader from three bare Ubuntu machines to a first answer: what each machine needs and the commands that check it, the release fetched and its checksum checked, the eight setup screens, the system's state and the console, and a first request with a key from the account page. Every screen is from an install of v0.14.9 on three fresh VMs, recorded with tmux and kept as terminal frames: the page shows them as text, and plays a session back when asked, fetching it compressed from /install/cast/. The administrator's password and the API key were masked before the recording was kept, and a test fails if either shape reaches the page. /about gains what llmgw now does beyond routing, and its install steps are today's: the setup screens and node add, not onboard-node.sh and a model file, with a link into the guide. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
340 lines
18 KiB
HTML
340 lines
18 KiB
HTML
{{define "about"}}{{if not .Site}}<!doctype html>
|
||
<html lang="{{lang}}"><head>
|
||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<meta name="description" content="{{t "about.meta.description"}}">
|
||
{{end}}<title>llmgw</title>
|
||
{{template "sitestyle" .}}
|
||
{{if not .Site}}</head><body>{{end}}
|
||
|
||
<div class="wrap">
|
||
<header class="bar">
|
||
<a class="mark" href="#top" aria-label="{{t "about.home_label"}}">
|
||
<svg width="26" height="26" viewBox="0 0 26 26" aria-hidden="true">
|
||
<rect x="1" y="1" width="24" height="24" rx="6" fill="none" stroke="currentColor" stroke-width="2"/>
|
||
<path d="M7 9h12M7 13h12M7 17h12" stroke="var(--fiber)" stroke-width="2" stroke-linecap="round"/>
|
||
</svg>
|
||
llmgw
|
||
</a>
|
||
<nav aria-label="{{t "about.nav.label"}}">
|
||
<a href="#what">{{t "about.nav.what"}}</a>
|
||
<a href="#fabrics">{{t "about.nav.fabrics"}}</a>
|
||
<a href="#install">{{t "about.nav.install"}}</a>
|
||
<a href="#proxy">{{t "about.nav.proxy"}}</a>
|
||
<a href="#download">{{t "about.nav.download"}}</a>
|
||
<a href="https://gitea.mynodes.xyz/ilker/llmgw">{{t "about.nav.source"}}</a>
|
||
{{if not .Site}}<a href="/">{{t "about.nav.gateway"}}</a>{{end}}
|
||
</nav>
|
||
</header>
|
||
|
||
<div class="hero" id="top">
|
||
<div>
|
||
<p class="eyebrow">{{t "about.hero.eyebrow" .Version}}</p>
|
||
<h1 style="margin-top:14px">{{th "about.hero.title"}}</h1>
|
||
<p class="lede">{{t "about.hero.lede"}}</p>
|
||
<div class="cta">
|
||
<a class="btn" href="#download">{{t "about.hero.download"}}{{with .Release}} {{.}}{{end}}</a>
|
||
<a class="btn ghost" href="{{.InstallURL}}">{{t "about.hero.guide"}}</a>
|
||
</div>
|
||
<div class="oneline" aria-label="{{t "about.hero.oneline_label"}}">
|
||
<code><span class="p">$ </span>sudo llmgw server init --admin you@example.com</code>
|
||
<button class="copy" style="position:static" data-copy="sudo llmgw server init --admin you@example.com" type="button">{{t "about.copy"}}</button>
|
||
</div>
|
||
</div>
|
||
|
||
<figure class="schem">
|
||
<svg viewBox="0 0 440 250" role="img" aria-labelledby="schem-t">
|
||
<title id="schem-t">{{t "about.schem.title"}}</title>
|
||
<!-- clients -->
|
||
<g>
|
||
<rect class="s-box" x="4" y="58" width="92" height="30" rx="6"/>
|
||
<text class="s-label" x="50" y="77" text-anchor="middle" translate="no">openai sdk</text>
|
||
<rect class="s-box" x="4" y="110" width="92" height="30" rx="6"/>
|
||
<text class="s-label" x="50" y="129" text-anchor="middle">{{t "about.schem.editor"}}</text>
|
||
<rect class="s-box" x="4" y="162" width="92" height="30" rx="6"/>
|
||
<text class="s-label" x="50" y="181" text-anchor="middle" translate="no">curl</text>
|
||
</g>
|
||
<path id="c1" class="s-link" d="M96 73 C130 73 130 118 160 118"/>
|
||
<path id="c2" class="s-link" d="M96 125 H160"/>
|
||
<path id="c3" class="s-link" d="M96 177 C130 177 130 132 160 132"/>
|
||
<!-- gateway -->
|
||
<rect class="s-gw" x="160" y="96" width="84" height="58" rx="8"/>
|
||
<text class="s-strong" x="202" y="122" text-anchor="middle">llmgw</text>
|
||
<text class="s-label" x="202" y="139" text-anchor="middle">:8080</text>
|
||
<path id="fa" class="s-link" d="M244 114 C272 114 272 62 300 62"/>
|
||
<path id="fb" class="s-link" d="M244 136 C272 136 272 188 300 188"/>
|
||
<!-- fabric a -->
|
||
<rect class="s-fab" x="300" y="14" width="136" height="98" rx="10"/>
|
||
<text class="s-label" x="312" y="32" translate="no">nvl72 · gb200</text>
|
||
<g transform="translate(312 42)">
|
||
<rect class="s-gpu-a" width="22" height="22" rx="3"/><rect class="s-gpu-a" x="28" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-a" x="56" width="22" height="22" rx="3"/><rect class="s-gpu-a" x="84" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-a" y="28" width="22" height="22" rx="3"/><rect class="s-gpu-a" x="28" y="28" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-idle" x="56" y="28" width="22" height="22" rx="3"/><rect class="s-gpu-idle" x="84" y="28" width="22" height="22" rx="3"/>
|
||
</g>
|
||
<!-- fabric b -->
|
||
<rect class="s-fab" x="300" y="138" width="136" height="98" rx="10"/>
|
||
<text class="s-label" x="312" y="156" translate="no">ib-b · h100-80g</text>
|
||
<g transform="translate(312 166)">
|
||
<rect class="s-gpu-b" width="22" height="22" rx="3"/><rect class="s-gpu-b" x="28" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-idle" x="56" width="22" height="22" rx="3"/><rect class="s-gpu-idle" x="84" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-idle" y="28" width="22" height="22" rx="3"/><rect class="s-gpu-idle" x="28" y="28" width="22" height="22" rx="3"/>
|
||
<rect class="s-gpu-idle" x="56" y="28" width="22" height="22" rx="3"/><rect class="s-gpu-idle" x="84" y="28" width="22" height="22" rx="3"/>
|
||
</g>
|
||
<!-- requests in flight -->
|
||
<circle class="pulse" r="4"><animateMotion dur="2.4s" repeatCount="indefinite"><mpath href="#c1"/></animateMotion></circle>
|
||
<circle class="pulse" r="4"><animateMotion dur="2.4s" begin="0.8s" repeatCount="indefinite"><mpath href="#c2"/></animateMotion></circle>
|
||
<circle class="pulse" r="4"><animateMotion dur="2.4s" begin="1.6s" repeatCount="indefinite"><mpath href="#c3"/></animateMotion></circle>
|
||
<circle class="pulse" r="4"><animateMotion dur="2.4s" begin="1.2s" repeatCount="indefinite"><mpath href="#fa"/></animateMotion></circle>
|
||
<circle class="pulse b" r="4"><animateMotion dur="2.4s" begin="2s" repeatCount="indefinite"><mpath href="#fb"/></animateMotion></circle>
|
||
</svg>
|
||
<figcaption>{{t "about.schem.caption"}}</figcaption>
|
||
</figure>
|
||
</div>
|
||
|
||
<section id="what">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.what.title"}}</h2>
|
||
<p class="intro">{{t "about.what.intro"}}</p>
|
||
</div>
|
||
<div class="facts">
|
||
<div class="fact"><h3>{{t "about.what.api.title"}}</h3>
|
||
<p>{{th "about.what.api.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.placement.title"}}</h3>
|
||
<p>{{t "about.what.placement.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.ondemand.title"}}</h3>
|
||
<p>{{t "about.what.ondemand.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.keys.title"}}</h3>
|
||
<p>{{t "about.what.keys.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.editors.title"}}</h3>
|
||
<p>{{t "about.what.editors.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.chat.title"}}</h3>
|
||
<p>{{t "about.what.chat.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.mirror.title"}}</h3>
|
||
<p>{{t "about.what.mirror.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.engines.title"}}</h3>
|
||
<p>{{t "about.what.engines.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.upgrades.title"}}</h3>
|
||
<p>{{t "about.what.upgrades.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.dashboard.title"}}</h3>
|
||
<p>{{th "about.what.dashboard.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.knowledge.title"}}</h3>
|
||
<p>{{th "about.what.knowledge.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.guard.title"}}</h3>
|
||
<p>{{t "about.what.guard.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.signin.title"}}</h3>
|
||
<p>{{t "about.what.signin.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.ha.title"}}</h3>
|
||
<p>{{t "about.what.ha.text"}}</p></div>
|
||
<div class="fact"><h3>{{t "about.what.media.title"}}</h3>
|
||
<p>{{t "about.what.media.text"}}</p></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="fabrics">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.fabrics.title"}}</h2>
|
||
<p class="intro">{{t "about.fabrics.intro"}}</p>
|
||
<p class="intro"><a href="https://gitea.mynodes.xyz/ilker/llmgw/src/branch/main/docs/fabrics.md">{{t "about.fabrics.guide"}}</a></p>
|
||
</div>
|
||
<div class="fab-grid">
|
||
<div class="order" aria-label="{{t "about.fabrics.order_label"}}">
|
||
<div><b>1</b><h3>{{t "about.fabrics.nvlink.title"}}</h3><p>{{th "about.fabrics.nvlink.text"}}</p></div>
|
||
<div><b>2</b><h3>{{t "about.fabrics.ib.title"}}</h3><p>{{t "about.fabrics.ib.text"}}</p></div>
|
||
<div><b class="x">×</b><h3>{{t "about.fabrics.never.title"}}</h3><p>{{t "about.fabrics.never.text"}}</p></div>
|
||
</div>
|
||
<div>
|
||
<h3>{{t "about.fabrics.doctor"}}</h3>
|
||
<div class="term" aria-label="{{t "about.fabrics.doctor_label"}}"><pre>$ sudo llmgw doctor
|
||
<span class="fail">FAIL</span> nvlink this machine has NVSwitch but nvidia-fabricmanager is inactive
|
||
<span class="dim">→ systemctl enable --now nvidia-fabricmanager</span>
|
||
<span class="warn">WARN</span> fabric nvidia_peermem is not loaded: GPUDirect RDMA is off
|
||
<span class="dim">→ modprobe nvidia_peermem</span>
|
||
<span class="ok">OK</span> gpu 8 GPUs: 8× NVIDIA H100 80GB HBM3
|
||
<span class="ok">OK</span> nvlink NVLink groups: [0 1 2 3 4 5 6 7]
|
||
<span class="ok">OK</span> fabric mlx5_0/1 ACTIVE at 400 Gb/s (InfiniBand), subnet manager 0x248a07030030f0c0
|
||
<span class="ok">OK</span> fabric subnet managers: 0x…f0c0 (master, priority 15), 0x…f1d4 (standby, priority 14)
|
||
<span class="ok">OK</span> agent NCCL bootstraps over ens3 (10.1.0.21)</pre></div>
|
||
</div>
|
||
<ul class="watch">
|
||
<li><strong>{{t "about.fabrics.sm.title"}}</strong>{{t "about.fabrics.sm.text"}}</li>
|
||
<li><strong>{{t "about.fabrics.map.title"}}</strong>{{th "about.fabrics.map.text"}}</li>
|
||
<li><strong>{{t "about.fabrics.racks.title"}}</strong>{{th "about.fabrics.racks.text"}}</li>
|
||
<li><strong>{{t "about.fabrics.ports.title"}}</strong>{{t "about.fabrics.ports.text"}}</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="install">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.install.title"}}</h2>
|
||
<p class="intro">{{t "about.install.intro"}}</p>
|
||
<p class="intro">{{th "about.install.guide" .InstallURL}}</p>
|
||
<p class="cta" style="margin-top:18px"><a class="btn" href="{{.InstallURL}}">{{t "about.install.cta"}} →</a></p>
|
||
</div>
|
||
<ol class="steps">
|
||
<li>
|
||
<h3>{{t "about.install.binary.title"}}</h3>
|
||
<p>{{t "about.install.binary.text"}}</p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>VERSION={{or .Release "vX.Y.Z"}}{{if not .Release}} <span class="c"># from the releases page</span>{{end}}
|
||
U=https://gitea.mynodes.xyz/ilker/llmgw/releases/download/$VERSION
|
||
curl -fsSLO $U/llmgw-$VERSION-linux-amd64
|
||
curl -fsSL $U/checksums.txt | sha256sum -c --ignore-missing
|
||
sudo install -m0755 llmgw-$VERSION-linux-amd64 /usr/local/bin/llmgw</code></pre></div>
|
||
</li>
|
||
<li>
|
||
<h3>{{t "about.install.server.title"}}</h3>
|
||
<p>{{th "about.install.server.text"}}</p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>sudo llmgw</code></pre></div>
|
||
<a href="{{.InstallURL}}#setup" style="text-decoration:none"><div class="term" aria-label="{{t "install.tty_label"}}"><pre translate="no" style="font-size:clamp(4px,.62vw,.5rem);line-height:1.25">{{.Still "setup-checks"}}</pre></div></a>
|
||
</li>
|
||
<li>
|
||
<h3>{{t "about.install.node.title"}}</h3>
|
||
<p>{{th "about.install.node.text"}}</p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>sudo llmgw node add ubuntu@10.0.0.21 --fabric ib-a:mlx5_0,mlx5_1</code></pre></div>
|
||
<div class="term" aria-label="{{t "about.install.node.output_label"}}"><pre>$ llmgw ctl nodes
|
||
NODE STATE GPUS MEM CLASSES FABRICS REPLICAS LAST SEEN
|
||
gpu01 <span class="ok">ready</span> 8/8 free 503G h100-80g ib-a 0 2s</pre></div>
|
||
</li>
|
||
<li>
|
||
<h3>{{t "about.install.model.title"}}</h3>
|
||
<p>{{th "about.install.model.text"}}</p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>curl https://llm.example.com/v1/chat/completions \
|
||
-H "Authorization: Bearer $LLMGW_API_KEY" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"model": "coder", "messages": [{"role": "user", "content": "hello"}]}'</code></pre></div>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="proxy">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.proxy.title"}}</h2>
|
||
<p class="intro">{{t "about.proxy.intro"}}</p>
|
||
<p class="intro">{{th "about.proxy.loopback"}}</p>
|
||
</div>
|
||
<div class="tabs">
|
||
<input type="radio" name="proxy" id="t-caddy" checked>
|
||
<input type="radio" name="proxy" id="t-nginx">
|
||
<div class="tablist" role="presentation" translate="no">
|
||
<label for="t-caddy">Caddy</label>
|
||
<label for="t-nginx">nginx</label>
|
||
</div>
|
||
<div class="panel p-caddy">
|
||
<p class="meta"><span>{{th "about.proxy.caddy"}}</span>
|
||
<a href="{{.Download}}/Caddyfile" translate="no">Caddyfile</a></p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>{{.Caddy}}</code></pre></div>
|
||
</div>
|
||
<div class="panel p-nginx">
|
||
<p class="meta"><span>{{th "about.proxy.nginx"}}</span>
|
||
<a href="{{.Download}}/nginx.conf" translate="no">nginx.conf</a></p>
|
||
<div class="code"><button class="copy" type="button">{{t "about.copy"}}</button><pre><code>{{.Nginx}}</code></pre></div>
|
||
</div>
|
||
<ul class="rules">
|
||
<li><strong>{{t "about.proxy.stream.title"}}</strong>{{t "about.proxy.stream.text"}}</li>
|
||
<li><strong>{{t "about.proxy.timeout.title"}}</strong>{{t "about.proxy.timeout.text"}}</li>
|
||
<li><strong>{{t "about.proxy.headers.title"}}</strong>{{th "about.proxy.headers.text"}}</li>
|
||
<li><strong>{{t "about.proxy.body.title"}}</strong>{{t "about.proxy.body.text"}}</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="download">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.download.title"}}</h2>
|
||
<p class="intro">{{th "about.download.intro"}}</p>
|
||
</div>
|
||
<div>
|
||
{{if .Release}}
|
||
<div class="ver"><span class="tag">{{.Release}}</span>{{with .Date}}<span class="eyebrow">{{t "about.download.released" .}}</span>{{end}}</div>
|
||
<div class="dl-wrap">
|
||
<table class="dl">
|
||
<thead><tr><th>{{t "about.download.col.for"}}</th><th>{{t "about.download.col.file"}}</th><th>{{t "about.download.col.notes"}}</th></tr></thead>
|
||
<tbody>
|
||
<tr><td translate="no">Linux x86-64</td><td><a href="{{$.Download}}/llmgw-{{$.Release}}-linux-amd64"><code>llmgw-{{$.Release}}-linux-amd64</code></a></td><td class="note">{{t "about.download.static_any"}}</td></tr>
|
||
<tr><td translate="no">Linux ARM64</td><td><a href="{{$.Download}}/llmgw-{{$.Release}}-linux-arm64"><code>llmgw-{{$.Release}}-linux-arm64</code></a></td><td class="note">{{t "about.download.static"}}</td></tr>
|
||
<tr><td translate="no">Linux x86-64, NVLink</td><td><a href="{{$.Download}}/llmgw-{{$.Release}}-linux-amd64-nvml"><code>llmgw-{{$.Release}}-linux-amd64-nvml</code></a></td><td class="note">{{t "about.download.nvml"}}</td></tr>
|
||
<tr><td>{{t "about.download.mac_arm"}}</td><td><a href="{{$.Download}}/llmgw-{{$.Release}}-darwin-arm64"><code>llmgw-{{$.Release}}-darwin-arm64</code></a></td><td class="note">{{th "about.download.mac_note"}}</td></tr>
|
||
<tr><td translate="no">macOS Intel</td><td><a href="{{$.Download}}/llmgw-{{$.Release}}-darwin-amd64"><code>llmgw-{{$.Release}}-darwin-amd64</code></a></td><td class="note"></td></tr>
|
||
<tr><td translate="no">Caddy</td><td><a href="{{$.Download}}/Caddyfile"><code>Caddyfile</code></a></td><td class="note">{{t "about.download.proxy_note"}}</td></tr>
|
||
<tr><td translate="no">nginx</td><td><a href="{{$.Download}}/nginx.conf"><code>nginx.conf</code></a></td><td class="note">{{t "about.download.proxy_note"}}</td></tr>
|
||
<tr><td>{{t "about.download.checksums"}}</td><td><a href="{{$.Download}}/checksums.txt"><code>checksums.txt</code></a></td><td class="note">{{t "about.download.checksums_note"}}</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{{else}}
|
||
<p class="intro" style="margin-top:0">{{th "about.download.dev" .Version}}</p>
|
||
{{end}}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="status">
|
||
<div class="sec-head">
|
||
<div>
|
||
<h2>{{t "about.status.title"}}</h2>
|
||
<p class="intro">{{t "about.status.intro"}}</p>
|
||
</div>
|
||
<div class="status">
|
||
<div class="proven">
|
||
<h3>{{t "about.status.proven"}}</h3>
|
||
<ul>
|
||
<li>{{t "about.status.proven.single"}}</li>
|
||
<li>{{t "about.status.proven.ondemand"}}</li>
|
||
<li>{{t "about.status.proven.keys"}}</li>
|
||
<li>{{t "about.status.proven.upgrades"}}</li>
|
||
<li>{{t "about.status.proven.stores"}}</li>
|
||
<li>{{t "about.status.proven.chat"}}</li>
|
||
<li>{{t "about.status.proven.ha"}}</li>
|
||
<li>{{t "about.status.proven.signin"}}</li>
|
||
<li>{{t "about.status.proven.kb"}}</li>
|
||
</ul>
|
||
</div>
|
||
<div class="open">
|
||
<h3>{{t "about.status.open"}}</h3>
|
||
<ul>
|
||
<li>{{th "about.status.open.fabrics"}}</li>
|
||
<li>{{t "about.status.open.planes"}}</li>
|
||
<li>{{t "about.status.open.weights"}}</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<footer>
|
||
<span>llmgw {{.Version}}</span>
|
||
<span><a href="https://gitea.mynodes.xyz/ilker/llmgw">{{t "about.nav.source"}}</a> ·
|
||
<a href="https://gitea.mynodes.xyz/ilker/llmgw/src/branch/main/CHANGELOG.md">{{t "about.footer.changelog"}}</a> ·
|
||
<a href="https://gitea.mynodes.xyz/ilker/llmgw/src/branch/main/docs/reference.md">{{t "about.footer.reference"}}</a></span>{{if not .Site}}{{template "langs"}}{{end}}
|
||
</footer>
|
||
</div>
|
||
|
||
<script>
|
||
var say = { copy: {{t "about.copy"}}, copied: {{t "about.copied"}}, selected: {{t "about.selected"}} };
|
||
document.querySelectorAll('.copy').forEach(function (b) {
|
||
b.addEventListener('click', function () {
|
||
var text = b.dataset.copy || b.parentElement.querySelector('pre').innerText;
|
||
var done = function (label) { b.textContent = label; setTimeout(function () { b.textContent = say.copy; }, 1600); };
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(text).then(function () { done(say.copied); }, function () { select(); });
|
||
} else { select(); }
|
||
function select() {
|
||
var el = b.dataset.copy ? b.parentElement.querySelector('code') : b.parentElement.querySelector('pre');
|
||
var r = document.createRange(); r.selectNodeContents(el);
|
||
var s = window.getSelection(); s.removeAllRanges(); s.addRange(r);
|
||
done(say.selected);
|
||
}
|
||
});
|
||
});
|
||
</script>
|
||
{{if not .Site}}</body></html>{{end}}{{end}}
|