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
58 changes: 57 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,63 @@ listed under a **Changed** or **Removed** heading.

## [Unreleased]

## [0.6.3] - 2026-08-24

### Added

- **Three more templates**, so the catalogue is a catalogue: `wave` (one clean
sine across the year), `pulse` (a heartbeat trace, a spike every few weeks)
and `invader` (a space invader, centred). Each is 51 columns, which keeps
every lit day clear of the two partial weeks at the ends of a year, and each
is drawn in `{0, 2, 4}` — the only three shades no reader has to squint at.

- **Two gates on template art**, which matter now that
[#57](https://github.com/vyncint/mossaic/issues/57) invites contributions.
`every_template_reads_clearly` measures the closest pair of shades in every
template and fails anything that is not *clear*: a picture using `2` and `3`
looks two-toned in the `.art` file, because the digits differ, and reads as
one flat colour on github.com. `no_template_overhangs_the_year` fails a
template that loses a lit day off either end of any year. Both were checked
against art planted to break them.

### Changed

- **`mossaic-art --help` is grouped rather than a list of thirty flags.** The
options now sit under *what to draw*, *where it goes*, *tracking*, *making
the commits* and *output*, with the usage and seven examples first. The
colour-theory paragraph that lived inside `--background` moved to
[docs/ART.md](docs/ART.md), where there is room to say it properly. Shorter
overall (93 lines against 113) and no flag was dropped.

- **Counts read as English.** Every user-facing count said `1 template(s)`,
`6 cell(s)`, `59 day(s)` — twenty-nine of them, on the first lines a new
user reads and in the markdown the GitHub Action posts. They now agree with
their number, verb included: *1 day is short*, *2 days are short*.

- **The description says what mossaic is.** It never mentioned the terminal.

### Fixed

- **The one shipped template no longer warns on every single year.** Drawing
`--template dragon` printed `note: 6 cell(s) fell outside 2027 and were
dropped` for 2025 through 2029 — and all six were *blank* margin, so nothing
was lost. `Canvas::place` counted every cell that fell outside the year,
lit or not. It now counts only the cells that would have been drawn, so the
note appears when a shade is genuinely lost and stays quiet otherwise.

Found by running the flagship path and reading what it printed.

- **A missing `--file` in a script names the file, not the terminal.** The
chart claims the terminal before it reads the calendar, so
`mossaic --file typo.json` in CI reported `needs an interactive terminal` —
true, and no help at all in finding the typo. With a terminal the behaviour
is unchanged: the error is shown *in* the chart with `r` to retry, which is
better than exiting.

- **`--font` no longer tells its readers to edit `src/art.rs`.** It printed a
note meant for contributors to everyone who ran it.


- **`brew install vyncint/tap/mossaic`.** The formula is generated by the
release itself from the checksums the archives produced, so it cannot
describe an archive that was never built, and a hand-edit in the tap is
Expand Down Expand Up @@ -861,7 +916,8 @@ there was none.

[termlens]: https://github.com/vyncint/termlens

[Unreleased]: https://github.com/vyncint/mossaic/compare/v0.6.2...HEAD
[Unreleased]: https://github.com/vyncint/mossaic/compare/v0.6.3...HEAD
[0.6.3]: https://github.com/vyncint/mossaic/compare/v0.6.2...v0.6.3
[0.6.2]: https://github.com/vyncint/mossaic/compare/v0.6.1...v0.6.2
[0.6.1]: https://github.com/vyncint/mossaic/compare/v0.6.0...v0.6.1
[0.6.0]: https://github.com/vyncint/mossaic/compare/v0.5.0...v0.6.0
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.

9 changes: 6 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
[package]
name = "mossaic"
version = "0.6.2"
version = "0.6.3"
edition = "2021"
# Minimum supported Rust version. Verified by the `msrv` CI job, which reads this
# field; bumping it is a minor (not patch) change.
#
# 1.88 is dictated by ratatui 0.30. Everything else in the tree needs less: the
# graphics and colour code is plain std.
rust-version = "1.88"
description = "Plan and track GitHub contribution art — what today owes to draw your name by December, and whether the year can still be drawn at all"
keywords = ["github", "contributions", "contribution-art", "sixel", "kitty"]
description = "Draw pixel art in your GitHub contribution graph — a terminal chart, an editor, and a planner that says what today owes"
# `tui` earns its place over `contributions`, which `contribution-art` already
# covers: the chart, the designer and the glyph viewer are all terminal UIs, and
# that is how someone looking for one searches.
keywords = ["github", "contribution-art", "tui", "sixel", "kitty"]
categories = ["command-line-utilities", "visualization"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/vyncint/mossaic"
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ That is `--template dragon` on 2027 — 146 days, 442 commits — drawn by the s
rasteriser that draws the chart, so it is what the graph will actually look
like rather than an impression of it.

Four templates ship with it — `dragon`, `wave`, `pulse` and `invader` — and
each is a seven-line text file you can copy and edit.

```sh
mossaic-art --list-templates # what there is, with thumbnails
mossaic-art --template dragon --year 2027 # draw one, and see what it costs
Expand Down
6 changes: 3 additions & 3 deletions action/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: art
uses: vyncint/mossaic/action@v0.6.0
uses: vyncint/mossaic/action@v0.6.3
with:
text: VYNCINT
year: "2027"
Expand Down Expand Up @@ -84,7 +84,7 @@ drawn. The rest are the same either way.

```yaml
- id: art
uses: vyncint/mossaic/action@v0.6.0
uses: vyncint/mossaic/action@v0.6.3
with:
template: dragon
year: "2027"
Expand Down Expand Up @@ -216,7 +216,7 @@ on 290 days of the year is a job nobody reads.

## Notes

- **Two knobs, two jobs.** The ref you pin (`@v0.6.0`, `@main`) chooses the
- **Two knobs, two jobs.** The ref you pin (`@v0.6.3`, `@main`) chooses the
*action's steps* — the glue that runs the tracker and shapes the outputs.
The `version` input chooses the *tracker itself*, straight from crates.io.
The default, `latest`, is fine for a daily report; pin a number when you
Expand Down
2 changes: 1 addition & 1 deletion action/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ inputs:
default: "true"
version:
description: >-
Which mossaic release runs the tracking, e.g. "0.6.0". The default,
Which mossaic release runs the tracking, e.g. "0.6.3". The default,
`latest`, installs the newest release on crates.io each run — fine for
tracking, since the report format is versioned with the crate. Pin a
number if you want the tracker to change only when you say so.
Expand Down
4 changes: 2 additions & 2 deletions action/track.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: art
uses: vyncint/mossaic/action@v0.6.0
uses: vyncint/mossaic/action@v0.6.3
with:
text: VYNCINT
year: "2027"
Expand All @@ -39,7 +39,7 @@ jobs:
# the failure notification you already get does the reminding.
fail-on: never
# Which mossaic release does the tracking. The default, latest,
# follows crates.io; pin a number ("0.6.0") to freeze it.
# follows crates.io; pin a number ("0.6.3") to freeze it.
# version: latest

# ----------------------------------------------------------------- issue
Expand Down
11 changes: 11 additions & 0 deletions art/templates/invader.art
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# name: Invader
# author: @vyncint
# description: A space invader, centred on the year

000000000000000000000040000400000000000000000000000
000000000000000000000004444000000000000000000000000
000000000000000000000044044400000000000000000000000
000000000000000000004444444444000000000000000000000
000000000000000000004044444404000000000000000000000
000000000000000000004040000404000000000000000000000
000000000000000000000004004000000000000000000000000
11 changes: 11 additions & 0 deletions art/templates/pulse.art
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# name: Pulse
# author: @vyncint
# description: A heartbeat trace across the year: a quiet line, a spike every few weeks

000000004400000000000000044000000000000000440000000
000000004400000000000000044000000000000000440000000
000004204404200000000042044042000000000420440420000
222224244424222222222242444242222222222424442422222
000000044420000000000000444200000000000004442000000
000000000420000000000000004200000000000000042000000
000000000000000000000000000000000000000000000000000
11 changes: 11 additions & 0 deletions art/templates/wave.art
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# name: Wave
# author: @vyncint
# description: One clean sine wave rolling across the whole year

000000000444444444000000000000000000000000000000000
000004444400000004444400000000000000000000000000000
004444000000000000000444400000000000000000000000000
444000000000000000000000444400000000000000000000044
000000000000000000000000000444400000000000000044440
000000000000000000000000000000444440000000444440000
000000000000000000000000000000000044444444400000000
15 changes: 14 additions & 1 deletion docs/ART.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,19 @@ mossaic-art --list-templates # what there is, with thumbnails
mossaic-art --template dragon --year 2027 # draw one
```

Four ship with it, and every one of them is a file in
[`art/templates/`](../art/templates):

| name | what it is |
|---|---|
| `dragon` | a serpentine dragon coiling across the whole year |
| `wave` | one clean sine rolling across the year |
| `pulse` | a heartbeat trace: a quiet line, a spike every few weeks |
| `invader` | a space invader, centred |

They are worth reading as much as drawing: each is seven lines of digits, and
copying one into your own file is the quickest way to start.

```
Dragon · 2027 · 53 of 53 columns · 146 days · 442 commits

Expand Down Expand Up @@ -494,7 +507,7 @@ arrive rather than be asked for:

```yaml
- id: art
uses: vyncint/mossaic/action@v0.6.0
uses: vyncint/mossaic/action@v0.6.3
with:
text: VYNCINT
year: "2027"
Expand Down
29 changes: 17 additions & 12 deletions src/art.rs
Original file line number Diff line number Diff line change
Expand Up @@ -916,10 +916,15 @@ impl Canvas {
/// Lay the canvas on a year and report the shade each day should end at.
///
/// `start` is the calendar column the canvas's first column lands on.
/// Columns that fall outside the year are counted in the returned total
/// rather than silently dropped — the first and last calendar columns are
/// partial weeks, so a full-width picture always loses a few days at the
/// ends and the caller should be able to say so.
/// The returned total counts the cells that fell outside the year and
/// **would have been drawn** — the first and last calendar columns are
/// partial weeks, so a full-width picture overhangs them.
///
/// Blank cells are not counted, because losing one costs the picture
/// nothing. Counting them meant a 53-column template warned about six
/// dropped cells on every year, all six of them empty margin: a `note:`
/// on the path everybody takes, which teaches people to stop reading
/// notes. What is worth interrupting for is a *shade* that will not fit.
///
/// Returns the level for **every** day it covers, including the level-0
/// ones. That is the difference between a canvas and text: a dark day
Expand All @@ -930,19 +935,19 @@ impl Canvas {
let mut levels = BTreeMap::new();
let mut skipped = 0;
for (offset, column) in self.columns.iter().enumerate() {
let Some(week) = start.checked_add(offset) else {
skipped += CANVAS_ROWS;
continue;
let week = match start.checked_add(offset) {
Some(week) if week < grid.weeks => week,
// Past the end of the year: nothing in this column lands.
_ => {
skipped += column.iter().filter(|level| **level > 0).count();
continue;
}
};
if week >= grid.weeks {
skipped += CANVAS_ROWS;
continue;
}
for (row, level) in column.iter().enumerate() {
let date = grid.date_at(week, row);
if grid.holds(date) {
levels.insert(date, *level);
} else {
} else if *level > 0 {
skipped += 1;
}
}
Expand Down
Loading