Add user avatar URL to the User struct and update HTML output for issue and comments
This commit is contained in:
parent
3b6f405c50
commit
08f7278302
2 changed files with 18 additions and 19 deletions
7
go.mod
7
go.mod
|
@ -2,9 +2,12 @@ module issue_cli
|
||||||
|
|
||||||
go 1.23.4
|
go 1.23.4
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0
|
||||||
|
github.com/urfave/cli/v2 v2.27.5
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
|
||||||
github.com/urfave/cli/v2 v2.27.5 // indirect
|
|
||||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||||
)
|
)
|
||||||
|
|
28
main.go
28
main.go
|
@ -27,6 +27,7 @@ type Issue struct {
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Login string `json:"login"`
|
Login string `json:"login"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Comment struct {
|
type Comment struct {
|
||||||
|
@ -76,7 +77,6 @@ func fetchIssue(c *cli.Context) error {
|
||||||
return fmt.Errorf("invalid GitHub issue URL")
|
return fmt.Errorf("invalid GitHub issue URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract owner, repo, and issue number from the URL
|
|
||||||
parts := strings.Split(url, "/")
|
parts := strings.Split(url, "/")
|
||||||
if len(parts) < 5 {
|
if len(parts) < 5 {
|
||||||
return fmt.Errorf("invalid GitHub issue URL")
|
return fmt.Errorf("invalid GitHub issue URL")
|
||||||
|
@ -85,19 +85,16 @@ func fetchIssue(c *cli.Context) error {
|
||||||
repo := parts[4]
|
repo := parts[4]
|
||||||
issueNumber := parts[len(parts)-1]
|
issueNumber := parts[len(parts)-1]
|
||||||
|
|
||||||
// Fetch the issue data from the GitHub API
|
|
||||||
issue, err := getIssue(owner, repo, issueNumber)
|
issue, err := getIssue(owner, repo, issueNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the comments for the issue
|
|
||||||
comments, err := getComments(owner, repo, issueNumber)
|
comments, err := getComments(owner, repo, issueNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the issue data to the specified format
|
|
||||||
format := c.String("format")
|
format := c.String("format")
|
||||||
var output string
|
var output string
|
||||||
if format == "html" {
|
if format == "html" {
|
||||||
|
@ -106,16 +103,13 @@ func fetchIssue(c *cli.Context) error {
|
||||||
output = convertToMarkdown(issue, comments)
|
output = convertToMarkdown(issue, comments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if output file path is provided
|
|
||||||
outputFile := c.String("output")
|
outputFile := c.String("output")
|
||||||
if outputFile != "" {
|
if outputFile != "" {
|
||||||
// Write the output to the specified file
|
|
||||||
if err := os.WriteFile(outputFile, []byte(output), 0644); err != nil {
|
if err := os.WriteFile(outputFile, []byte(output), 0644); err != nil {
|
||||||
return fmt.Errorf("failed to write to file: %v", err)
|
return fmt.Errorf("failed to write to file: %v", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Output written to %s\n", outputFile)
|
fmt.Printf("Output written to %s\n", outputFile)
|
||||||
} else {
|
} else {
|
||||||
// Print the output to the console
|
|
||||||
fmt.Println(output)
|
fmt.Println(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,14 +165,11 @@ func formatDate(isoDate string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseMarkdown(md string) string {
|
func parseMarkdown(md string) string {
|
||||||
// Use blackfriday to convert markdown to HTML
|
|
||||||
html := blackfriday.Run([]byte(md))
|
html := blackfriday.Run([]byte(md))
|
||||||
|
|
||||||
// Custom handling for images
|
|
||||||
re := regexp.MustCompile(`!\[Image\]\((https://github.com/user-attachments/assets/[^\)]+)\)`)
|
re := regexp.MustCompile(`!\[Image\]\((https://github.com/user-attachments/assets/[^\)]+)\)`)
|
||||||
html = re.ReplaceAll(html, []byte(`<img src="$1" alt="Image" style="max-width:100%;height:auto;">`))
|
html = re.ReplaceAll(html, []byte(`<img src="$1" alt="Image" style="max-width:100%;height:auto;">`))
|
||||||
|
|
||||||
// Remove leading and trailing <p> tags and replace <br> tags with spaces
|
|
||||||
re = regexp.MustCompile(`(?m)^<p>(.*?)</p>$`)
|
re = regexp.MustCompile(`(?m)^<p>(.*?)</p>$`)
|
||||||
html = re.ReplaceAll(html, []byte("$1"))
|
html = re.ReplaceAll(html, []byte("$1"))
|
||||||
html = bytes.ReplaceAll(html, []byte("<br>"), []byte(" "))
|
html = bytes.ReplaceAll(html, []byte("<br>"), []byte(" "))
|
||||||
|
@ -223,7 +214,6 @@ func convertToHTML(issue Issue, comments []Comment) string {
|
||||||
createdAt, _ := formatDate(issue.CreatedAt)
|
createdAt, _ := formatDate(issue.CreatedAt)
|
||||||
updatedAt, _ := formatDate(issue.UpdatedAt)
|
updatedAt, _ := formatDate(issue.UpdatedAt)
|
||||||
|
|
||||||
// Add CSS styling
|
|
||||||
sb.WriteString(`<style>
|
sb.WriteString(`<style>
|
||||||
body {
|
body {
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
||||||
|
@ -281,6 +271,13 @@ body.light-mode .comment-container {
|
||||||
.comment-body {
|
.comment-body {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
.avatar {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
#toggle-button {
|
#toggle-button {
|
||||||
background-color: #444c56;
|
background-color: #444c56;
|
||||||
color: #c9d1d9;
|
color: #c9d1d9;
|
||||||
|
@ -297,7 +294,6 @@ body.light-mode #toggle-button {
|
||||||
}
|
}
|
||||||
</style>`)
|
</style>`)
|
||||||
|
|
||||||
// Add the toggle button and JavaScript
|
|
||||||
sb.WriteString(`<button id="toggle-button">Toggle Light/Dark Mode</button>
|
sb.WriteString(`<button id="toggle-button">Toggle Light/Dark Mode</button>
|
||||||
<script>
|
<script>
|
||||||
document.getElementById('toggle-button').addEventListener('click', function() {
|
document.getElementById('toggle-button').addEventListener('click', function() {
|
||||||
|
@ -308,21 +304,21 @@ document.getElementById('toggle-button').addEventListener('click', function() {
|
||||||
sb.WriteString(fmt.Sprintf(`<div class="issue-container">
|
sb.WriteString(fmt.Sprintf(`<div class="issue-container">
|
||||||
<div class="issue-header">
|
<div class="issue-header">
|
||||||
<h1 class="issue-title">%s</h1>
|
<h1 class="issue-title">%s</h1>
|
||||||
<p class="issue-meta">Issue Number: %d | State: %s | Created By: %s | Created At: %s | Updated At: %s | Comments: %d</p>
|
<p class="issue-meta"><img src="%s" alt="Avatar" class="avatar">%s | Issue Number: %d | State: %s | Created At: %s | Updated At: %s | Comments: %d</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="issue-body">
|
<div class="issue-body">
|
||||||
%s
|
%s
|
||||||
</div>
|
</div>
|
||||||
</div>`, issue.Title, issue.Number, issue.State, issue.User.Login, createdAt, updatedAt, issue.Comments, parseMarkdown(issue.Body)))
|
</div>`, issue.Title, issue.User.AvatarURL, issue.User.Login, issue.Number, issue.State, createdAt, updatedAt, issue.Comments, parseMarkdown(issue.Body)))
|
||||||
|
|
||||||
if len(comments) > 0 {
|
if len(comments) > 0 {
|
||||||
sb.WriteString("<h2>Comments:</h2>")
|
sb.WriteString("<h2>Comments:</h2>")
|
||||||
for _, comment := range comments {
|
for _, comment := range comments {
|
||||||
commentCreatedAt, _ := formatDate(comment.CreatedAt)
|
commentCreatedAt, _ := formatDate(comment.CreatedAt)
|
||||||
sb.WriteString(fmt.Sprintf(`<div class="comment-container">
|
sb.WriteString(fmt.Sprintf(`<div class="comment-container">
|
||||||
<div class="comment-meta">%s commented on %s:</div>
|
<div class="comment-meta"><img src="%s" alt="Avatar" class="avatar">%s commented on %s:</div>
|
||||||
<div class="comment-body">%s</div>
|
<div class="comment-body">%s</div>
|
||||||
</div>`, comment.User.Login, commentCreatedAt, parseMarkdown(comment.Body)))
|
</div>`, comment.User.AvatarURL, comment.User.Login, commentCreatedAt, parseMarkdown(comment.Body)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue