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}, 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}}", ""}, 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 != "" {