Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/pages/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,12 @@ def render(markdown):
if heading:
level = len(heading.group(1))
text = heading.group(2).strip()
out.append('<h%d id="%s">%s</h%d>' % (level, slug(text), inline(text), level))
anchor = slug(text)
body = inline(text)
if anchor and "<a " not in body:
# every heading is a link to itself, so a section can be shared
body = '<a class="anchor" href="#%s">%s</a>' % (anchor, body)
out.append('<h%d id="%s">%s</h%d>' % (level, anchor, body, level))
seen_prose = True
i += 1
continue
Expand Down
22 changes: 18 additions & 4 deletions .github/pages/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,25 @@

/* ---- prose ---- */
h1, h2, h3 {
font-family: var(--mono); font-weight: 700;
letter-spacing: -0.035em; line-height: 1.25; text-wrap: balance;
font-family: var(--mono); font-weight: 500;
letter-spacing: -0.03em; line-height: 1.25; text-wrap: balance;
}

/* headings link to themselves, prefixed with their markdown level */
.anchor { color: inherit; text-decoration: none; }
h2 .anchor::before, h3 .anchor::before {
color: var(--ink-3); font-weight: 400; margin-right: .5ch;
}
h2 .anchor::before { content: "##"; }
h3 .anchor::before { content: "###"; }
.anchor:hover { text-decoration: none; }
.anchor:hover::before { color: var(--accent-ink); }
h1 { font-size: clamp(1.9rem, 4.6vw, 2.3rem); margin: 0 0 .3em; }
h2 {
font-size: 1.26rem; margin: 2.2em 0 1em;
padding-bottom: .4em; border-bottom: 1px solid var(--rule);
}
h3 { font-size: 1rem; font-weight: 500; letter-spacing: -0.025em; margin: 1.5em 0 .45em; }
h3 { font-size: 1rem; letter-spacing: -0.025em; margin: 1.5em 0 .45em; }

/* the wordmark leads the page; the h1 stays for readers and search */
.sr-only {
Expand Down Expand Up @@ -209,7 +219,11 @@
border: 1px solid var(--rule); border-radius: 8px;
}
.doc th, .doc td { text-align: left; padding: 15px 18px; vertical-align: top; }
.doc thead th { background: var(--surface-2); font-weight: 600; border-bottom: 1px solid var(--rule); }
.doc thead th {
background: var(--surface-2); border-bottom: 1px solid var(--rule);
font-family: var(--mono); font-weight: 500; font-size: .84rem;
letter-spacing: -0.02em; color: var(--ink-2);
}
.doc tbody tr + tr td { border-top: 1px solid var(--rule-soft); }
.doc td:first-child { font-weight: 600; }
/* key/value rows: hold the value column to a readable measure */
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ python3 install.py # --cli-only, --dev, --prefix, --verify, --uninstal
# Pipe a single command (non-interactive; cli.py detects a non-tty stdin)
echo '/search "q2 plan"' | python3 -m glean_code

# Run the full test suite (1,103 tests, stdlib unittest — works with or without pytest)
# Run the full test suite (1,108 tests, stdlib unittest — works with or without pytest)
python3 -m pytest tests/
python3 -m unittest discover tests/

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ The full Glean Code REPL — slash commands, status bar, mock/live switching, se
| 🔐 **[SSO / OAuth](docs/SSO_OAUTH.md)** · **[Secure tokens](docs/SECURE_TOKENS.md)** | Browser sign-in, secure refs, the masking matrix |
| 🔌 **[MCP server](docs/MCP.md)** | Glean as native tools in Claude Code, Claude Desktop, Cursor |
| 🏛️ **[Architecture](docs/ARCHITECTURE.md)** · **[REST paths](docs/REST_PATHS.md)** | Module map, request flow, endpoints, how to add a command |
| ✅ **[Testing](docs/TESTING.md)** | Running the 1,103-test suite and what it covers |
| ✅ **[Testing](docs/TESTING.md)** | Running the 1,108-test suite and what it covers |
| 🛟 **[Support](SUPPORT.md)** · **[Changelog](CHANGELOG.md)** | How to report a bug · release history |

> [!NOTE]
Expand Down
4 changes: 2 additions & 2 deletions docs/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ files, and they outrank the `Glean Code.app` launcher in `Cmd+Space`:
export PYTHONPYCACHEPREFIX="$HOME/.cache/python"
```

1,103 tests covering the client and every mock response, commands and dispatch, config, UI, auth, completion, help docs, the mock corpus, indexing-walk, scaffold, the installer, the MCP server, the flow mapper, the Pages site builder, and Glean Personal (text extraction, the index, the content graph, ranking explanations, local mode, and the local MCP tools).
1,108 tests covering the client and every mock response, commands and dispatch, config, UI, auth, completion, help docs, the mock corpus, indexing-walk, scaffold, the installer, the MCP server, the flow mapper, the Pages site builder, and Glean Personal (text extraction, the index, the content graph, ranking explanations, local mode, and the local MCP tools).

## Development notes

Notes on the test suite added during development of glean-code-cli.

All 1,103 tests pass. Here's what was added across the development passes:
All 1,108 tests pass. Here's what was added across the development passes:

`tests/test_commands_extended.py` (155 new tests) — covers all previously untested commands:

Expand Down
27 changes: 26 additions & 1 deletion tests/test_pages_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@ class TestBlocks(unittest.TestCase):
def test_heading_gets_an_anchor_id(self):
self.assertIn('<h2 id="quickstart">', build.render("## Quickstart"))

def test_heading_links_to_itself(self):
out = build.render("## Quickstart")
self.assertEqual(
out, '<h2 id="quickstart"><a class="anchor" href="#quickstart">Quickstart</a></h2>')

def test_every_heading_level_gets_an_anchor(self):
out = build.render("# One\n\n## Two\n\n### Three")
self.assertEqual(out.count('class="anchor"'), 3)
self.assertIn('href="#three"', out)

def test_a_heading_that_already_holds_a_link_is_not_double_wrapped(self):
out = build.render("## See [the docs](docs/COMMANDS.md)")
self.assertNotIn('class="anchor"', out)
self.assertEqual(out.count("<a "), 1)

def test_fenced_code_is_escaped_and_tagged(self):
out = build.render("```bash\necho '<a>' && x\n```")
self.assertIn('<pre><code class="language-bash">', out)
Expand Down Expand Up @@ -136,7 +151,8 @@ def test_note_alert(self):
def test_raw_html_passes_through_untouched(self):
out = build.render('<div align="center">\n\n# Glean Code\n\n</div>')
self.assertIn('<div align="center">', out)
self.assertIn('<h1 id="glean-code">Glean Code</h1>', out)
self.assertIn(
'<h1 id="glean-code"><a class="anchor" href="#glean-code">Glean Code</a></h1>', out)
self.assertIn("</div>", out)

def test_horizontal_rule(self):
Expand Down Expand Up @@ -283,6 +299,15 @@ def test_tagline_is_set_in_the_mono_face(self):
rule = self.css[self.css.index('[align="center"] .banner + p {'):]
self.assertIn("font-family: var(--mono)", rule[:rule.index("}")])

def test_headings_carry_their_markdown_level(self):
self.assertIn('h2 .anchor::before { content: "##"; }', self.css)
self.assertIn('h3 .anchor::before { content: "###"; }', self.css)

def test_headings_and_table_headers_use_the_mono_face(self):
for selector in ("h1, h2, h3 {", ".doc thead th {"):
rule = self.css[self.css.index(selector):]
self.assertIn("font-family: var(--mono)", rule[:rule.index("}")], selector)

def test_image_rows_do_not_stretch_their_items(self):
row = self.css[self.css.index("p.imgrow {"):]
self.assertIn("align-items: center", row[:row.index("}")])
Expand Down
Loading