de8b8fa30d3d7d77cb8f5e1a096fee1cffc8ae73
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
de8b8fa30d |
feat(13.1): colorize + color_dic → ColorNode renderer
Closes the last pending §13.1 entries: - **`nuwiki.colorize`** (client-side, Lua + VimL) — wraps the word at cursor (or the visual selection on Neovim) in an inline `<span style="color:%c">…</span>` template. Matches vimwiki's default `color_tag_template`. Bound to `<Leader>wc` in both normal and visual mode on both editor paths; the previous "deferred" stub is gone. - **`color_dic` → renderer** — `HtmlConfig` gains a `color_dic: HashMap<String, String>` field reading the same key out of `initializationOptions` / `didChangeConfiguration`. The HTML export path threads it into `HtmlRenderer::with_colors`; `ColorNode` now picks `style="color:<value>"` when the colour name is in the dict, falling back to the existing `class="color-<name>"` when it isn't. SPEC §13.1 is fully checked off — the table moved from "deferred sketch" to a per-command status table marking all 11 commands done, plus a note on the `color_dic` follow-up landing alongside. README's "Phase 14 list & table edit commands" row now reads ✅ without the deferred-subset caveat, and the §13.1-blocked text-objects note in the keymaps section is rephrased as "planned follow-ups". Tests: 4 new in `phase17_colorize.rs` covering the renderer fallback when the dict is empty, the inline-style emission for a listed name, the fallback path for an unlisted name in a populated dict, and the `initializationOptions` JSON shape. Total 414 Rust tests pass; clippy clean; keymap harness still 20/20. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d1b807b7d1 |
phase 17: html export commands + extended template vars
HtmlRenderer (nuwiki-core):
- `with_var(k, v)` / `with_vars(map)` add arbitrary `{{key}}`
substitution alongside the existing `{{title}}` / `{{content}}`.
Substitution order: content → title → user vars, so a rendered body
that happens to contain a literal `{{title}}` isn't double-processed.
WikiConfig (nuwiki-lsp/config):
- New `html: HtmlConfig` field with per-wiki export options matching
vimwiki's `g:vimwiki_*` keys: `html_path`, `template_path`,
`template_default`, `template_ext`, `template_date_format`,
`css_name`, `auto_export`, `html_filename_parameterization`,
`exclude_files`. Defaults: `<root>/_html` and `<root>/_templates`.
- `RawWiki` accepts all of the above through `initializationOptions`
(and `workspace/didChangeConfiguration` reload).
New `export` module (pure helpers):
- `output_path_for` — page name → on-disk HTML path. Slugifies only
the final segment when `html_filename_parameterization = true` so
the `diary/` subdir survives.
- `template_for` — primary/fallback path lookup tuple.
- `fallback_template` — minimal in-memory page used when neither
template file exists.
- `format_date` — strftime subset (`%Y`/`%m`/`%d`/`%%`) so we don't
depend on `chrono`/`time`.
- `build_toc_html` — nested `<ul class="toc">` from the doc's
headings, with HTML escaping.
- `compute_root_path` — `../` prefix per directory depth for
stylesheet hrefs in nested pages.
- `is_excluded` — glob matcher supporting `*`, `**`, `?`. Used by
the `allToHtml*` walker against `exclude_files`.
- `render_page_html` — wires the above into HtmlRenderer with
`{{date}}`, `{{root_path}}`, `{{toc}}`, `{{css}}` populated.
- `DEFAULT_CSS` — minimal stylesheet bundled for first-time exports.
New commands:
- `nuwiki.export.currentToHtml` — render the current buffer; honours
`%nohtml` and `%template`; ensures CSS exists.
- `nuwiki.export.allToHtml` — walk the wiki root, skip pages matched
by `exclude_files` and `%nohtml`, and only re-export pages whose
source is newer than the existing HTML (incremental behaviour
matching `:VimwikiAll2HTML`).
- `nuwiki.export.allToHtmlForce` — same but unconditional re-export.
- `nuwiki.export.browse` — alias of currentToHtml that returns the
`file://` URL of the rendered page in the response so the client
can open it.
- `nuwiki.export.rss` — write `<html_path>/rss.xml` listing the
wiki's diary entries newest-first.
- `did_save` handler — runs the auto-export equivalent when the
resolved wiki has `auto_export = true`.
LSP capability:
- `text_document_sync` switched from `Kind(FULL)` to `Options(...)`
so the server can register a `save` notification (otherwise
clients never push `did_save` events).
Tests: 33 new in `phase17_html_export.rs` covering HtmlConfig
defaults + JSON-shape config, the `format_date` subset (including
the `%%` escape and pass-through for unsupported specifiers),
root-path computation, output-path slugification rules, the glob
matcher (single-star, globstar, question-mark, non-match),
template_for primary/fallback selection, render_page_html for the
title/content/date/root_path triad and the override-by-extras flow,
and side-effecting disk paths (write_page creates parents, picks up
on-disk template, RSS is newest-first, ensure_css is idempotent).
Total 357 tests pass; fmt + clippy clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
e75ad6ca89 |
phase 16: diary path conventions + nav commands
Hand-rolled date primitive (no chrono/time dep) plus the diary
command surface that closes the `:VimwikiMakeDiaryNote` ergonomics gap.
nuwiki-core/src/date.rs:
- `DiaryDate { year, month, day }` with strict `YYYY-MM-DD` parsing
(rejects missing zero-padding, alternate separators, whitespace,
impossible calendar dates including the leap-year exceptions).
- `next_day` / `prev_day` via Howard Hinnant's days-from-civil
algorithm — proleptic Gregorian, walks across month/year/leap-day
boundaries.
- `today_utc()` from `SystemTime::now()`. UTC-only by design: a
local-tz implementation would need a tz database we don't ship.
- `Ord` by epoch days, `Display`/`format` round-trip with `parse`.
WikiConfig (P15 resolution):
- `diary_rel_path: String` (default `"diary"`) — mirrors vimwiki's
`g:vimwiki_diary_rel_path`.
- `diary_index: String` (default `"diary"`) — the stem inside the
diary subdir.
- `diary_dir()`, `diary_index_path()`, `diary_path_for(date)` —
centralise the path math so commands stay declarative.
- `RawWiki` (init-options wire format) accepts both fields, so users
with `g:vimwiki_diary_rel_path = "journal"` migrate cleanly.
WorkspaceIndex:
- New `diary_rel_path: Option<String>` field set by `Wiki::new`.
- `IndexedPage.diary_date: Option<DiaryDate>` — populated in `upsert`
when the URI is under `<root>/<diary_rel_path>/` and the stem
parses. `diary_date_for_uri` is the standalone classifier.
- The classifier *requires* the URI to be inside the diary subdir
when a root is known; with no root it accepts any file whose stem
is a date (kept for the ad-hoc test/scratch case).
nuwiki-lsp/src/diary.rs:
- `uri_for_date` / `index_uri` — bridge from `DiaryDate` and config
to `file://` URIs.
- `list_entries(index) → Vec<DiaryEntry>` — ascending, plus
`list_entries_filtered(year, month)` for calendar hooks.
- `next_entry` / `prev_entry` — strict less-than/greater-than
comparison so navigating from a non-diary page (uses today as
pivot) still moves to the right entry.
- `build_index_body` — newest-first, grouped under `== YYYY ==` /
`=== Month ===` subheadings, emits `- [[diary/YYYY-MM-DD]]`. Matches
`:VimwikiDiaryGenerateLinks`.
- `DiaryEntry` JSON shape: `{ date: "YYYY-MM-DD", uri }`. Manual
serde impl so DiaryDate stays serde-free in nuwiki-core.
Commands (9 new):
- `nuwiki.diary.openToday` / `openYesterday` / `openTomorrow` →
`{ uri, date }`.
- `nuwiki.diary.openIndex` → `{ uri }`.
- `nuwiki.diary.generateIndex` → WorkspaceEdit. Three paths:
live document in `backend.documents` → full-doc replace; on-disk
index → read + full-doc replace; missing → CreateFile + insert.
- `nuwiki.diary.next` / `prev` → pivots on the current page's
`diary_date`, falls back to today.
- `nuwiki.diary.listEntries` → optional `year` / `month` filter.
- `nuwiki.diary.openForDate` → strict `YYYY-MM-DD` arg.
All commands accept an optional `uri` to scope to a particular wiki
when multi-wiki lands; the dispatcher falls back to `default_wiki()`.
Tests: 35 new in `phase16_diary.rs` (date parser exhaustively,
calendar arithmetic across boundaries + leaps, path conventions,
upsert classification including the "date filename outside diary dir"
no-op case, list/filter/nav, index body grouping, serde shape, command
list completeness). Total 309 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
ea574f23f8 |
phase 11: plumbing prereqs — Wiki, edits, config, snapshot, diags
Cross-cutting infrastructure that every v1.1 phase depends on. Lands as a numbered phase before any user-visible feature so Phases 12–19 stay mechanical. 5 pieces: - `config.rs` — `Config` + `WikiConfig` + `DiagnosticConfig` + `LinkSeverity`. Serde-deserialised from `initialization_options`. v1.0 single-wiki shape (`wiki_root` + `file_extension` + `syntax`) desugars to one-entry `wikis = [...]` per P16. `~/...` expansion without pulling in `dirs`. Fallbacks: workspace_folders[0] → deprecated root_uri → empty list. - `wiki.rs` — `Wiki` aggregate (id + WikiConfig + Arc<RwLock<Index>>). `build_wikis(&[WikiConfig])` materialises the list; `resolve_uri_to_wiki` picks the longest-prefix root match so nested wikis route correctly. Single-entry today, multi-entry once Phase 18 lands. - `edits.rs` — `WorkspaceEditBuilder` + `text_edit_replace/insert/delete` + `op_rename/delete/create`. Handles the UTF-8/UTF-16 conversion at the span boundary so each Phase 13+ command stays a 3-liner. Builder picks `documentChanges` when file ops are present (LSP requires it), `changes` map otherwise (works for LSP 3.15- clients). File ops precede content edits in the output so created/renamed files exist when edits apply. `DeleteFile` is built without `annotation_id` — lsp-types 0.94.x ships it that way; later versions added the field. - `Backend` refactor — `index: Arc<RwLock<WorkspaceIndex>>` replaced by `wikis: Arc<RwLock<Vec<Wiki>>>` + `config: Arc<RwLock<Config>>`. New `wiki(id)` / `default_wiki()` / `wiki_for_uri(uri)` helpers. Every v1.0 handler (definition, references, hover, completion, workspace/symbol, update_document) goes through `wiki_for_uri`. `initialize` builds wikis from `Config::from_init_params`; `initialized` spawns one indexer task per wiki with the existing `window/workDoneProgress` wrapper. New `did_change_configuration` handler re-applies settings (rebuild semantics revisited in Phase 18). The old `workspace_root_from_params` helper is gone. - `read_or_open` + `DocSnapshot` (scaffolded, `#[allow(dead_code)]` until Phase 13's `workspace/rename` consumes it). Returns the live document when held in the documents map, otherwise async-reads from disk and re-parses so cross-document operations get accurate text and spans instead of trusting stale `WorkspaceIndex` data. - `collect_diagnostics` composable collector. Same `ErrorNode` walk today; takes `Option<&WorkspaceIndex>` + `page_name` + `&DiagnosticConfig` so Phase 15 can drop a link-health source in without further refactor. `ast_diagnostics` kept as a thin wrapper for the v1.0 test surface. New deps: `serde` + `serde_json` (already transitive through tower-lsp; elevated to direct deps for clarity and stability). `tokio` gains the `fs` feature for `read_or_open`'s async disk read. Tests (19 new in `phase11_plumbing.rs`): - Edits: UTF-8 passthrough + UTF-16 conversion (`héllo`), insert/delete shape, builder mode selection, file-op accumulation, `op_create` round-trip - Config: defaults, v1.0 desugar, explicit list overrides legacy, empty JSON, invalid JSON preserves prior state - Wiki: sequential id assignment, longest-prefix resolution, no-match, `Wiki::contains` - Diagnostics: error-node composition, link-health stub returns empty in Phase 11 All 172 v1.0 tests still pass — backward compatible. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |