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
26 changes: 25 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.1.7] - 2026-05-18

Full commit range: [`v0.1.6...v0.1.7`](https://github.com/pacificcodeinc/glass/compare/v0.1.6...v0.1.7)

### Added

- Markdown table rendering with aligned columns, styled headers, escaped pipe support, and source mapping for search and selection highlights.
- Table cells wrap into additional visual rows instead of truncating long content.
- A broad `benchmark.md` fixture covering implemented Markdown behavior, known gaps, and renderer stress cases.
- GitHub Actions CI for formatting, tests, and release build checks.

### Changed

- Table body rows now use internal separators so wrapped rows remain visually distinct without adding an outside top or bottom border.
- Wrapped blockquotes keep their quiet quote marker and styling across visual rows.
- Nested bullets alternate between filled and hollow markers by indentation level.

### Fixed

- Nested blockquotes render repeated quote markers instead of falling back toward plain Markdown source.
- Long inactive table cells no longer collapse into ellipsized text in narrow article widths.
- Long benchmark prose now exercises the renderer's wrapping behavior instead of relying on manual hard wraps in the fixture.

## [0.1.6] - 2026-05-18

Full commit range: [`v0.1.5...v0.1.6`](https://github.com/pacificcodeinc/glass/compare/v0.1.5...v0.1.6)
Expand Down Expand Up @@ -134,7 +157,8 @@ Full commit range: [`v0.1.0...v0.1.1`](https://github.com/pacificcodeinc/glass/c
- Live Markdown rendering with concealed syntax markers.
- Checkbox (`- [ ]` / `- [x]`) rendering.

[Unreleased]: https://github.com/pacificcodeinc/glass/compare/v0.1.6...HEAD
[Unreleased]: https://github.com/pacificcodeinc/glass/compare/v0.1.7...HEAD
[0.1.7]: https://github.com/pacificcodeinc/glass/compare/v0.1.6...v0.1.7
[0.1.6]: https://github.com/pacificcodeinc/glass/compare/v0.1.5...v0.1.6
[0.1.5]: https://github.com/pacificcodeinc/glass/compare/v0.1.4...v0.1.5
[0.1.4]: https://github.com/pacificcodeinc/glass/compare/v0.1.3...v0.1.4
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "glass"
version = "0.1.6"
version = "0.1.7"
edition = "2024"

[dependencies]
Expand Down
2 changes: 1 addition & 1 deletion ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Bug & feature log for glass.
## Rendering

- [ ] **Fenced code blocks**: highlight the language identifier (e.g., `rust` in ` ```rust `).
- [ ] **Tables**: render Markdown tables.
- [x] **Tables**: render Markdown tables.
- [ ] **Strikethrough**: render `~~text~~`, including inside list items.
- [ ] **URL display**: strip unnecessary parts (e.g., `https://`) from bare URLs that lack pretty titles.
- [ ] **Link expansion**: only expand URLs to their real Markdown form on hover, not whenever their line is active in Normal mode.
Expand Down
257 changes: 257 additions & 0 deletions benchmark.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
# Glass Markdown Benchmark

This file is a visual and interaction benchmark for Glass. It intentionally mixes Markdown that Glass supports today with Markdown that should stay readable even before dedicated rendering support exists.

Use it to check:

- inactive-line Markdown concealment
- active-line raw Markdown editing
- wrapped-line cursor movement
- search highlighting with `/`, `n`, and `N`
- mouse click navigation and drag selection
- link navigation with `gf`, Enter, and Command-click
- table rendering added on the `table-rendering` branch

## Headings

# Heading level 1
## Heading level 2
### Heading level 3
#### Heading level 4 currently falls back to plain Markdown

Indented headings should stay plain:

# This is indented, so it should not render as a heading

## Paragraphs And Wrapping

This paragraph is intentionally long so it wraps across several visual rows in a normal terminal width. It includes plain words, punctuation, and a useful search target: glass benchmark needle. Cursor movement should preserve the intended visual column when moving through this wrapped paragraph, and selection should copy the selected text immediately.

This query is split across a physical line break for search testing:
multi
line needle

## Inline Formatting

Plain text with *emphasis*, _alternate emphasis_, **strong text**, and `inline code`. Glass conceals some inline syntax on inactive rows while keeping the active row editable as source Markdown.

Wrapped inline formatting should not leak delimiters between visual rows:
This sentence has **bold text that keeps going for a while so the wrapped row still looks clean** and then returns to normal text.

Known gap: ~~strikethrough is not rendered yet~~.

## Links

Markdown links:

- [Glass repository](https://github.com/pacificcodeinc/glass)
- [Relative note](README.md)
- [Nested path](docs/example.md)

Bare URLs:

- https://example.com
- https://example.com/wiki/Foo_(bar)
- https://example.com/some/really/long/path/that/should/wrap/without/leaking/url/fragments?query=glass

Autolink:

<https://example.com/autolink>

Wiki links:

- [[README]]
- [[ISSUES.md]]
- [[Projects/Glass Benchmark]]

Known gap: wiki links are navigable, but their visual treatment is still not as distinct as it should be.

## Blockquotes

> A simple quote should render with a quiet quote marker.

> A longer quote should wrap without turning into noisy syntax. It should keep the quote style across wrapped rows and still feel like a calm reading surface.

Nested blockquote benchmark:

> Outer quote
> > Inner quote currently falls back toward plain Markdown behavior

## Lists

Bullets:

- First bullet item
- Second bullet item with `inline code`
- Third bullet item with [a link](README.md)
- Nested bullet item
- Another nested bullet item that wraps for a while so continuation indentation can be checked visually

Alternate bullet markers:

* Star bullet
+ Plus bullet

Numbered lists:

1. First numbered item
2. Second numbered item
10. Multi-digit marker should align cleanly

Task lists:

- [ ] Unchecked task
- [x] Checked task
- [ ] Task with [a relative link](ISSUES.md)
- [x] Completed task with `inline code`

Marker-only task row:

- [ ]

## Tables

Basic table:

| Name | Role | Status |
| --- | --- | --- |
| Ada | Editor core | Done |
| Linus | Terminal polish | In progress |
| Grace | Rendering | Planned |

Aligned table:

| Item | Count | Ratio | Notes |
| :--- | ---: | :---: | --- |
| Tables | 1 | 100% | Newly rendered |
| Links | 3 | 75% | Markdown, bare URL, wiki |
| Motions | 42 | 80% | More Vim parity needed |

Narrow-width pressure table:

| Column | Long content | Number |
| --- | --- | ---: |
| Alpha | This cell is intentionally long enough to force wrapping in a narrow terminal | 1200 |
| Beta | Short value | 7 |

Escaped pipe table:

| Pattern | Meaning |
| --- | --- |
| `A \| B` | Escaped pipe should stay inside the cell |
| `x \| y \| z` | Multiple escaped pipes |

Markdown inside table cells:

| Cell type | Example |
| --- | --- |
| Inline code | `cargo test --locked` |
| Link | [README](README.md) |
| Emphasis | **bold** and *italic* |

Known gap: inline Markdown inside inactive table cells is aligned, but not yet fully concealed or styled per cell.

## Code

Inline command: `cargo test --locked`

Fenced Rust code:

```rust
fn main() {
let message = "glass benchmark";
println!("{message}");
}
```

Fenced shell code:

```bash
cargo fmt --all -- --check
cargo test --locked
cargo build --release --locked
```

Known gap: fenced code blocks render as code fences, but the language marker is not specially highlighted yet.

## Rules And Separators

Horizontal rules should remain readable, even if they are not custom-rendered:

---

***

___

## Images And HTML

Image syntax:

![Alt text for a local image](assets/example.png)

Inline HTML:

<kbd>Esc</kbd> exits insert mode.

<details>
<summary>HTML details summary</summary>

This is HTML content that should remain readable as source.

</details>

Known gap: images and raw HTML are not rendered as rich elements.

## Footnotes And References

Footnote reference[^one] and another reference[^two].

[^one]: Footnote definitions are not specially rendered yet.
[^two]: This is here to make sure the source stays readable.

Reference link:

[reference-style link][glass]

[glass]: https://github.com/pacificcodeinc/glass

## Definition Lists

Glass
: A terminal Markdown editor focused on feel.

Benchmark
: A file that catches visual and interaction regressions.

Known gap: definition lists are not custom-rendered yet.

## Command And Search Words

Use these repeated words to test search result counts:

needle alpha
needle beta
needle gamma

Try these command-ish strings without accidentally executing them while editing:

:w
:q
:e benchmark.md
/needle

## Mixed Stress Section

> Quote with [a link](README.md), `inline code`, and **strong text** inside it.

- [ ] A task with a bare URL https://example.com/todo
- [x] A completed task with a wiki link [[ISSUES.md]]

| Mixed | Example | Result |
| --- | --- | --- |
| Link | [README](README.md) | should align |
| Code | `glass benchmark.md` | should align |
| Text | long plain text that needs fitting in smaller windows | should not break the table |

Final long wrapped line with many constructs: **bold words**, `inline code`, [a link](README.md), a bare URL https://example.com/final-check, and enough plain text to wrap several times in a narrow viewport.
8 changes: 7 additions & 1 deletion src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use crate::{
render::{visible_rows, visual_line_bounds, wrap_index_for_column, wrap_line},
},
fs::tree::FileTree,
markdown::highlight::concealed_wrap_line,
markdown::inline::{LinkKind, link_at_column},
markdown::{highlight::concealed_wrap_line, table::TableLayout},
};

const STATUS_MESSAGE_TTL: Duration = Duration::from_secs(3);
Expand Down Expand Up @@ -1224,6 +1224,7 @@ impl App {
let gutter = (self.buffer.line_count().to_string().len() + 1) as usize;
let text_x = local_x.saturating_sub(gutter);
let width = self.wrap_width();
let table_layout = TableLayout::new(&self.buffer);
let rows = visible_rows(
&self.buffer,
self.viewport.top_line,
Expand All @@ -1233,6 +1234,8 @@ impl App {
|line_num, text, width| {
if line_num == self.cursor.line {
wrap_line(text, width)
} else if table_layout.is_table_row(line_num) {
table_layout.wrap_line(line_num, text, width)
} else {
concealed_wrap_line(text, width)
}
Expand Down Expand Up @@ -1847,8 +1850,11 @@ impl App {
fn line_wrap_count(&self, line: usize, width: usize) -> usize {
let line_text = self.buffer.line(line);
let trimmed = line_text.trim_end_matches(['\r', '\n']);
let table_layout = TableLayout::new(&self.buffer);
let (segments, _) = if line == self.cursor.line {
wrap_line(trimmed, width)
} else if table_layout.is_table_row(line) {
table_layout.wrap_line(line, trimmed, width)
} else {
concealed_wrap_line(trimmed, width)
};
Expand Down
Loading