From 8bea092e89ef718c565a3ffe929890a99d8ac892 Mon Sep 17 00:00:00 2001
From: Naveen Prashanth <78990165+gnpaone@users.noreply.github.com>
Date: Mon, 2 Sep 2024 21:46:08 +0530
Subject: [PATCH] Bump version to v1.0.2
---
.github/workflows/{main.yml => tag.yml} | 0
CONTRIBUTING.md | 7 +
README.md | 38 +--
action/go.mod | 3 +-
dynreadme.go | 108 ++++----
examples/update.yml | 10 +-
go.mod | 2 +
helpers/table.go | 321 ------------------------
8 files changed, 93 insertions(+), 396 deletions(-)
rename .github/workflows/{main.yml => tag.yml} (100%)
delete mode 100644 helpers/table.go
diff --git a/.github/workflows/main.yml b/.github/workflows/tag.yml
similarity index 100%
rename from .github/workflows/main.yml
rename to .github/workflows/tag.yml
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e69de29..bc3221c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -0,0 +1,7 @@
+Contributions are welcome! Please follow these steps:
+
+1. Fork the project.
+2. Create a new branch (`git checkout -b feature-branch`).
+3. Commit your changes (`git commit -m 'Add a feature'`).
+4. Push to the branch (`git push origin feature-branch`).
+5. Open a Pull Request.
\ No newline at end of file
diff --git a/README.md b/README.md
index 38b23ba..0f26496 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,7 @@
[![Issues](https://img.shields.io/github/issues/gnpaone/dynamic-update-readme?color=orange&style=flat-square)](https://github.com/gnpaone/dynamic-update-readme/issues)
[![Go](https://img.shields.io/github/go-mod/go-version/gnpaone/dynamic-update-readme?color=maroon&style=flat-square)](https://github.com/gnpaone/dynamic-update-readme/blob/main/go.mod)
[![Godoc](https://pkg.go.dev/badge/github.com/gnpaone/dynamic-update-readme.svg?utm_source=godoc)](https://godoc.org/github.com/gnpaone/dynamic-update-readme)
+[![GitHub Marketplace](https://img.shields.io/badge/Marketplace-v1.0.2-undefined.svg?logo=github&logoColor=white&style=flat-square)](https://github.com/marketplace/actions/dynamic-update-readme)
#### As a power user, automate the updating of markdown text with content obtained from other actions in the workflow, as well as a Go module that can update markdown text
@@ -17,13 +18,13 @@ A Go module that updates markdown text and is integrated as a GitHub Action.
## Parameters
-| Parameter | Workflow default | Description | Required | Possible values |
-|:----------------:|:-------------------:|:-------------------------------------------|:-----------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| readme_path | ./README.md | Path of the markdown file | No | *File path relative to the root directory of the GitHub repo* |
-| marker_text | *null* | Marker text to replace in markdown file | Yes | *Example markers to be added in the markdown:*
`` |
-| markdown_text | *null* | Markdown text that needs to be updated | Yes | *Any markdown compatible text (For GitHub markdown please check [GitHub Flavored Markdown parser](https://github.github.com/gfm/))* |
-| table | false | Markdown text is a table | No | true, false |
-| table_options | *null* | Alignment for the table | No | align-*Alignment*, head-align-*Alignment*, text-align-*Alignment*, col-*Column*-align-*Alignment*, col-*Column*-w-*Min-width*, colH-*Column*-align-*Alignment*, colT-*Column*-align-*Alignment* |
+| Parameter | Workflow default | Description | Required | Possible values |
+|:----------------:|:-------------------:|:-------------------------------------------|:-----------:|:-------------------|
+| readme_path | ./README.md | Path of the markdown file | No | *File path relative to the root directory of the GitHub repo* |
+| marker_text | *null* | Marker text to replace in markdown file | Yes | *Example markers to be added in the markdown:*
`` |
+| markdown_text | *null* | Markdown text that needs to be updated | Yes | *Any markdown compatible text* |
+| table | false | Markdown text is a table | No | true, false |
+| table_options | *null* | Alignment for the table | No | align-*Alignment*, col-*Column*-align-*Alignment*, col-*Column*-w-*Min-width* |
_Alignment_: `left, right, center`
_Column_: Column number of the table (starts with `0`)
_Min-width_: Minimum width of a column (in other words, minimum number of hyphens (`-`) in the delimiter row)
@@ -31,26 +32,33 @@ A Go module that updates markdown text and is integrated as a GitHub Action.
* Make sure to change the following in your GitHub repo settings: `Actions` > `General` > `Workflow permissions` > Choose `Read and write permissions` > Check `Allow GitHub Actions to create and approve pull requests` > `Save`.
* Other parameters `commit_user`, `commit_email`, `commit_message` and `confirm_and_push` related to action workflow are optional.
* If `confirm_and_push` is "false" committer detalis can be accessed via `outputs.commit_user`, `outputs.commit_email` & `outputs.commit_message` for further usage in the workflow.
+* The syntax mostly revolves around [GitHub Flavored Markdown parser](https://github.github.com/gfm/).
* The `table` parameter is optional as `markdown_text` supports table markdown syntax by default but this parameter can be used as a simple alternative or any special use case. If `table` is "true":
+ - It uses [github.com/willabides/mdtable](https://godoc.org/github.com/willabides/mdtable) module
- `markdown_text` contents should follow these conditions:
+ Table row contents are seperated with ";" delimiter. First element will make up the table header.
+ For each element of table rows, table column contents are seperated with "," delimiter.
- `table_options` can be used only if `table` is "true".
+ Description of options/values:
1. `align-`: This option aligns the whole table according to the alignment set.
- 2. `head-`: This option aligns the header row of the table according to the alignment set.
- 3. `text-`: This option aligns all the data rows of the table according to the alignment set.
- 4. `col-`: This option sets properties of any particular column based on the column number.
- 5. `colH-`: This option sets properties of header row of any particular column based on the column number.
- 6. `colT-`: This option sets properties of data rows of any particular column based on the column number.
- + Order of preference of the alignment options:
- 1. Header rows: `colH-` > `col-` > `head-` > `align-`
- 2. Data rows: `colT-` > `col-` > `text-` > `align-`
+ 2. `col-`: This option sets properties of any particular column based on the column number.
+ + Order of preference of the alignment options: `col-` > `align-`
* The markdown file must contain start marker `` and end marker `` where "EXAMPLE_MARKER" is the input of `marker_text` parameter. Note that the `_START` and `_END` part is important.
## Usage
Check the example workflow [here](https://github.com/gnpaone/dynamic-update-readme/blob/main/examples/update.yml).
+## Contributing
+See [CONTRIBUTING.md](https://github.com/gnpaone/dynamic-update-readme/blob/main/CONTRIBUTING.md) for more details.
+
+## Acknowledgements
+
+This project uses few of the open-source Go modules, without which it would not have been possible. I extend my gratitude to the developers and maintainers of these modules for their valuable contributions to the open-source community:
+
+* [github.com/willabides/mdtable](https://godoc.org/github.com/willabides/mdtable) - Generates markdown tables from string slices.
+* [github.com/mattn/go-runewidth](https://godoc.org/github.com/mattn/go-runewidth) - Provides functions to get fixed width of the character or string.
+* [github.com/rivo/uniseg](https://godoc.org/github.com/rivo/uniseg) - Implements Unicode Text Segmentation, Word Wrapping, and String Width Calculation.
+
## License
This project is licensed under GPL-3.0.
Copyright © 2024, Naveen Prashanth. All Rights Reserved.
diff --git a/action/go.mod b/action/go.mod
index dcd9b07..b51c4a1 100644
--- a/action/go.mod
+++ b/action/go.mod
@@ -2,9 +2,10 @@ module github.com/gnpaone/dynamic-update-readme/update-readme-action
go 1.22
-require github.com/gnpaone/dynamic-update-readme v1.0.1
+require github.com/gnpaone/dynamic-update-readme v1.0.2
require (
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/willabides/mdtable v0.3.1 // indirect
)
diff --git a/dynreadme.go b/dynreadme.go
index b9b53a2..aa072f8 100644
--- a/dynreadme.go
+++ b/dynreadme.go
@@ -6,7 +6,7 @@ import (
"os"
"strings"
- table "github.com/gnpaone/dynamic-update-readme/helpers"
+ table "github.com/willabides/mdtable"
)
// UpdateContent parses and updates content between markers
@@ -69,57 +69,57 @@ func parseTableOptions(tableOptions string) []table.Option {
}
}
- case strings.HasPrefix(part, "colH-"):
- colHParts := strings.Split(part, "-")
- if len(colHParts) >= 3 {
- colHNum := parseColumnNumber(colHParts[1])
- switch colHParts[2] {
- case "align":
- if len(colHParts) == 4 {
- alignment := parseAlignment(colHParts[3])
- options = append(options, table.ColumnHeaderAlignment(colHNum, alignment))
- }
- }
- }
-
- case strings.HasPrefix(part, "colT-"):
- colTParts := strings.Split(part, "-")
- if len(colTParts) >= 3 {
- colTNum := parseColumnNumber(colTParts[1])
- switch colTParts[2] {
- case "align":
- if len(colTParts) == 4 {
- alignment := parseAlignment(colTParts[3])
- options = append(options, table.ColumnTextAlignment(colTNum, alignment))
- }
- }
- }
-
- case strings.HasPrefix(part, "head-"):
- headParts := strings.Split(part, "-")
- if len(headParts) >= 2 {
- switch headParts[1] {
- case "align":
- if len(headParts) == 3 {
- alignment := parseAlignment(headParts[2])
- options = append(options, table.HeaderAlignment(alignment))
- }
- }
-
- }
-
- case strings.HasPrefix(part, "text-"):
- textParts := strings.Split(part, "-")
- if len(textParts) >= 2 {
- switch textParts[1] {
- case "align":
- if len(textParts) == 3 {
- alignment := parseAlignment(textParts[2])
- options = append(options, table.TextAlignment(alignment))
- }
- }
-
- }
+ // case strings.HasPrefix(part, "colH-"):
+ // colHParts := strings.Split(part, "-")
+ // if len(colHParts) >= 3 {
+ // colHNum := parseColumnNumber(colHParts[1])
+ // switch colHParts[2] {
+ // case "align":
+ // if len(colHParts) == 4 {
+ // alignment := parseAlignment(colHParts[3])
+ // options = append(options, table.ColumnHeaderAlignment(colHNum, alignment))
+ // }
+ // }
+ // }
+
+ // case strings.HasPrefix(part, "colT-"):
+ // colTParts := strings.Split(part, "-")
+ // if len(colTParts) >= 3 {
+ // colTNum := parseColumnNumber(colTParts[1])
+ // switch colTParts[2] {
+ // case "align":
+ // if len(colTParts) == 4 {
+ // alignment := parseAlignment(colTParts[3])
+ // options = append(options, table.ColumnTextAlignment(colTNum, alignment))
+ // }
+ // }
+ // }
+
+ // case strings.HasPrefix(part, "head-"):
+ // headParts := strings.Split(part, "-")
+ // if len(headParts) >= 2 {
+ // switch headParts[1] {
+ // case "align":
+ // if len(headParts) == 3 {
+ // alignment := parseAlignment(headParts[2])
+ // options = append(options, table.HeaderAlignment(alignment))
+ // }
+ // }
+
+ // }
+
+ // case strings.HasPrefix(part, "text-"):
+ // textParts := strings.Split(part, "-")
+ // if len(textParts) >= 2 {
+ // switch textParts[1] {
+ // case "align":
+ // if len(textParts) == 3 {
+ // alignment := parseAlignment(textParts[2])
+ // options = append(options, table.TextAlignment(alignment))
+ // }
+ // }
+
+ // }
}
}
return options
@@ -142,7 +142,7 @@ func parseColumnNumber(num string) int {
var colNum int
if _, err := fmt.Sscanf(num, "%d", &colNum); err != nil {
log.Fatalf("Error parsing column number: %s", err)
- }
+ }
return colNum
}
@@ -150,7 +150,7 @@ func parseColumnWidth(width string) int {
var w int
if _, err := fmt.Sscanf(width, "%d", &w); err != nil {
log.Fatalf("Error parsing column width: %s", err)
- }
+ }
return w
}
diff --git a/examples/update.yml b/examples/update.yml
index f8e0de3..27cdee2 100644
--- a/examples/update.yml
+++ b/examples/update.yml
@@ -12,7 +12,7 @@ jobs:
# Marker as
- name: Example 1 - multiple lines
- uses: gnpaone/dynamic-update-readme@v1.0.1
+ uses: gnpaone/dynamic-update-readme@v1.0.2
with:
marker_text: "EXAMPLE"
markdown_text: |
@@ -51,7 +51,7 @@ jobs:
### Requirements
- Node.js >= 18.0.0
- - npm >= 6.0.0
+ - npm >= 9.0.0
## Usage
@@ -168,15 +168,15 @@ jobs:
# Marker as
- name: Example 2 - single line
- uses: gnpaone/dynamic-update-readme@v1.0.1
+ uses: gnpaone/dynamic-update-readme@v1.0.2
with:
marker_text: "MARKER_TEXT"
- markdown_text: "This is a sample text."
+ markdown_text: "#### This is a sample text."
confirm_and_push: "false"
# Marker as
- name: Example 3 - add table
- uses: gnpaone/dynamic-update-readme@v1.0.1
+ uses: gnpaone/dynamic-update-readme@v1.0.2
with:
marker_text: "TABLE"
table: "true"
diff --git a/go.mod b/go.mod
index 4117397..017380e 100644
--- a/go.mod
+++ b/go.mod
@@ -4,4 +4,6 @@ go 1.22
require (
github.com/mattn/go-runewidth v0.0.16 // indirect
+ github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/willabides/mdtable v0.3.1 // indirect
)
diff --git a/helpers/table.go b/helpers/table.go
deleted file mode 100644
index 822a1e0..0000000
--- a/helpers/table.go
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
-Package table generates markdown tables from string slices with formatting options for alignment and column width.
-
-*/
-package table
-
-import (
- "bytes"
- "strings"
-
- runewidth "github.com/mattn/go-runewidth"
-)
-
-// Align is a value for markdown and text alignment
-type Align uint8
-
-// Align values
-const (
- AlignDefault Align = iota // markdown: |--------| text: | foo |
- AlignLeft // markdown: |:-------| text: | foo |
- AlignRight // markdown: |-------:| text: | foo |
- AlignCenter // markdown: |:------:| text: | foo |
-)
-
-// defaultTextAlignment is the alignment used for text alignment on columns set to AlignDefault
-const defaultTextAlignment = AlignLeft
-
-func (a Align) headerPrefix() string {
- switch a {
- case AlignLeft, AlignCenter:
- return ":"
- default:
- return "-"
- }
-}
-
-func (a Align) headerSuffix() string {
- switch a {
- case AlignRight, AlignCenter:
- return ":"
- default:
- return "-"
- }
-}
-
-func (a Align) fillCell(s string, width, padding int) string {
- align := a
- if align == AlignDefault {
- align = defaultTextAlignment
- }
- pad := strings.Repeat(" ", padding)
- var leftFill, rightFill int
- switch align {
- case AlignCenter:
- filled := runewidth.FillLeft(s, width)
- delta := runewidth.StringWidth(filled) - runewidth.StringWidth(s)
- leftFill = delta / 2
- rightFill = delta/2 + delta%2
- s = strings.Repeat(" ", leftFill) + s + strings.Repeat(" ", rightFill)
- case AlignRight:
- s = runewidth.FillLeft(s, width)
- case AlignLeft:
- s = runewidth.FillRight(s, width)
- }
- return pad + s + pad
-}
-
-// Generate generates a markdown table.
-func Generate(data [][]string, options ...Option) []byte {
- t := &table{
- data: data,
- }
-
- for _, o := range options {
- o(t)
- }
-
- return t.generate()
-}
-
-// Option is to control a table's formatting
-type Option func(*table)
-
-// Start Options
-
-// HeaderAlignment sets the text alignment for headers
-func HeaderAlignment(val Align) Option {
- return func(t *table) {
- t.headerAlignment = val
- }
-}
-
-// TextAlignment sets the default text alignment for non-header cells
-func TextAlignment(val Align) Option {
- return func(t *table) {
- t.textAlignment = val
- }
-}
-
-// Alignment sets alignment for columns.
-func Alignment(val Align) Option {
- return func(t *table) {
- t.mdAlignment = val
- }
-}
-
-// ColumnAlignment sets the markdown alignment for a column
-func ColumnAlignment(column int, alignment Align) Option {
- return func(t *table) {
- t.mdAlignments = setColumnAlignment(t.mdAlignments, column, alignment)
- }
-}
-
-// ColumnHeaderAlignment sets the text alignment for a column header
-func ColumnHeaderAlignment(column int, alignment Align) Option {
- return func(t *table) {
- t.headerAlignments = setColumnAlignment(t.headerAlignments, column, alignment)
- }
-}
-
-// ColumnTextAlignment sets the text alignment for a column
-func ColumnTextAlignment(column int, alignment Align) Option {
- return func(t *table) {
- t.textAlignments = setColumnAlignment(t.textAlignments, column, alignment)
- }
-}
-
-// ColumnMinWidth sets the minimum width for a column
-func ColumnMinWidth(column, width int) Option {
- return func(t *table) {
- if column < 0 {
- return
- }
- delta := (column + 1) - len(t.minWidths)
- if delta > 0 {
- t.minWidths = append(t.minWidths, make([]int, delta)...)
- }
- t.minWidths[column] = width
- }
-}
-
-// End Options
-
-// table is a markdown table
-type table struct {
- data [][]string
- mdAlignment Align
- textAlignment Align
- headerAlignment Align
- mdAlignments []Align
- textAlignments []Align
- headerAlignments []Align
- minWidths []int
-}
-
-// columnMinWidth returns the minimum width that is set for a column. Returns 0 if non has been set.
-func (t *table) columnMinWidth(column int) int {
- if column < 0 {
- return 0
- }
- if len(t.minWidths) < column+1 {
- return 0
- }
- return t.minWidths[column]
-}
-
-// columnAlignment returns the markdown alignment for a column
-func (t *table) columnAlignment(column int) Align {
- align := getColumnAlignment(t.mdAlignments, column)
- if align != AlignDefault {
- return align
- }
- return t.mdAlignment
-}
-
-// columnTextAlignment returns text alignment for a column
-//
-// Order of preference:
-// 1. value set with ColumnTextAlignment
-// 2. value set with TextAlignment
-// 3. columnAlignment(column)
-// 4. defaultTextAlignment (which is AlignLeft)
-func (t *table) columnTextAlignment(column int) Align {
- align := getColumnAlignment(t.textAlignments, column)
- if align != AlignDefault {
- return align
- }
- align = t.textAlignment
- if align != AlignDefault {
- return align
- }
- align = t.columnAlignment(column)
- if align != AlignDefault {
- return align
- }
- return defaultTextAlignment
-}
-
-// columnHeaderAlignment returns the text alignment for a column header
-//
-// Order or preference:
-// 1. value set with ColumnHeaderAlignment
-// 2. value set with HeaderAlignment
-// 3. ColumnTextAlignment(column)
-func (t *table) columnHeaderAlignment(column int) Align {
- align := getColumnAlignment(t.headerAlignments, column)
- if align != AlignDefault {
- return align
- }
- align = t.headerAlignment
- if align != AlignDefault {
- return align
- }
- return t.columnTextAlignment(column)
-}
-
-func getColumnAlignment(alignments []Align, column int) Align {
- if column < 0 {
- return AlignDefault
- }
- if len(alignments) < column+1 {
- return AlignDefault
- }
- return alignments[column]
-}
-
-func setColumnAlignment(alignments []Align, column int, align Align) []Align {
- if column < 0 {
- return alignments
- }
- delta := (column + 1) - len(alignments)
- if delta > 0 {
- alignments = append(alignments, make([]Align, delta)...)
- }
- alignments[column] = align
- return alignments
-}
-
-// generate returns the markdown representation of table
-func (t *table) generate() []byte {
- var buf bytes.Buffer
- if len(t.data) == 0 {
- return buf.Bytes()
- }
- row := 0
- buf.WriteString(t.renderRow(0, t.columnHeaderAlignment) + "\n")
- buf.WriteString(t.renderHeaderRow())
- for row = 1; row < len(t.data); row++ {
- buf.WriteString("\n" + t.renderRow(row, t.columnTextAlignment))
- }
- return buf.Bytes()
-}
-
-func (t *table) renderColumnHeader(column int) string {
- width := t.columnWidth(column)
- if width == 0 {
- return "--"
- }
- align := t.columnAlignment(column)
- return align.headerPrefix() + strings.Repeat("-", width) + align.headerSuffix()
-}
-
-func cellValue(data [][]string, row, column int) string {
- if row < 0 || column < 0 {
- return ""
- }
- if len(data) < row+1 {
- return ""
- }
- if len(data[row]) < column+1 {
- return ""
- }
- return data[row][column]
-}
-
-func (t *table) renderCell(row, column int, alignment Align) string {
- s := cellValue(t.data, row, column)
- width := t.columnWidth(column)
- return alignment.fillCell(s, width, 1)
-}
-
-func (t *table) renderRow(row int, alignmentFunc func(int) Align) string {
- cells := make([]string, t.columnCount())
- for i := range cells {
- cells[i] = t.renderCell(row, i, alignmentFunc(i))
- }
- return "|" + strings.Join(cells, "|") + "|"
-}
-
-func (t *table) renderHeaderRow() string {
- headers := make([]string, t.columnCount())
- for i := range headers {
- headers[i] = t.renderColumnHeader(i)
- }
- return "|" + strings.Join(headers, "|") + "|"
-}
-
-// columnCount returns the number of columns in the table
-func (t *table) columnCount() int {
- count := 0
- for _, row := range t.data {
- if len(row) > count {
- count = len(row)
- }
- }
- return count
-}
-
-func (t *table) columnWidth(column int) int {
- width := t.columnMinWidth(column)
- for _, row := range t.data {
- if len(row) < column+1 {
- continue
- }
- strLen := len(row[column])
- if strLen > width {
- width = strLen
- }
- }
- return width
-}
\ No newline at end of file