Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
c3afa66
breaking: remove automatic tab expansion, add BuffeeSanitize extension
varrockbank Jan 12, 2026
03fa756
feat: add Mode.ext to track registered extensions
varrockbank Jan 12, 2026
3f9f436
breaking: Span.ins now takes array of lines instead of string
varrockbank Jan 12, 2026
7927ea2
refactor: rename Model.end to Model.last, View.start/end to View.firs…
varrockbank Jan 13, 2026
842d7f5
refactor(api): remove Model.s api, delegate to user to render after M…
varrockbank Jan 13, 2026
9ec02f2
refactor(api): s/rows/h s/cols/w in config params
varrockbank Jan 13, 2026
90c105d
perf: optimize hotpath, regex for move word only when used
varrockbank Jan 13, 2026
4281738
api: move render/RENDER to View namespace, convert api.md to api.txt
varrockbank Jan 13, 2026
ef9ff9b
web: add Sanitize extension example, rename Kitchen Sink to Examples
varrockbank Jan 13, 2026
a4dc8f4
web: update wrappers to use h/w/s props, add API Changes section to C…
varrockbank Jan 13, 2026
d93aecf
docs: add changelog entry for wrapper updates, update CLAUDE.md
varrockbank Jan 13, 2026
eb4d4b6
docs: add theme and dependency commentary to wrappers
varrockbank Jan 13, 2026
69f8b79
api: wrappers accept lines array instead of initialText string
varrockbank Jan 13, 2026
b3403cd
docs: add version 1.1.0 to wrappers
varrockbank Jan 13, 2026
2d761fc
feat(wrappers): add extensions prop to apply extensions via array
varrockbank Jan 13, 2026
dab587d
fix(statusline): restore original format with line count and bytes
varrockbank Jan 13, 2026
254e00c
fix(statusline): remove locale formatting from line/byte counts
varrockbank Jan 13, 2026
1b99d5b
fix(statusline): remove commas, add API for setting original bytes/lines
varrockbank Jan 13, 2026
39e762b
docs: split CSS step into core, custom theme, and pre-built theme
varrockbank Jan 13, 2026
84c6d9d
docs: link template.html to GitHub
varrockbank Jan 13, 2026
19359f7
docs: use raw GitHub URL for template.html
varrockbank Jan 13, 2026
e4e21b8
docs: fix relative path to dist/buffee.min.js
varrockbank Jan 13, 2026
afc3d0c
docs: add link to sample-sizing.html demo
varrockbank Jan 13, 2026
fbe095e
docs: add API section with quick reference and link to api.txt
varrockbank Jan 13, 2026
df4fa9b
docs: update getting-started.html
varrockbank Jan 13, 2026
cb5ff6a
refactor: rename extensions to combinators
varrockbank Jan 13, 2026
5f010d6
docs: update landing page
varrockbank Jan 13, 2026
9e3b34e
v15.7.0-alpha.1: remove View._ getter
varrockbank Jan 13, 2026
f7684fa
v15.7.1-alpha.1: perf: replace forEach with for..of loops
varrockbank Jan 13, 2026
9a2ca61
v15.7.2-alpha.1: refactor: use const in for..of loops
varrockbank Jan 13, 2026
3dbe356
v15.7.3-alpha.1: perf: remove unnecessary detachedHead initialization
varrockbank Jan 13, 2026
e409d0e
v15.7.4-alpha.1: refactor: rename tail→anchor, detachedHead→detached
varrockbank Jan 13, 2026
5207257
v15.8.0-alpha.1: api: View.first and View.n are now setters
varrockbank Jan 13, 2026
3164885
v15.8.1-alpha.1: fix: viewport scroll regression
varrockbank Jan 13, 2026
826bb70
v15.8.2-alpha.1: fix(css): rail clipping
varrockbank Jan 13, 2026
e0dbca5
v15.8.3-alpha.1: perf: use preventScroll:1 instead of true
varrockbank Jan 13, 2026
ee60989
v15.9.0-alpha.1: refactor: remove $clip clipboard bridge
varrockbank Jan 13, 2026
5c19fa5
v15.9.1-alpha.1: perf: simplify paste handler
varrockbank Jan 13, 2026
74e2097
v15.9.2-alpha.1: perf: remove empty v/c/x handlers
varrockbank Jan 13, 2026
a34d4ca
v15.9.3-alpha.1: perf: inline metaKeys map
varrockbank Jan 13, 2026
558099d
v15.9.4-alpha.1: golf: remove braces from single-expression arrows
varrockbank Jan 13, 2026
b3743b4
v15.9.5-alpha.1: golf: move mvW regexes to local consts
varrockbank Jan 13, 2026
1eaf1b3
v15.9.6-alpha.1: golf: simplify Span._ getter, update API docs
varrockbank Jan 13, 2026
c8d6fb2
api: expose maxCol as Mode.mx for external access
varrockbank Jan 13, 2026
77c4465
golf: simplify dent cursor detection with && ||
varrockbank Jan 13, 2026
164c59d
golf: merge special into const chain in keydown handler
varrockbank Jan 13, 2026
a18cc53
golf: extract cw to local const, use in render
varrockbank Jan 13, 2026
4abee9f
refactor: reintroduce cmdMap for keyboard shortcuts
varrockbank Jan 13, 2026
0bc5042
api: add Model.end, Span.select(pos) parameter
varrockbank Jan 13, 2026
e331974
fix(extensions): update for Model.end API, improve StatusLine
varrockbank Jan 14, 2026
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
493 changes: 0 additions & 493 deletions API.md

This file was deleted.

45 changes: 28 additions & 17 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Claude Instructions for buffee

**Documentation:** `docs/` folder
- `docs/onboarding.md` — Getting started guide
- `docs/api.md` — API surface reference
- `docs/extensions.md` — Extension documentation
**Full API reference: `docs/`** — Read these files for complete documentation:
- `docs/api.txt` — Model, View, Span, Mode API
- `docs/onboarding.md` — Getting started, sizing, keybindings
- `docs/combinators.md` — Combinator documentation

## Quick Reference

```javascript
BuffeeStatusLine(new Buffee(el, { rows: 20, cols: 80, s: 4 }));
BuffeeStatusLine(new Buffee(el, { h: 20, w: 80, s: 4 }));

editor.Model.s = "content"; // Set content
editor.Model._; // ["line1", "line2"]
editor.View.set(5); // Scroll to line index 5
editor.Span.ins("text"); // Insert at cursor
editor.Span.cursor({y:0,x:0});// Move cursor
editor.Model._ = ["line1", "line2"]; // Set content (array of lines)
editor.View.render(); // Render after content changes
editor.View.first = 5; // Scroll to line index 5
editor.Span.ins(["text"]); // Insert at cursor
editor.Span.cursor({y:0,x:0}); // Move cursor
```

## Required HTML Structure
Expand All @@ -28,6 +28,17 @@ See `web/template.html` for the required HTML structure. Missing any element wil
- `samples/*.html` (all sample files)
- `web/themes.html`

## API Changes

**When changing the Buffee API (config options, method names, namespaces), also update:**
- `wrappers/react.jsx` - React component props and config
- `wrappers/svelte.svelte` - Svelte component props and config
- `wrappers/vue.js` - Vue component props and config
- `docs/api.txt` - API reference
- `web/getting-started.html` - Usage examples
- `web/wrappers.html` - Wrapper documentation
- `dev/changelog.txt` - Add entry for wrapper updates

## Cursor Model (Vim-style)

- **Cursor sits ON a character**, not between characters
Expand Down Expand Up @@ -85,12 +96,12 @@ left with alt
EXPECT cursor at 0,5
```

## Extensions
## Combinators

Located in `extensions/`, tested in "Extensions" tab of `test/index.html`.
Located in `combinators/`, tested in "Combinators" tab of `test/index.html`.

**When adding an extension, also update:**
- `web/extensions.html` (documentation)
**When adding a combinator, also update:**
- `web/combinators.html` (documentation)
- `samples/index.html` (if adding a sample)

| File | Function | Description |
Expand All @@ -103,6 +114,7 @@ Located in `extensions/`, tested in "Extensions" tab of `test/index.html`.
| `tui.js` | `BuffeeTUI(editor)` | Text-based UI via text manipulation |
| `ios.js` | `BuffeeIOS(editor)` | iOS touch/keyboard support |
| `fileloader.js` | `BuffeeFileLoader(editor)` | File loading strategies |
| `sanitize.js` | `BuffeeSanitize(editor)` | Tab/Unicode sanitization |
| `ultrahighcapacity.js` | `BuffeeUltraHighCapacity(editor)` | 1B+ line support |
| `treesitter.js` | `BuffeeTreeSitter(editor, opts)` | Tree-sitter integration |

Expand Down Expand Up @@ -139,7 +151,7 @@ GitHub Pages serves from root. CI screenshot tests run against these (see `snaps
|------|---------|
| `template.html` | Required HTML structure |
| `getting-started.html` | Setup guide |
| `extensions.html` | Extension documentation |
| `combinators.html` | Combinator documentation |
| `themes.html` | Theme showcase |
| `comparison.html` | Editor comparison |
| `performance.html` | Performance research |
Expand All @@ -148,7 +160,7 @@ GitHub Pages serves from root. CI screenshot tests run against these (see `snaps
**assets/** (internal):
- `reset.css` - CSS reset (web-specific)

Templates: `extensions/_template.js`, `samples/_template.html`, `themes/_template.css`
Templates: `combinators/_template.js`, `samples/_template.html`, `themes/_template.css`

## DOM Classes Reference

Expand All @@ -163,7 +175,6 @@ Templates: `extensions/_template.js`, `samples/_template.html`, `themes/_templat
| `.buffee-layer-elements` | Overlay | TUI/Elementals overlay |
| `.buffee-caret` | Cursor | Blinking cursor |
| `.buffee-status` | Status bar | Bottom bar container |
| `.buffee-clip` | `<textarea>` | Hidden, for clipboard |

## Keybindings Reference

Expand Down
15 changes: 8 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
# Commits

## Scopes:
## Directory structure

web - github pages related stuff
test - test related stuff

## Files

assets - for github pages assets
samples - examples
theme - css themess
wrappers - Component wrappers in JavaScript UI frameworks
resources - test files, mostly for load testing

## Extensions
## Combinators

1. Add to extensions directory
2. update web/extensions.html
1. Add to combinators directory
2. update web/combinators.html

## Distributable

Expand Down
55 changes: 33 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Inspired by the experience of terminal interfaces and Vim, Buffee is a microlibr
- tiny: ~2kb (gz+min) fooprint, low memory/CPU overhead
- performant: rivals native editors like Vim - no slowdown on large files
- hassle-free: no build step, no NPM, no dependencies
- programmable: extensions, hackable internals, minimal API
- programmable: combinators, hackable internals, minimal API
- heavy-duty: ~70m SLOC file capacity, 1B+ in high-capacity mode

Yes - like Emacs, it includes a text editor too.
Expand All @@ -32,8 +32,7 @@ See [comparison](https://varrockbank.github.io/buffee/web/comparison.html) and [

## The Magic Trick

The crux is maintaining a small DOM footprint. This is achieved by maintain a virtual viewport and being
smart in surgically rendering only what's changed.
The crux is maintaining a small DOM footprint. This is achieved by maintain a virtual viewport and being smart in surgically rendering only what's changed.

The zeitgeist of webdev is VDOM. This does not come free. VDOM libraries are bulkier than Buffee in its entirety because they deal with arbitrary trees. Buffee avoids this
with a predictable and narrowly constrained UI surface space.
Expand All @@ -44,17 +43,31 @@ Finally, (V8) arrays, not being real arrays, prove miraculuously viable as a buf

## Usage

### Font Requirements
### Monowidth Character Handling

Buffee's fixed-width grid layout requires all characters to occupy exactly one cell. This section covers common issues that break grid alignment.

#### Font Requirements

Buffee assumes monospace fonts having accurate CSS `ch` values. If this assumption breaks, the cursor position
will be visually misaligned from true position. This is evident with variable-width
text but some monospace fonts can cause "drift", fractions of a pixel per character, that accumulate numerical errors.
will be visually misaligned from true position. This is evident with variable-width
text but some monospace fonts can cause "drift", fractions of a pixel per character, that accumulate numerical errors.

- **Good:** Menlo, Consolas, `monospace` (generic)
- **Bad:** Monaco

To test: type "A" 100+ times and move cursor to end. If misaligned, try a different font.

#### Tab Sanitization

Tab characters (`\t`) break grid alignment because browsers render them as variable-width. Buffee core does not sanitize input—if you set content containing tabs via `Model.s` or `Span.ins()`, they appear as-is.

**Solutions:**
- **BuffeeSanitize combinator** — Automatically converts tabs to spaces, removes zero-width characters, and normalizes multi-width Unicode spaces. See [Sanitize combinator](web/combinators.html#sanitize).
- **Pre-sanitize** — Clean your text before passing to Buffee: `text.replace(/\t/g, ' ')`

The keyboard controller already handles Tab key presses by inserting spaces (based on `Mode.s`), so typed tabs are not an issue—only programmatic content.

### CSS

[style.css](style.css) contains structural styles. Bring-your-own cursor and selection color:
Expand All @@ -74,7 +87,6 @@ Editor instances attach to a root node having such structure:

```html
<div class="buffee" id="editor">
<textarea class="buffee-clip" aria-hidden="true"></textarea>
<div class="no-select buffee-pane">
<!-- Can omit optional gutter rail -->
<div class="buffee-rail"></div>
Expand Down Expand Up @@ -110,9 +122,9 @@ const editor = new Buffee(document.getElementById("editor"), {});
Editor auto-fits to its container size. For fixed dimensions:

```javascript
new Buffee(el, { rows: 20 }); // Fixed row count
new Buffee(el, { cols: 80 }); // Fixed column width
new Buffee(el, { rows: 20, cols: 80 }); // Both fixed
new Buffee(el, { h: 20 }); // Fixed row count
new Buffee(el, { w: 80 }); // Fixed column width
new Buffee(el, { h: 20, w: 80 }); // Both fixed
```

Container should have explicit height inherit some percentage from parent.
Expand All @@ -125,24 +137,22 @@ Container should have explicit height inherit some percentage from parent.

**View** `editor.View` represents the virtual viewport

`editor.View._` is the buffer lines in view

**Span** `editor.Span` represents a text selection. Cursors are the special case of this where the
anchor and the head/dot are the same. Text editing operations are defined relative to this selection.

The controller are keyboard event handlers which route to operations on the selection. In the future, the basic controller will be refactored out of Buffee.js as an Extension such that you will have to bring-your-own controller by default. e.g. a "vim normal mode controller".
The controller are keyboard event handlers which route to operations on the selection. In the future, the basic controller will be refactored out of Buffee.js as a Combinator such that you will have to bring-your-own controller by default. e.g. a "vim normal mode controller".

See: [API Reference](docs/api.md) | [Getting Started](docs/onboarding.md)
See: [API Reference](docs/api.txt) | [Getting Started](docs/onboarding.md)

## Extensibility
## Combinators

Extensions use the decorator pattern - pure functions that wrap the editor, being an editor instance themselves, meaning they can be combined:
Combinators use the decorator pattern - pure functions that wrap the editor, being an editor instance themselves, meaning they can be combined:

```javascript
// Single extension
// Single combinator
const editor = BuffeeHistory(new Buffee(container, config));

// Multiple extensions (compose by nesting)
// Multiple combinators (compose by nesting)
const editor = BuffeeElementals(
BuffeeSyntax(
BuffeeHistory(
Expand All @@ -151,23 +161,24 @@ const editor = BuffeeElementals(
)
);

// Extensions expose APIs on the editor instance
// Combinators expose APIs on the editor instance
editor.History.undo();
editor.Syntax.setLanguage('javascript');
editor.Elementals.addButton({ row: 0, col: 0, label: 'OK' });
```

Available extensions:
Available combinators:
- **History** - Undo/redo with operation coalescing
- **UndoTree** - Tree-based undo that preserves all branches
- **Syntax** - Regex-based syntax highlighting
- **Elementals** - DOM-based UI elements (buttons, inputs)
- **TUI** - Terminal UI via text manipulation
- **FileLoader** - Multiple strategies for large file loading
- **UltraHighCapacity** - Gzip-compressed storage for 1B+ lines
- **iOS** - Touch and on-screen keyboard support
- **Sanitize** - Tab/Unicode normalization for programmatic content

See: [Extensions](docs/extensions.md)
See: [Dev Guide on Combinators](docs/combinators.md)
See: [Combinator Gallery](web/combinators.html)

## Versioning

Expand Down
Loading
Loading