Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
7266032
feat: implement Phase 1 — extension scaffold, language promotion, Tex…
claude Feb 23, 2026
6b3ceb7
feat: implement Phase 2 — dynamic due date proximity decorator
claude Feb 24, 2026
905fb0a
ci: add GitHub Actions workflow for lint, type-check, build, and package
claude Feb 24, 2026
2262dd0
fix(ci): fix failing setup-node cache + auto-commit lockfile on first…
claude Feb 24, 2026
556572c
chore: commit generated pnpm-lock.yaml
github-actions[bot] Feb 24, 2026
ac73667
fix(lint): disable base no-unused-vars; fix prettier alignment
claude Feb 24, 2026
2a6d57a
fix(lint): add env:node and disable no-undef
claude Feb 24, 2026
d42fb40
fix(format): collapse setTextDocumentLanguage call to one line
claude Feb 24, 2026
c4ef2d3
fix(grammar): use injection grammar so inline patterns fire within ma…
jimblom Feb 27, 2026
9888006
feat: Phase 3 — full decorator coverage, configurable colors, dev setup
jimblom Feb 27, 2026
8fe81a0
fix(format): run prettier on dueDateDecorator.ts
jimblom Feb 28, 2026
6947244
feat: migrate color settings to shared hexfield.colors.* namespace
jimblom Feb 28, 2026
7415668
feat: per-project tag coloring from hexfield-deck.projects config
jimblom Feb 28, 2026
a78029c
Pulling back target version for now.
jimblom Feb 28, 2026
474c973
docs: add Hexfield ecosystem section to README and USER_GUIDE
jimblom Feb 28, 2026
ca89ba2
chore: bump to v1.0.0, consolidate CHANGELOG for release
jimblom Mar 1, 2026
7e61ca7
chore: set version to 0.1.0 for initial release
jimblom Mar 2, 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
24 changes: 24 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2022,
"sourceType": "module",
"project": "./tsconfig.json"
},
"env": {
"node": true
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"no-unused-vars": "off",
"no-undef": "off",
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
"@typescript-eslint/explicit-function-return-type": "warn",
"no-console": "warn"
}
}
86 changes: 86 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: CI

on:
push:
branches:
- main
- 'claude/**'
pull_request:
branches:
- main

jobs:
ci:
name: Lint · type-check · build · package
runs-on: ubuntu-latest
permissions:
contents: write # write needed to commit pnpm-lock.yaml on first bootstrap run

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
version: 9

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20.11.0'
# No cache: 'pnpm' here — that requires pnpm-lock.yaml to already exist.
# We cache the pnpm store directly below, which works with or without a lockfile.

- name: Get pnpm store path
id: pnpm-store
run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"

- name: Cache pnpm store
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-store.outputs.path }}
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-

- name: Install dependencies
run: pnpm install

# On the first push after bootstrapping there is no lockfile in the repo.
# pnpm install generates one; this step commits it back so future runs get
# a fully deterministic, cacheable install. github-actions[bot] commits do
# not re-trigger CI, so there is no infinite loop.
- name: Commit lockfile if newly generated
if: github.event_name == 'push'
run: |
if ! git ls-files --error-unmatch pnpm-lock.yaml > /dev/null 2>&1; then
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git add pnpm-lock.yaml
git commit -m "chore: commit generated pnpm-lock.yaml"
git push
fi

- name: Check formatting
run: pnpm format:check

- name: Lint
run: pnpm lint

- name: Type-check
run: pnpm typecheck

- name: Build
run: pnpm build

- name: Package (.vsix)
run: pnpm package

- name: Upload .vsix artifact
uses: actions/upload-artifact@v4
with:
name: hexfield-text-${{ github.sha }}
path: '*.vsix'
retention-days: 30
if-no-files-found: error
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
dist/
*.vsix
out/
.DS_Store
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2
}
7 changes: 7 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"editorconfig.editorconfig"
]
}
17 changes: 17 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "pnpm: build"
}
]
}
47 changes: 47 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
// Editor
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"editor.tabSize": 4,
"editor.insertSpaces": true,

// Files
"files.eol": "\n",
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"files.exclude": {
"**/.git": true,
"**/node_modules": true,
"**/dist": true,
"**/*.tsbuildinfo": true
},

// TypeScript
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,

// Search
"search.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/pnpm-lock.yaml": true
},

// Hexfield Text — token color defaults for development
// These ensure grammar scopes render correctly regardless of active theme.
"editor.tokenColorCustomizations": {
"textMateRules": [
{ "scope": "entity.name.tag.hexfield", "settings": { "foreground": "#569CD6" } },
{ "scope": "string.quoted.hexfield.date", "settings": { "foreground": "#858585" } },
{ "scope": "keyword.operator.hexfield.priority.high", "settings": { "foreground": "#F44747" } },
{ "scope": "keyword.operator.hexfield.priority.medium", "settings": { "foreground": "#CCA700" } },
{ "scope": "keyword.operator.hexfield.priority.low", "settings": { "foreground": "#89D185" } },
{ "scope": "constant.numeric.hexfield.estimate", "settings": { "foreground": "#4EC9B0" } },
{ "scope": "markup.changed.hexfield.checkbox", "settings": { "foreground": "#CE9178" } },
{ "scope": "keyword.other.hexfield.frontmatter", "settings": { "foreground": "#C586C0" } }
]
}
}
12 changes: 12 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"command": "pnpm build",
"group": "build",
"label": "pnpm: build",
"problemMatcher": ["$esbuild"]
}
]
}
14 changes: 14 additions & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.vscode/**
src/**
node_modules/**
examples/**
.eslintrc.json
.prettierrc
tsconfig.json
esbuild.js
pnpm-lock.yaml
*.map
.gitignore
**/*.ts
!dist/**
IMPLEMENTATION_PLAN.md
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Changelog

All notable changes to Hexfield Text are documented here. Dates are in `YYYY-MM-DD` format.

---

## [0.1.0] — 2026-03-01

Initial public release.

### Added

- **Language promotion** — `.md` files with `type: hexfield-planner` in their YAML frontmatter are promoted to the `hexfield-markdown` language mode. Removing or changing the field reverts immediately — no VS Code reload needed.

- **TextMate grammar** — an injection grammar colorizes Hexfield tokens inside markdown list items, paragraphs, and other block-level scopes where a top-level grammar include cannot reach:
- Project tags (`#project`)
- Priority markers (`!!!` / `!!` / `!`)
- Time estimates (`est:2h`, `est:30m`)
- In-progress checkbox (`[/]`)
- Frontmatter keys (`type`, `week`, `year`, `quarter`, `tags`, `startDate`, `endDate`)

- **Decoration API — theme-independent token colors** — all inline tokens are colored via VS Code's Decoration API rather than relying on theme scope mappings. Colors are absolute; no theme (Dracula, One Dark, etc.) can override them:
- Project tags — blue pill border (`#569CD6` default)
- Priority HIGH / MED / LOW — red / yellow / green
- Time estimates — teal
- In-progress checkbox (`[/]`) — orange
- Due dates — dynamically colored by proximity to today:
- Overdue → red (`#F44747`)
- Today → orange (`#CE9178`)
- Within 3 days → yellow (`#CCA700`)
- Future → gray (`#858585`)

- **Per-project tag colors** — `#project-tag` tokens read `hexfield-deck.projects.<name>.color` from VS Code settings. Each project renders in its configured color with a matching pill border. Tags without a configured color fall back to the `hexfield.colors.projectTag` default.

- **Shared configuration namespace** — all 10 token colors are user-configurable under `hexfield.colors.*`. This namespace is shared with Hexfield Deck; configure colors once and every installed Hexfield component responds. Changes take effect live with no reload.

- **Ecosystem documentation** — README and User Guide document the Hexfield component model: the shared file format, shared configuration architecture, and design principles for independently-installable components.

- Published to VS Code Marketplace as `jimblom.hexfield-text`.

31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,38 @@ See the [Hexfield Deck User Guide](https://github.com/jimblom/Hexfield-Deck/blob

---

## 🛰️ The Hexfield Ecosystem

Hexfield Text is one component in a growing family of tools built around the Hexfield planner file format. Each component does one thing and composes cleanly with the others — no hard dependencies, no mandatory install order.

### The connective tissue

Every Hexfield component is anchored to the same two things:

**The file format** — a plain markdown file with `type: hexfield-planner` in its YAML frontmatter. That single field is what identifies a Hexfield file. Any component can detect it, none of them own it.

**The shared configuration namespace** — `hexfield.colors.*` for token colors, `hexfield-deck.projects.*` for per-project settings. Components contribute to and read from the same VS Code settings keys. Configure colors once; every installed component responds.

### Current components

| Component | What it does |
|---|---|
| **[Hexfield Deck](https://github.com/jimblom/Hexfield-Deck)** | Kanban board view — renders your planner file as a visual task board with card drag-and-drop, project filtering, and badge coloring |
| **Hexfield Text** _(this extension)_ | Editor view — colorizes planner metadata inline so the source file reflects the same visual language as the board |

### Design principles

- **Independently installable.** Each component works without the others present. Hexfield Text colorizes tags even if Hexfield Deck isn't installed; it just uses the default color.
- **Loosely coupled.** Components communicate through shared VS Code settings, not direct APIs or shared code. A new component can join the ecosystem by reading the same config keys.
- **Same file, different views.** A planner file is just a markdown file. Every component is a different lens on the same data — board view, editor view, and whatever comes next.

---

## 🎬 About the Name

**Hexfield Text** is part of the Hexfield product family, named after the **Hexfield Viewscreen** on the Satellite of Love from _Mystery Science Theater 3000_ — the ship's iconic hexagonal display and communication screen.
Hexfield is named after the **Hexfield Viewscreen** on the Satellite of Love from _Mystery Science Theater 3000_ — the ship's iconic hexagonal display and communication screen. Each component is a different panel on that display.

**Hexfield Deck** is the board view. **Hexfield Text** is the editor layer of the same interface — the source-level view of your planner data, brought to visual life.
**Hexfield Deck** is the board. **Hexfield Text** is the editor. The Satellite of Love runs on more than one screen.

---

Expand Down
51 changes: 32 additions & 19 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,28 +187,35 @@ Due date brackets (`[YYYY-MM-DD]`) are colorized by the Decoration API at runtim

## Configuration

> Token color configuration is planned for v1.0.0 (Phase 3). The settings listed here describe the intended behavior.
All token colors are applied by the Decoration API and are fully user-configurable. In VS Code Settings (`Ctrl+,`), search for **hexfield-text** to access:

In VS Code Settings (`Ctrl+,`), search for **hexfield-text** to access:
| Setting | Default | Token |
|---|---|---|
| `hexfield.colors.projectTag` | `#569CD6` | `#project-tag` |
| `hexfield.colors.priorityHigh` | `#F44747` | `!!!` |
| `hexfield.colors.priorityMed` | `#CCA700` | `!!` |
| `hexfield.colors.priorityLow` | `#89D185` | `!` |
| `hexfield.colors.timeEstimate` | `#4EC9B0` | `est:2h` / `est:30m` |
| `hexfield.colors.inProgressCheckbox` | `#CE9178` | `[/]` |
| `hexfield.colors.dueDateOverdue` | `#F44747` | `[YYYY-MM-DD]` — overdue |
| `hexfield.colors.dueDateToday` | `#CE9178` | `[YYYY-MM-DD]` — today |
| `hexfield.colors.dueDateSoon` | `#CCA700` | `[YYYY-MM-DD]` — within 3 days |
| `hexfield.colors.dueDateFuture` | `#858585` | `[YYYY-MM-DD]` — future |

All colors override the active VS Code theme — they match the Hexfield Deck board palette exactly. Changes take effect immediately with no reload needed.

### Frontmatter Key Colors

Frontmatter keys (`type`, `week`, `year`, etc.) are colored by the TextMate grammar and follow your active theme. To override them, add to your `settings.json`:

```json
{
"hexfield-text.colors.projectTag": "#569CD6",
"hexfield-text.colors.priorityHigh": "#F44747",
"hexfield-text.colors.priorityMed": "#CCA700",
"hexfield-text.colors.priorityLow": "#89D185",
"hexfield-text.colors.timeEstimate": "#4EC9B0",
"hexfield-text.colors.inProgressCheckbox": "#CE9178",
"hexfield-text.colors.frontmatterKey": "#C586C0",
"hexfield-text.colors.dueDateOverdue": "#F44747",
"hexfield-text.colors.dueDateToday": "#CE9178",
"hexfield-text.colors.dueDateSoon": "#CCA700",
"hexfield-text.colors.dueDateFuture": "#858585"
"editor.tokenColorCustomizations": {
"textMateRules": [
{ "scope": "keyword.other.hexfield.frontmatter", "settings": { "foreground": "#C586C0" } }
]
}
```

All settings have defaults matching the values in the Token Reference above. Any setting left unset uses the default.

---

## How Scoping Works
Expand Down Expand Up @@ -273,7 +280,13 @@ This should not happen with correct usage. If it does:

---

## Related
## The Hexfield Ecosystem

Hexfield Text is one component in a family of tools built around the Hexfield planner file format. Components share a configuration namespace (`hexfield.colors.*`, `hexfield-deck.projects.*`) and are independently installable — each works without the others present.

| Component | Role |
|---|---|
| **[Hexfield Deck](https://github.com/jimblom/Hexfield-Deck)** | Kanban board view of your planner file |
| **Hexfield Text** | Inline colorization in the markdown editor |

- [Hexfield Deck](https://github.com/jimblom/Hexfield-Deck) — The companion kanban board extension
- [Hexfield Deck User Guide](https://github.com/jimblom/Hexfield-Deck/blob/main/USER_GUIDE.md) — Full planner file format reference
See the [Hexfield Deck User Guide](https://github.com/jimblom/Hexfield-Deck/blob/main/USER_GUIDE.md) for the complete planner file format reference.
Loading