feat(config): on-save autoregen family — links/tags/diary-index (P2)
CI / cargo fmt --check (push) Successful in 17s
CI / cargo clippy (push) Successful in 38s
CI / cargo test (push) Successful in 41s
CI / editor keymaps (push) Successful in 1m25s

Added per-wiki auto_generate_links, auto_generate_tags, auto_diary_index
(default false, like upstream), wired into the did_save hook mirroring
auto_toc:

- auto_generate_links / auto_generate_tags rebuild the Generated Links /
  Generated Tags section ONLY when it already exists (new
  links_rebuild_edit / tag_links_rebuild_edit, like toc_rebuild_edit) — never
  inserts one into a page that lacks it.
- auto_diary_index regenerates the diary index page when a dated diary entry
  (not the index itself) is saved, via diary_generate_index_edit (handles the
  index file open / on-disk / absent).

auto_tags is recorded as an intentional divergence: nuwiki re-indexes tags on
every change, so the tag metadata is always fresh (no on-disk file to update).

Tests: links_rebuild_edit_only_acts_when_section_present,
tag_links_rebuild_edit_only_acts_when_index_present, config round-trip +
defaults. README/doc/lua comment updated. fmt/clippy clean; 0 Rust failures.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 18:55:51 +00:00
parent 3fd04b0efa
commit 09b5a2bd46
10 changed files with 255 additions and 3 deletions
+78
View File
@@ -635,6 +635,84 @@ impl LanguageServer for Backend {
}
}
let utf8 = self.use_utf8.load(Ordering::Relaxed);
// `auto_generate_links`: rebuild an existing `Generated Links` section.
if wiki.config.auto_generate_links {
let edit = self.documents.get(&uri).and_then(|doc| {
let current = index::page_name_from_uri(&uri, Some(&wiki.config.root));
let pages = wiki
.index
.read()
.ok()
.map(|i| i.page_names())
.unwrap_or_default();
commands::ops::links_rebuild_edit(
&doc.text,
&doc.ast,
&uri,
&current,
&pages,
utf8,
&wiki.config.links_header,
wiki.config.links_header_level,
)
});
if let Some(edit) = edit {
let _ = self.client.apply_edit(edit).await;
}
}
// `auto_generate_tags`: rebuild an existing `Generated Tags` index.
if wiki.config.auto_generate_tags {
let edit = self.documents.get(&uri).and_then(|doc| {
let snap = wiki
.index
.read()
.ok()
.map(|i| commands::ops::tag_pages_snapshot(&i))
.unwrap_or_default();
commands::ops::tag_links_rebuild_edit(
&doc.text,
&doc.ast,
&uri,
&snap,
utf8,
&wiki.config.tags_header,
wiki.config.tags_header_level,
)
});
if let Some(edit) = edit {
let _ = self.client.apply_edit(edit).await;
}
}
// `auto_diary_index`: when a diary *entry* (a dated page, not the
// index itself) is saved, regenerate the diary index page.
if wiki.config.auto_diary_index {
if let Some(index_uri) = crate::diary::index_uri(&wiki.config) {
let is_diary_entry = uri != index_uri
&& wiki
.index
.read()
.ok()
.and_then(|i| i.page(&uri).and_then(|p| p.diary_period))
.is_some();
if is_diary_entry {
let body = wiki
.index
.read()
.ok()
.map(|i| crate::diary::render_index_body(&wiki.config, &i));
if let Some(body) = body {
let edit =
commands::ops::diary_generate_index_edit(self, &index_uri, &body, utf8);
let _ = self.client.apply_edit(edit).await;
}
}
}
}
// When `auto_export` is set on the resolved wiki, run
// the equivalent of `nuwiki.export.currentToHtml` after the file
// hits disk. Best-effort — failures are logged but do not bubble