fix(wiki): cleanSidebar strip .- suffix so deleted pages unlink correctly

GitLink appends a ".-" suffix to every wiki page's sub_url on create, so
callers must pass the sub_url (e.g. "Home.-") to delete — the clean name
404s. But the sidebar stores links by the clean name ([[Home]], no suffix),
so cleanSidebar's exact match [[Home.-]] never hit, orphaning the link.

Now match both [[page]] and [[<page without .->]] forms.

Verified end-to-end on baoerjun/gitlink-cli: delete now removes the
[[link]] from _Sidebar automatically. Adds TestWikiDeleteStripsSuffix.
This commit is contained in:
wauxing 2026-07-07 18:43:50 +08:00
parent 0b00391bfb
commit bed343239b
2 changed files with 60 additions and 2 deletions

View File

@ -433,11 +433,17 @@ func cleanSidebar(ctx *common.RuntimeContext, projectID int, pageName string) {
return
}
target := "[[" + pageName + "]]"
// GitLink appends a ".-" suffix to every page's sub_url on create, so the
// caller usually passes the sub_url here. But the sidebar stores links by
// the clean name (no ".-"). Match both forms so the link is never orphaned.
targets := map[string]bool{
"[[" + pageName + "]]": true,
"[[" + stripPageSuffix(pageName) + "]]": true,
}
lines := strings.Split(sidebar, "\n")
var newLines []string
for _, line := range lines {
if strings.TrimSpace(line) != target {
if !targets[strings.TrimSpace(line)] {
newLines = append(newLines, line)
}
}
@ -449,6 +455,12 @@ func cleanSidebar(ctx *common.RuntimeContext, projectID int, pageName string) {
updateSidebarContent(ctx, projectID, newSidebar, "Remove deleted page "+pageName+" from sidebar")
}
// stripPageSuffix removes the trailing ".-" suffix that GitLink appends to a
// page's sub_url. It leaves all other names (including "_Sidebar") untouched.
func stripPageSuffix(name string) string {
return strings.TrimSuffix(name, ".-")
}
// addPageToSidebarDir adds a [[pageName]] link under the specified directory in the sidebar.
func addPageToSidebarDir(ctx *common.RuntimeContext, projectID int, pageName, dirName string) error {
defer withWikiGateway(ctx)()

View File

@ -190,3 +190,49 @@ func TestWikiDelete(t *testing.T) {
expectedSidebar := base64.StdEncoding.EncodeToString([]byte("[[OtherPage]]"))
common.AssertEqual(t, sidebarUpdatePayload["content_base64"], expectedSidebar)
}
// TestWikiDeleteStripsSuffix reproduces the real-platform scenario:
// GitLink appends a ".-" suffix to every page's sub_url on create, so the
// caller must pass the sub_url ("OldPage.-") to delete (the clean name 404s).
// But the sidebar stores the link as [[OldPage]] (no suffix). cleanSidebar
// must therefore strip the ".-" suffix when matching, otherwise the link is
// orphaned in the sidebar after deletion.
func TestWikiDeleteStripsSuffix(t *testing.T) {
var sidebarUpdatePayload map[string]interface{}
server := common.NewTestServer(t, func(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == "GET" && r.URL.Path == "/owner/repo.json":
common.WriteJSON(t, w, map[string]interface{}{"id": float64(123)})
case r.Method == "DELETE" && r.URL.Path == "/wiki/open/deleteWiki":
common.WriteJSON(t, w, map[string]interface{}{"code": 204})
case r.Method == "GET" && r.URL.Path == "/wiki/open/getWiki":
common.WriteJSON(t, w, map[string]interface{}{
"code": 200,
"data": map[string]interface{}{
// sidebar holds the clean name (no ".-")
"content_base64": base64.StdEncoding.EncodeToString([]byte("[[OldPage]]\n[[OtherPage]]")),
},
})
case r.Method == "PUT" && r.URL.Path == "/wiki/open/updateWiki":
sidebarUpdatePayload = common.DecodeJSON(t, r)
common.WriteJSON(t, w, map[string]interface{}{"code": 200})
default:
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path)
}
})
defer server.Close()
// Caller passes the sub_url (with ".-"), as required by the real API.
ctx := common.NewTestContext(t, server, "owner", "repo", map[string]string{
"name": "OldPage.-",
})
if err := common.RunShortcut(t, Shortcuts(), "delete", ctx); err != nil {
t.Fatalf("delete failed: %v", err)
}
if sidebarUpdatePayload == nil {
t.Fatal("expected sidebar to be updated to remove [[OldPage]], but no update was sent")
}
expectedSidebar := base64.StdEncoding.EncodeToString([]byte("[[OtherPage]]"))
common.AssertEqual(t, sidebarUpdatePayload["content_base64"], expectedSidebar)
}