From 3926442c0e19d9bfdd418095d3b6e5e144890524 Mon Sep 17 00:00:00 2001 From: Foosy Date: Sun, 31 May 2026 13:10:06 +0200 Subject: [PATCH 1/4] fix: render ADF document custom fields as plain text FormatCustomFieldValue's map[string]any case did not detect Atlassian Document Format objects (type: 'doc'), causing ADF-backed custom fields (e.g. textarea, paragraph-rich) to render as '-' in 'issues get'. Add ADF detection: when the map has type='doc', marshal+unmarshal into ADFDocument and call ToPlainText() to extract readable text. Fixes reading of fields like 'Changelog Entry' that use ADF storage. --- tools/jtk/api/issues.go | 8 ++++++++ tools/jtk/api/issues_extract_test.go | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/tools/jtk/api/issues.go b/tools/jtk/api/issues.go index fbde2477..6994ea70 100644 --- a/tools/jtk/api/issues.go +++ b/tools/jtk/api/issues.go @@ -422,6 +422,14 @@ func FormatCustomFieldValue(v any) string { } return fmt.Sprintf("%g", val) case map[string]any: + // Detect ADF documents (type: "doc") and extract plain text. + if t, _ := val["type"].(string); t == "doc" { + b, _ := json.Marshal(val) + var doc ADFDocument + if err := json.Unmarshal(b, &doc); err == nil { + return doc.ToPlainText() + } + } if s, ok := val["value"].(string); ok { return s } diff --git a/tools/jtk/api/issues_extract_test.go b/tools/jtk/api/issues_extract_test.go index 8f324a42..8d5919f9 100644 --- a/tools/jtk/api/issues_extract_test.go +++ b/tools/jtk/api/issues_extract_test.go @@ -105,6 +105,21 @@ func TestFormatCustomFieldValue_Types(t *testing.T) { {"bool_true", true, "yes"}, {"bool_false", false, "no"}, {"nil", nil, ""}, + {"adf_document", map[string]any{ + "type": "doc", + "version": float64(1), + "content": []any{ + map[string]any{ + "type": "paragraph", + "content": []any{ + map[string]any{ + "type": "text", + "text": "Hello ADF", + }, + }, + }, + }, + }, "Hello ADF\n"}, {"unhandled_map", map[string]any{"progress": float64(0), "total": float64(0)}, ""}, {"unhandled_type", struct{ X int }{42}, ""}, {"serialized_java_object", "{pullrequest={dataType=pullrequest, state=MERGED}}", ""}, From 58a805f0665d8a09b7d645453f026a7151774879 Mon Sep 17 00:00:00 2001 From: Foosy Date: Fri, 19 Jun 2026 13:26:59 +0200 Subject: [PATCH 2/4] ci: retry failed flaky test in comments package From 1e681be498e9014a68494117b17fb4a30edd05ba Mon Sep 17 00:00:00 2001 From: Foosy Date: Mon, 22 Jun 2026 13:26:08 +0200 Subject: [PATCH 3/4] fix: auto-link bare URLs in descriptions and comments Add extension.Linkify to both mdParser and wikiParser so that bare URLs (e.g. https://example.com) in --description and --body text are automatically converted to clickable ADF hyperlinks. --- shared/adf/convert.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared/adf/convert.go b/shared/adf/convert.go index 5ff97d68..1ec0d536 100644 --- a/shared/adf/convert.go +++ b/shared/adf/convert.go @@ -22,6 +22,7 @@ import ( var mdParser = goldmark.New( goldmark.WithExtensions( extension.Table, + extension.Linkify, extras.New(extras.Config{ Delete: extras.DeleteConfig{Enable: true}, }), @@ -37,6 +38,7 @@ var mdParser = goldmark.New( var wikiParser = goldmark.New( goldmark.WithExtensions( extension.Table, + extension.Linkify, extras.New(extras.Config{ Subscript: extras.SubscriptConfig{Enable: true}, Superscript: extras.SuperscriptConfig{Enable: true}, From 05bdf4cd3e2e4aee1290ebf368a1aa2c10fe63b2 Mon Sep 17 00:00:00 2001 From: Foosy Date: Mon, 22 Jun 2026 13:51:27 +0200 Subject: [PATCH 4/4] fix: preserve media (images) when updating description via --description When --description is used, the current issue is fetched first. Any mediaSingle/mediaGroup nodes (images, attachments) in the existing description are preserved and appended after the new markdown content. This prevents accidental deletion of embedded images when replacing text in a description. --- tools/jtk/internal/cmd/issues/update.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/jtk/internal/cmd/issues/update.go b/tools/jtk/internal/cmd/issues/update.go index 4431e966..11449bc6 100644 --- a/tools/jtk/internal/cmd/issues/update.go +++ b/tools/jtk/internal/cmd/issues/update.go @@ -17,6 +17,7 @@ import ( jtkpresent "github.com/open-cli-collective/jira-ticket-cli/internal/present" "github.com/open-cli-collective/jira-ticket-cli/internal/resolve" "github.com/open-cli-collective/jira-ticket-cli/internal/text" + "github.com/open-cli-collective/atlassian-go/adf" ) func newUpdateCmd(opts *root.Options) *cobra.Command { @@ -132,7 +133,23 @@ func runUpdate(ctx context.Context, opts *root.Options, issueKey, summary, descr } if description != "" { - fields["description"] = api.NewADFDocument(text.InterpretEscapes(description)) + // Fetch current issue to preserve media (images, attachments) in description + existingIssue, fetchErr := client.GetIssue(ctx, issueKey) + if fetchErr == nil && existingIssue.Fields.Description != nil && existingIssue.Fields.Description.ADF != nil { + var mediaNodes []*adf.Node + for _, node := range existingIssue.Fields.Description.ADF.Content { + if node.Type == "mediaSingle" || node.Type == "mediaGroup" { + mediaNodes = append(mediaNodes, node) + } + } + newDoc := api.NewADFDocument(text.InterpretEscapes(description)) + if newDoc != nil && len(mediaNodes) > 0 { + newDoc.Content = append(newDoc.Content, mediaNodes...) + } + fields["description"] = newDoc + } else { + fields["description"] = api.NewADFDocument(text.InterpretEscapes(description)) + } } if parent != "" {