blog / posts /formatting-debug.html
wop's picture
Update posts/formatting-debug.html
fedea4d verified
Raw
History Blame Contribute Delete
15.7 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Formatting Debug</title>
<!-- KaTeX -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" crossorigin="anonymous"
onload="renderMathInElement(document.body,{delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],throwOnError:false});"></script>
<!-- Your stylesheet -->
<link rel="stylesheet" href="../style.css">
</head>
<body><script src="../script.js" defer></script>
<div class="background"></div>
<main class="article">
<a class="back" href="../index.html">&larr; Back</a>
<div class="meta">June 2026 &middot; Debug</div>
<h1>Formatting Debug Post</h1>
<p>This is a throwaway post to verify every element renders the way
<code>style.css</code> intends. If something below looks off, that's the
bug &mdash; not a feature.</p>
<h2>Headings</h2>
<h3>Heading level 3</h3>
<h4>Heading level 4</h4>
<h2>Inline Formatting</h2>
<p>You can write <strong>strong</strong>, <em>emphasized</em>,
<strong><em>strong + emphasized</em></strong>, <mark>highlighted</mark>,
and <kbd>Cmd</kbd> + <kbd>K</kbd> text. Here is an inline
<code>variable_name</code> for good measure, plus a
<a href="https://huggingface.co">link to the Hub</a> and a long
<a href="https://huggingface.co/spaces/seton-labs/blog">https://huggingface.co/spaces/seton-labs/blog/with/a/very/long/url/that/might/overflow</a>
to test <code>overflow-wrap</code>.</p>
<h2>Blockquote</h2>
<blockquote>
This is a blockquote. It should show a thin accent bar on the left
and render in italic, per the stylesheet.
</blockquote>
<h2>Lists</h2>
<p>Unordered:</p>
<ul>
<li>First item</li>
<li>Second item with a nested list
<ul>
<li>Nested item A</li>
<li>Nested item B</li>
</ul>
</li>
<li>Third item</li>
</ul>
<p>Ordered:</p>
<ol>
<li>Step one</li>
<li>Step two</li>
<li>Step three</li>
</ol>
<h2>Code Block &mdash; Python</h2>
<pre><code>def greet(name: str) -> str:
"""Return a friendly greeting."""
return f"Hello, {name}!"
# Call the function
print(greet("Seton"))</code></pre>
<h2>Code Block &mdash; JavaScript</h2>
<pre><code>const train = async (model, data, epochs = 10) => {
for (let i = 0; i < epochs; i++) {
const loss = model.forward(data);
model.backward(loss);
console.log(`Epoch ${i + 1}/${epochs} — loss: ${loss.toFixed(4)}`);
}
return model;
};
// Usage
const result = await train(myModel, dataset, 20);</code></pre>
<h2>Table</h2>
<table>
<thead>
<tr><th>Element</th><th>Styled?</th><th>Notes</th></tr>
</thead>
<tbody>
<tr><td>Headings</td><td>Yes</td><td>Fluid type on h1/h2</td></tr>
<tr><td>Blockquote</td><td>Yes</td><td>Accent left border</td></tr>
<tr><td>Code</td><td>Yes</td><td>Syntax highlighted</td></tr>
<tr><td>Math</td><td>Yes</td><td>KaTeX rendering</td></tr>
<tr><td>Images</td><td>Yes</td><td>Click to enlarge</td></tr>
</tbody>
</table>
<h2>Images</h2>
<p>Click any image to enlarge. Use the side arrows to navigate between all images on this page.</p>
<p><img src="https://picsum.photos/seed/seton-debug/800/360" alt="Placeholder test image"></p>
<h2>More Images</h2>
<p>A couple more to test the lightbox navigation.</p>
<p><img src="https://picsum.photos/seed/seton-two/800/400" alt="Second test image"></p>
<p><img src="https://picsum.photos/seed/seton-three/800/400" alt="Third test image"></p>
<h2>Horizontal Rule</h2>
<p>Text above the rule.</p>
<hr>
<p>Text below the rule.</p>
<h2>Collapsible Section</h2>
<details>
<summary>Click to expand (testing &lt;details&gt;)</summary>
<p>Hidden body text. Useful for long appendices or changelogs.</p>
</details>
<h2>Math</h2>
<p>Inline math: the cross-entropy loss is $L = -\sum_{i=1}^{N} \log p(y_i \mid x_i)$. Block math &mdash; the gradient descent update rule:</p>
<p>$$ \theta_{t+1} = \theta_t - \eta \, \nabla_\theta \mathcal{L}(\theta_t) $$</p>
<p>And Bayes' theorem for good measure:</p>
<p>$$ P(\theta \mid \mathcal{D}) = \frac{P(\mathcal{D} \mid \theta) \, P(\theta)}{P(\mathcal{D})} $$</p>
<h2>Edge Cases</h2>
<p>A verylongunbrokenstringwithoutanyspacesAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA to test overflow handling.</p>
<p>Emoji test: &#x1F917; &#x2705; &#x274C; &#x1F680; &#x1F9EA; &mdash; should render in color at body size.</p>
</main>
<script>
/* ==========================================================
SYNTAX HIGHLIGHTING
========================================================== */
const PY_KW = new Set([
'def','class','return','if','elif','else','for','while','import','from','as',
'try','except','finally','with','yield','lambda','pass','break','continue',
'raise','and','or','not','in','is','global','nonlocal','assert','del',
'async','await'
]);
const JS_KW = new Set([
'const','let','var','function','return','if','else','for','while','do',
'switch','case','break','continue','new','class','extends','import','export',
'from','default','try','catch','finally','throw','typeof','instanceof',
'in','of','async','await','yield','void','delete','with'
]);
const PY_BI = new Set([
'print','len','range','int','str','float','list','dict','set','tuple','bool',
'type','isinstance','input','open','map','filter','zip','enumerate','sorted',
'reversed','sum','min','max','abs','round','any','all','super','property',
'staticmethod','classmethod','True','False','None','Exception','ValueError',
'TypeError','KeyError','IndexError','AttributeError','NotImplementedError',
'RuntimeError','StopIteration','FileNotFoundError','object'
]);
const JS_BI = new Set([
'console','Math','Array','Object','String','Number','Boolean','Date','RegExp',
'Error','TypeError','RangeError','SyntaxError','JSON','Promise','Map','Set',
'Symbol','Proxy','Reflect','parseInt','parseFloat','isNaN','isFinite',
'undefined','null','true','false','NaN','Infinity'
]);
function escapeHtml(s) {
return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
function detectLang(code) {
let py = 0, js = 0;
const pyP = /\b(def |class |import |from \w+ import|elif |print\(|True|False|None|self[\.\[])\b/g;
const jsP = /\b(const |let |var |function |=>|console\.|undefined|null|async |await )\b/g;
let m;
while ((m = pyP.exec(code)) !== null) py++;
while ((m = jsP.exec(code)) !== null) js++;
if (py > js) return 'python';
if (js > 0) return 'javascript';
return 'text';
}
function highlight(code) {
const lang = detectLang(code);
const kw = lang === 'python' ? PY_KW : lang === 'javascript' ? JS_KW : new Set();
const bi = lang === 'python' ? PY_BI : lang === 'javascript' ? JS_BI : new Set();
const tokens = [];
let i = 0;
const len = code.length;
while (i < len) {
if (lang === 'python') {
const t3 = code.slice(i, i + 3);
if (t3 === '"""' || t3 === "'''") {
const end = code.indexOf(t3, i + 3);
const span = end !== -1 ? code.slice(i, end + 3) : code.slice(i);
tokens.push({ type: 'string', text: span });
i += span.length;
continue;
}
}
{
const pm = code.slice(i).match(/^[frbFRB]{0,3}/);
if (pm) {
const pLen = pm[0].length;
const nc = code[i + pLen];
if (nc === '"' || nc === "'") {
const q = nc;
const isF = pm[0].toLowerCase().includes('f');
let depth = 0, k = i + pLen + 1;
let found = false;
while (k < len) {
const ch = code[k];
if (ch === '\\') { k += 2; continue; }
if (isF) {
if (ch === '{') { depth++; k++; continue; }
if (ch === '}') { depth = Math.max(0, depth - 1); k++; continue; }
}
if (ch === q && depth === 0) { found = true; break; }
k++;
}
if (found) {
tokens.push({ type: 'string', text: code.slice(i, k + 1) });
i = k + 1;
continue;
}
}
}
}
if (lang === 'python' && code[i] === '#') {
let end = code.indexOf('\n', i);
if (end === -1) end = len;
tokens.push({ type: 'comment', text: code.slice(i, end) });
i = end;
continue;
}
if (lang === 'javascript' && code.slice(i, i + 2) === '//') {
let end = code.indexOf('\n', i);
if (end === -1) end = len;
tokens.push({ type: 'comment', text: code.slice(i, end) });
i = end;
continue;
}
if (lang === 'javascript' && code.slice(i, i + 2) === '/*') {
let end = code.indexOf('*/', i + 2);
if (end === -1) end = len; else end += 2;
tokens.push({ type: 'comment', text: code.slice(i, end) });
i = end;
continue;
}
{
const m = code.slice(i).match(
/^(0x[0-9a-fA-F_]+|0b[01_]+|0o[0-7_]+|\d[\d_]*\.?\d*(?:e[+-]?\d+)?)/
);
if (m) {
tokens.push({ type: 'number', text: m[0] });
i += m[0].length;
continue;
}
}
if (lang === 'python' && code[i] === '@') {
const m = code.slice(i).match(/^@[\w.]+/);
if (m) {
tokens.push({ type: 'decorator', text: m[0] });
i += m[0].length;
continue;
}
}
{
const m = code.slice(i).match(/^\w+/);
if (m) {
const w = m[0];
let type = 'plain';
if (kw.has(w)) type = 'keyword';
else if (bi.has(w)) type = 'builtin';
else if (w === 'self' || w === 'cls' || w === 'this') type = 'self';
else {
let j = i + w.length;
while (j < len && code[j] === ' ') j++;
if (code[j] === '(') type = 'function';
}
tokens.push({ type, text: w });
i += w.length;
continue;
}
}
{
const m = code.slice(i).match(/^[+\-*/%=<>!&|^~:]+/);
if (m) {
tokens.push({ type: 'operator', text: m[0] });
i += m[0].length;
continue;
}
}
if ('(){}[],;.'.includes(code[i])) {
tokens.push({ type: 'punctuation', text: code[i] });
i++;
continue;
}
{
const m = code.slice(i).match(/^\s+/);
if (m) {
tokens.push({ type: 'plain', text: m[0] });
i += m[0].length;
} else {
tokens.push({ type: 'plain', text: code[i] });
i++;
}
}
}
return tokens.map(t => {
const esc = escapeHtml(t.text);
return t.type === 'plain' ? esc : `<span class="tok-${t.type}">${esc}</span>`;
}).join('');
}
document.querySelectorAll('pre code').forEach(block => {
block.innerHTML = highlight(block.textContent);
});
/* ==========================================================
LIGHTBOX
========================================================== */
class Lightbox {
constructor() {
this.images = [];
this.currentIndex = 0;
this.isOpen = false;
this._build();
this._bindImages();
this._bindKeys();
this._bindSwipe();
}
_build() {
this.el = document.createElement('div');
this.el.className = 'lightbox-overlay';
this.el.setAttribute('role', 'dialog');
this.el.setAttribute('aria-modal', 'true');
this.el.setAttribute('aria-label', 'Image viewer');
this.el.innerHTML = `
<button class="lightbox-btn lightbox-close" aria-label="Close">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
<line x1="18" y1="6" x2="6" y2="18"/>
<line x1="6" y1="6" x2="18" y2="18"/>
</svg>
</button>
<button class="lightbox-btn lightbox-arrow lightbox-prev" aria-label="Previous image">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<polyline points="15 18 9 12 15 6"/>
</svg>
</button>
<button class="lightbox-btn lightbox-arrow lightbox-next" aria-label="Next image">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<polyline points="9 6 15 12 9 18"/>
</svg>
</button>
<img class="lightbox-img" src="" alt="">
<div class="lightbox-counter"></div>
`;
document.body.appendChild(this.el);
this.imgEl = this.el.querySelector('.lightbox-img');
this.counterEl = this.el.querySelector('.lightbox-counter');
this.prevBtn = this.el.querySelector('.lightbox-prev');
this.nextBtn = this.el.querySelector('.lightbox-next');
this.closeBtn = this.el.querySelector('.lightbox-close');
this.closeBtn.addEventListener('click', () => this.close());
this.prevBtn.addEventListener('click', (e) => { e.stopPropagation(); this.prev(); });
this.nextBtn.addEventListener('click', (e) => { e.stopPropagation(); this.next(); });
this.el.addEventListener('click', (e) => {
if (e.target === this.el) this.close();
});
}
_bindImages() {
this.images = Array.from(document.querySelectorAll('.article img'));
this.images.forEach((img, idx) => {
img.addEventListener('click', () => this.open(idx));
});
}
_bindKeys() {
document.addEventListener('keydown', (e) => {
if (!this.isOpen) return;
if (e.key === 'Escape') this.close();
if (e.key === 'ArrowLeft') this.prev();
if (e.key === 'ArrowRight') this.next();
});
}
_bindSwipe() {
let startX = 0;
this.el.addEventListener('touchstart', (e) => {
startX = e.changedTouches[0].clientX;
}, { passive: true });
this.el.addEventListener('touchend', (e) => {
const dx = startX - e.changedTouches[0].clientX;
if (Math.abs(dx) > 60) {
dx > 0 ? this.next() : this.prev();
}
}, { passive: true });
}
open(idx) {
this.currentIndex = idx;
this.isOpen = true;
this._update();
requestAnimationFrame(() => {
this.el.classList.add('active');
});
document.body.style.overflow = 'hidden';
this.closeBtn.focus();
}
close() {
this.isOpen = false;
this.el.classList.remove('active');
document.body.style.overflow = '';
this.images[this.currentIndex]?.focus();
}
prev() {
this.currentIndex = (this.currentIndex - 1 + this.images.length) % this.images.length;
this._update();
}
next() {
this.currentIndex = (this.currentIndex + 1) % this.images.length;
this._update();
}
_update() {
const srcImg = this.images[this.currentIndex];
this.imgEl.style.opacity = '0';
this.imgEl.style.transform = 'scale(0.96)';
setTimeout(() => {
this.imgEl.src = srcImg.src;
this.imgEl.alt = srcImg.alt;
this.imgEl.removeAttribute('loading');
this.imgEl.style.opacity = '1';
this.imgEl.style.transform = 'scale(1)';
}, 120);
const total = this.images.length;
if (total > 1) {
this.counterEl.textContent = `${this.currentIndex + 1} / ${total}`;
this.prevBtn.style.display = '';
this.nextBtn.style.display = '';
} else {
this.counterEl.textContent = '';
this.prevBtn.style.display = 'none';
this.nextBtn.style.display = 'none';
}
}
}
new Lightbox();
</script>
</body>
</html>