a653903dba7a9c8679efc02b2f49932f7bc99af4
10 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a653903dba |
fix(html): keyword-in-heading badge + brackets in wikilink descriptions
Two export bugs reported against v0.4.0: 1. A heading whose text is a keyword (`== TODO ==`) rendered as an inline `<span class="todo">` badge with an *empty* id, instead of a styled header. Root causes: `inline_text` dropped Keyword nodes (so the heading id/anchor came out empty, or `My TODO list` → `My list`), and the keyword span was emitted inside the heading. Fix: `inline_text` now includes the keyword's literal text (via new `Keyword::label()`), and heading content renders keywords as plain text (flatten_keywords) so a keyword title looks like a header. Keyword badges still render in body text as before. 2. A `]` inside a wikilink description (e.g. `[[page|Task [B-1]]]`) closed the link at the first `]]`, truncating the description and leaking a stray `]`. The close-scan is now bracket-aware (find_wikilink_close): inner `[ ]` pairs are balanced so the link closes at the correct `]]`. Added regression tests for both. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
8fdfa9e256 |
fix(html): match vimwiki export output for headings, code fences, tags, anchors (#6)
Exported HTML diverged from upstream vimwiki's :VimwikiAll2HTML in ways that break custom templates' CSS/JS and deep-links. Bring the renderer to parity on the structural differences reported in #6: 1. Headings — restore vimwiki's structure: a wrapping `<div id="{hierarchical}">` (parent anchors joined by `-`), `class="header"`, and an in-heading `<a href="#{hierarchical}">` self-link. The flat `id` stays on the heading element so intra-page TOC / `#anchor` links keep resolving. Ancestor path is tracked while walking top-level headings. 2. Code fences — emit vimwiki's `<pre {raw-attrs}>` (the verbatim text after `{{{`, e.g. `<pre python>`) instead of `<pre><code class="language-X">`, so highlighters wired for vimwiki output apply. The fence text is now preserved verbatim through the lexer/AST (PreformattedNode.attrs). 3. Inline tag ids — drop the `tag-` prefix (`id="wiki"`, not `id="tag-wiki"`). Also fixes a real inconsistency: the LSP validated `[[Page#wiki]]` as resolvable while the HTML emitted `id="tag-wiki"`, so the exported link was broken. 4. Same-page anchors — `[[#Section]]` resolves to `index.html#Section` (current page filename + fragment), matching vimwiki, rather than a bare `#Section`. Also ship vimwiki's stock style.css verbatim as the default stylesheet (was a ~7-line minimal one) so exports look identical out of the box and the `.header`/`.tag`/`.toc`/`done*` classes are styled. Centered headings and the `<div class="toc">` Contents wrapper keep their existing form. Tests updated across core + lsp to the new output; added coverage for hierarchical ids, raw fence attrs, bare tag ids, and the same-page anchor filename. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
fc0d74bfbe |
fix(toc): honour toc_header/level in single-wiki config + div.toc on export
Two TOC bugs: 1. :NuwikiTOC ignored toc_header / toc_header_level (always "= Contents =" at level 1). In the single-wiki shorthand the server only carried file_extension/syntax from the top-level options into the synthesized wiki; every other per-wiki key (toc_header, toc_header_level, links_header, html_path, auto_export, …) was dropped. Add single_wiki_from_value(), which re-parses the top-level object as a full RawWiki (injecting root from wiki_root), so all per-wiki keys set at the top level flow through. Wired into from_init_params + apply_change. 2. HTML export put class="toc" on the <hN> element, but upstream vimwiki (and its stylesheet) wraps the TOC heading in <div class="toc">…</div>. render_heading now emits the div wrapper, matching upstream so .toc CSS applies. With (1) fixed, detection also works for a custom toc_header. Tests: single_wiki_shorthand_honours_top_level_per_wiki_keys (config), toc_header_heading_wrapped_in_div_toc + non_toc_heading_not_wrapped (renderer). Full suite 572 passed; clippy clean; config-parity goldens match. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
68f10971f7 |
fix(html): emit heading id anchors so exported #links resolve
Exported HTML anchor links (TOC entries, [[Page#Heading]], [[#Heading]]) went nowhere because heading elements carried no `id`. Worse, the two TOC builders slugified anchors (`#my-heading`) while the link resolver emits the raw heading text (`#My Heading`, matching upstream vimwiki), so even once ids existed the two halves wouldn't have agreed. Fix — adopt vimwiki's scheme (raw heading text as the anchor) everywhere: - render_heading emits `<hN id="<plain heading text>">`. - build_toc_html (HTML export TOC) uses the raw, HTML-escaped title for both the href and the link text (was slugify). - collect_toc_items (:VimwikiTOC buffer output) uses the raw title for the generated `[[#anchor]]` (was slugify). In-editor navigation slugifies both sides, so it still resolves. Consistency: add canonical `nuwiki_core::ast::inline_text()` and route the heading id, the HTML-TOC title, the buffer-TOC title, and `diagnostics::heading_text` through it — three duplicated extractors collapsed into one, so the anchor and its validation can't drift. Regression test: heading_id_matches_anchor_link_href (core) asserts the heading id and a `#anchor` link's href are identical. Updated the heading assertions in the renderer/export tests for the new `id=` attribute. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
3b92b11948 |
fix(review): close all 2026-06-03 codebase-review findings (R1-R18)
Resolves the 18 findings from the parallel codebase review, tracked in development/vimwiki-gap.md. Correctness / perf: - Wiki.config -> Arc<WikiConfig> so cloning a Wiki is a refcount bump (R5) - WorkspaceIndex::remove is no longer O(n^2): a per-source contributions map limits the scan to buckets the source actually wrote into (R6) - render_color now expands color_tag_template (__STYLE__/__CONTENT__), consuming the previously-dead field; ColorNode documented as an extension point; 3 renderer tests added (R3/R4) - wiki_root_for returns empty/nil on no-match instead of falling back to the first wiki (R2); auto_header honours links_space_char (R7) Cleanup / dedup: - Remove dead #[allow(dead_code)] stubs + uncalled pub helpers, narrow imports (R10/R11) - Dedup span_of_inline x3 -> InlineNode::span() (R12) - diary_step single read lock; page_captions single pass (R13) - Lua auto_header loop -> wiki_list(); detect_current_symbol cleanup (R14/R18) Client / docs: - :VimwikiNormalizeLink Vim cmds -> <q-args> (R17); ftplugin header fix (R16); vars.vim multi-wiki limitation documented (R15) - Document 19 config options in README.md + doc/nuwiki.txt; fix list_margin/shiftwidth doc and stale comments (R1/R9) - R8 investigated, confirmed not a real bug (documented) Verified: Neovim harness 307, Vim harness 301/18/21, Rust suite 568, all 0 failed; clippy clean; fresh parallel-agent audit found no regressions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
fa2d1b8b42 |
feat(keywords): add STOPPED keyword
Adds STOPPED alongside TODO/DONE/STARTED/FIXME/FIXED/XXX across the stack: lexer, AST Keyword enum, HTML renderer (class="stopped"), LSP keyword_str, and the Vim syntax red group (nuwikiKeywordAttn). Grouped with the attention/pending keywords (red) for both export and in-editor highlighting. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
e0f97a5caf |
fix(export): emit one CSS class per keyword for independent colouring
All keywords previously shared `class="todo"`, so a stylesheet couldn't distinguish e.g. red TODO from green DONE. Emit a distinct class per keyword (todo/done/started/fixme/fixed/xxx); TODO keeps the vimwiki `todo` class so stock vimwiki CSS still styles it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
e90bbab39e |
fix(export): render vimwiki-compatible HTML for templates, links, and tasks
Stock vimwiki templates and stylesheets rendered broken pages because the
HTML output diverged from vimwiki conventions on three fronts:
- Templates: the renderer only substituted nuwiki's `{{key}}` placeholders,
so vimwiki's `%title%`/`%content%`/`%root_path%`/`%date%`/`%wiki_css%`
passed through literally — dropping the body and breaking asset links.
Both delimiter styles are now recognised; `%wiki_css%` aliases the css var.
- Links: `[[todo.wiki]]` exported to `todo.wiki.html`. render_page_html now
takes the wiki file extension and strips it from wiki/interwiki targets
(via index::strip_wiki_extension) before the `.html` URL is built, matching
in-editor navigation. file:/local: links keep their literal extension.
- Tasks: checkbox items used bespoke `task-*` classes plus an `<input>`,
which double-rendered against vimwiki stylesheets. Emit `done0..done4`
(`[ ] [.] [o] [O] [X]`) and `rejected` (`[-]`) classes with no input — the
stylesheet draws the box.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
f4e086f981 |
refactor(tests): group test files by feature, drop phase/cluster naming
Restructures the integration test layout so each file is named after
what it covers, not the implementation phase it landed in.
nuwiki-core (renames only):
vimwiki_lexer → lexer
vimwiki_parser → parser
vimwiki_tags → tags
vimwiki_table_alignment → table_alignment
diary_period → diary
list_continuation → lists
transclusion_attrs → transclusion
+ table colspan/rowspan tests moved here from parity_cluster_1
nuwiki-lsp (renames + merges + one split):
cluster_a_list_rewriters → commands_lists
cluster_b_table_rewriters → commands_tables
cluster_c_link_helpers +
phase19_followlink_creates → commands_links
phase13_rename_commands → commands_files
phase17_colorize → commands_colorize
phase17_html_export → html_export
phase15_link_health → link_health
phase18_multi_wiki → multi_wiki
phase19_folding → folding
nav → navigation
lsp_helpers → helpers
phase16_diary +
diary_frequency → diary
phase11_plumbing +
parity_cluster_1 (config) → index_and_config
tags_index_and_lsp +
phase17_backfill → commands_tags
phase14_edit_commands → split into
commands_checkboxes,
commands_headings,
commands_tasks
Net: 30 → 28 integration-test files. 456 → 455 tests (the one
removed test was a dummy `paragraph_render_is_unchanged` whose only
purpose was to keep a `ParagraphNode` import alive in
parity_cluster_1; the import is exercised elsewhere now).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
f00b0780b8 |
phase 5: renderer trait + HtmlRenderer
Writer-based `Renderer` trait per SPEC §6.8: object-safe
`fn render(&self, doc, w: &mut dyn Write) -> io::Result<()>` plus
a `render_to_string` convenience. Object safety preserves the option
of `Box<dyn Renderer>` in the LSP layer.
`HtmlRenderer` builder accepts a link-resolution callback (via
`with_link_resolver`) and an optional enclosing template (via
`with_template`). The default resolver mirrors §9: Wiki paths become
`path.html`, interwiki links land in sibling directories
(`../wiki<N>/` / `../wn-<Name>/`), diary entries under `diary/`,
file/local schemes use literal paths, anchor-only collapses to `#`.
Renderer covers every AST node:
- block: heading (centered class), paragraph, hr, blockquote,
preformatted (`language-<lang>` class), math block (with
`\begin{env}` when an environment is set), lists (ordered/unordered
+ every checkbox state, plus recursive sublists), definition list
(dt/dd), table (thead/tbody driven by `is_header`, col/row span as
CSS class hooks), comment (as HTML comment with `--` neutralised),
error node (as `.parse-error` span)
- inline: strong/em + bold-italic, `<del>`, code (escaped),
`<sup>`/`<sub>`, math-inline wrapped in `\(...\)`, keyword spans
with per-keyword class, color spans, wikilink/external/raw URL
anchors, transclusion as `<img>` with sorted attrs
HTML escaping is byte-level (`<>&"'`). Template substitution replaces
`{{content}}` first so a body containing the literal `{{title}}`
isn't double-substituted.
Tests (31 new) cover every block + inline construct, every LinkKind
through the default resolver, HTML escaping, custom resolver
override, template with/without title metadata, and an end-to-end
smoke test on a multi-construct document.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|