mirror of
https://github.com/kovetskiy/mark.git
synced 2026-01-22 10:47:36 +08:00
fix: resolve link space inheritance and enhance Confluence URL normalization tests
Signed-off-by: Nikolai Emil Damm <ndam@tv2.dk>
This commit is contained in:
parent
0dd5ea9aee
commit
ef560d095c
75
page/link.go
75
page/link.go
@ -40,6 +40,13 @@ func ResolveRelativeLinks(
|
||||
) ([]LinkSubstitution, error) {
|
||||
matches := parseLinks(string(markdown))
|
||||
|
||||
// If the user didn't provide --space, inherit the current document's space so
|
||||
// relative links can be resolved within the same space.
|
||||
spaceForLinks := spaceFromCli
|
||||
if spaceForLinks == "" && meta != nil {
|
||||
spaceForLinks = meta.Space
|
||||
}
|
||||
|
||||
links := []LinkSubstitution{}
|
||||
for _, match := range matches {
|
||||
log.Tracef(
|
||||
@ -49,7 +56,7 @@ func ResolveRelativeLinks(
|
||||
match.filename,
|
||||
match.hash,
|
||||
)
|
||||
resolved, err := resolveLink(api, base, match, spaceFromCli, titleFromH1, titleFromFilename, parents, titleAppendGeneratedHash)
|
||||
resolved, err := resolveLink(api, base, match, spaceForLinks, titleFromH1, titleFromFilename, parents, titleAppendGeneratedHash)
|
||||
if err != nil {
|
||||
return nil, karma.Format(err, "resolve link: %q", match.full)
|
||||
}
|
||||
@ -71,7 +78,7 @@ func resolveLink(
|
||||
api *confluence.API,
|
||||
base string,
|
||||
link markdownLink,
|
||||
spaceFromCli string,
|
||||
spaceForLinks string,
|
||||
titleFromH1 bool,
|
||||
titleFromFilename bool,
|
||||
parents []string,
|
||||
@ -113,7 +120,7 @@ func resolveLink(
|
||||
|
||||
// This helps to determine if found link points to file that's
|
||||
// not markdown or have mark required metadata
|
||||
linkMeta, _, err := metadata.ExtractMeta(linkContents, spaceFromCli, titleFromH1, titleFromFilename, filepath, parents, titleAppendGeneratedHash)
|
||||
linkMeta, _, err := metadata.ExtractMeta(linkContents, spaceForLinks, titleFromH1, titleFromFilename, filepath, parents, titleAppendGeneratedHash)
|
||||
if err != nil {
|
||||
log.Errorf(
|
||||
err,
|
||||
@ -199,30 +206,60 @@ func getConfluenceLink(
|
||||
api *confluence.API,
|
||||
space, title string,
|
||||
) (string, error) {
|
||||
link := fmt.Sprintf(
|
||||
"%s/display/%s/%s",
|
||||
api.BaseURL,
|
||||
space,
|
||||
url.QueryEscape(title),
|
||||
)
|
||||
|
||||
page, err := api.FindPage(space, title, "page")
|
||||
if err != nil {
|
||||
return "", karma.Format(err, "api: find page")
|
||||
}
|
||||
|
||||
if page != nil {
|
||||
link = api.BaseURL + page.Links.Full
|
||||
if page == nil {
|
||||
// Without a page ID there is no stable way to produce
|
||||
// /wiki/spaces/<space>/pages/<id>/<name>.
|
||||
return "", nil
|
||||
}
|
||||
|
||||
linkUrl, err := url.Parse(link)
|
||||
// Confluence Cloud web UI URLs can be returned either as a path ("/wiki/..." or
|
||||
// "/ex/confluence/<cloudId>/wiki/...") or as a full absolute URL.
|
||||
absolute, err := makeAbsoluteConfluenceWebUIURL(api.BaseURL, page.Links.Full)
|
||||
if err != nil {
|
||||
return "", karma.Format(err, "parse URL: %s", link)
|
||||
return "", karma.Format(err, "build confluence webui URL")
|
||||
}
|
||||
// Confluence supports relative links to reference other pages:
|
||||
// https://confluence.atlassian.com/doc/links-776656293.html
|
||||
linkPath := normalizeConfluenceWebUIPath(linkUrl.Path)
|
||||
return linkPath, nil
|
||||
|
||||
return absolute, nil
|
||||
}
|
||||
|
||||
func makeAbsoluteConfluenceWebUIURL(baseURL string, webui string) (string, error) {
|
||||
if webui == "" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
u, err := url.Parse(webui)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
path := normalizeConfluenceWebUIPath(u.Path)
|
||||
if path == "" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// If Confluence returns an absolute URL, trust its host/scheme.
|
||||
if u.Scheme != "" && u.Host != "" {
|
||||
baseURL = u.Scheme + "://" + u.Host
|
||||
}
|
||||
|
||||
baseURL = strings.TrimSuffix(baseURL, "/")
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
path = "/" + path
|
||||
}
|
||||
|
||||
result := baseURL + path
|
||||
if u.RawQuery != "" {
|
||||
result += "?" + u.RawQuery
|
||||
}
|
||||
if u.Fragment != "" {
|
||||
result += "#" + u.Fragment
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// normalizeConfluenceWebUIPath rewrites Confluence Cloud "experience" URLs
|
||||
|
||||
@ -54,13 +54,13 @@ func TestParseLinks(t *testing.T) {
|
||||
|
||||
func TestNormalizeConfluenceWebUIPath(t *testing.T) {
|
||||
t.Run("confluence-cloud-experience-prefix", func(t *testing.T) {
|
||||
input := "/ex/confluence/05532958-2d1d-4f01-2027-90926d8b54d5/wiki/spaces/MySpace/pages/2441299827/TEST"
|
||||
expected := "/wiki/spaces/MySpace/pages/2441299827/TEST"
|
||||
input := "/ex/confluence/cloud-id/wiki/spaces/SPACE/pages/12345/PageName"
|
||||
expected := "/wiki/spaces/SPACE/pages/12345/PageName"
|
||||
assert.Equal(t, expected, normalizeConfluenceWebUIPath(input))
|
||||
})
|
||||
|
||||
t.Run("already-canonical-wiki", func(t *testing.T) {
|
||||
input := "/wiki/spaces/MySpace/pages/2441299827/TEST"
|
||||
input := "/wiki/spaces/SPACE/pages/12345/PageName"
|
||||
assert.Equal(t, input, normalizeConfluenceWebUIPath(input))
|
||||
})
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user