Skip to content

Commit 31febb7

Browse files
committed
fix: add missing dependencies and implementation files
Adds files that were missing from previous commit: - Add required Go dependencies (spinner, color, isatty, fsnotify) - Add watcher implementation (internal/watcher/watcher.go) - Add missing config helper functions - Update go.mod and go.sum with new dependencies This fixes CI failures where test files referenced non-existent code. Generated-by: Claude AI-Model: claude-sonnet-4-5-20250929
1 parent 4862b62 commit 31febb7

File tree

4 files changed

+333
-0
lines changed

4 files changed

+333
-0
lines changed

cmd/config.go

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"os"
67
"strconv"
@@ -20,9 +21,22 @@ const (
2021
configKeyPageSize
2122
)
2223

24+
// configCategory groups related configuration keys.
25+
type configCategory string
26+
27+
const (
28+
categoryTypography configCategory = "Typography"
29+
categoryCode configCategory = "Code Styling"
30+
categoryPage configCategory = "Page Layout"
31+
categoryMetadata configCategory = "PDF Metadata"
32+
categoryMermaid configCategory = "Mermaid Settings"
33+
)
34+
2335
// configKeyDef defines metadata for a configuration key including validation rules.
2436
type configKeyDef struct {
2537
name string
38+
category configCategory
39+
description string
2640
keyType configKeyType
2741
defaultValue interface{}
2842
minValue float64
@@ -37,6 +51,8 @@ var configKeys = []configKeyDef{
3751
// Typography & Fonts
3852
{
3953
name: "font-family",
54+
category: categoryTypography,
55+
description: "Font family for body text (Arial, Times, Helvetica, Courier)",
4056
keyType: configKeyString,
4157
defaultValue: "Arial",
4258
getter: func(c *config.UserConfig) interface{} { return c.FontFamily },
@@ -45,6 +61,8 @@ var configKeys = []configKeyDef{
4561
},
4662
{
4763
name: "font-size",
64+
category: categoryTypography,
65+
description: "Font size in points (range: 1-72)",
4866
keyType: configKeyFloat64,
4967
defaultValue: 12.0,
5068
minValue: core.FontSizeMin,
@@ -55,6 +73,8 @@ var configKeys = []configKeyDef{
5573
},
5674
{
5775
name: "heading-scale",
76+
category: categoryTypography,
77+
description: "Heading size multiplier (range: 0.1-10.0)",
5878
keyType: configKeyFloat64,
5979
defaultValue: 1.5,
6080
minValue: core.HeadingScaleMin,
@@ -65,6 +85,8 @@ var configKeys = []configKeyDef{
6585
},
6686
{
6787
name: "line-spacing",
88+
category: categoryTypography,
89+
description: "Line spacing multiplier (range: 0.1-5.0)",
6890
keyType: configKeyFloat64,
6991
defaultValue: 1.2,
7092
minValue: core.LineSpacingMin,
@@ -76,6 +98,8 @@ var configKeys = []configKeyDef{
7698
// Code styling
7799
{
78100
name: "code-font",
101+
category: categoryCode,
102+
description: "Font family for code blocks (typically monospace)",
79103
keyType: configKeyString,
80104
defaultValue: "Courier",
81105
getter: func(c *config.UserConfig) interface{} { return c.CodeFont },
@@ -84,6 +108,8 @@ var configKeys = []configKeyDef{
84108
},
85109
{
86110
name: "code-size",
111+
category: categoryCode,
112+
description: "Font size for code blocks in points (range: 6-48)",
87113
keyType: configKeyFloat64,
88114
defaultValue: 10.0,
89115
minValue: core.CodeSizeMin,
@@ -95,6 +121,8 @@ var configKeys = []configKeyDef{
95121
// Page layout
96122
{
97123
name: "page-size",
124+
category: categoryPage,
125+
description: "Page size (A3, A4, A5, Letter, Legal, Tabloid)",
98126
keyType: configKeyPageSize,
99127
defaultValue: "A4",
100128
getter: func(c *config.UserConfig) interface{} { return c.PageSize },
@@ -103,6 +131,8 @@ var configKeys = []configKeyDef{
103131
},
104132
{
105133
name: "margin-top",
134+
category: categoryPage,
135+
description: "Top margin in mm (range: 0-100)",
106136
keyType: configKeyFloat64,
107137
defaultValue: 20.0,
108138
minValue: core.MarginMin,
@@ -113,6 +143,8 @@ var configKeys = []configKeyDef{
113143
},
114144
{
115145
name: "margin-bottom",
146+
category: categoryPage,
147+
description: "Bottom margin in mm (range: 0-100)",
116148
keyType: configKeyFloat64,
117149
defaultValue: 20.0,
118150
minValue: core.MarginMin,
@@ -123,6 +155,8 @@ var configKeys = []configKeyDef{
123155
},
124156
{
125157
name: "margin-left",
158+
category: categoryPage,
159+
description: "Left margin in mm (range: 0-100)",
126160
keyType: configKeyFloat64,
127161
defaultValue: 15.0,
128162
minValue: core.MarginMin,
@@ -133,6 +167,8 @@ var configKeys = []configKeyDef{
133167
},
134168
{
135169
name: "margin-right",
170+
category: categoryPage,
171+
description: "Right margin in mm (range: 0-100)",
136172
keyType: configKeyFloat64,
137173
defaultValue: 15.0,
138174
minValue: core.MarginMin,
@@ -144,6 +180,8 @@ var configKeys = []configKeyDef{
144180
// PDF metadata
145181
{
146182
name: "title",
183+
category: categoryMetadata,
184+
description: "PDF document title (embedded in PDF metadata)",
147185
keyType: configKeyString,
148186
defaultValue: "",
149187
getter: func(c *config.UserConfig) interface{} { return c.Title },
@@ -152,6 +190,8 @@ var configKeys = []configKeyDef{
152190
},
153191
{
154192
name: "author",
193+
category: categoryMetadata,
194+
description: "PDF document author (embedded in PDF metadata)",
155195
keyType: configKeyString,
156196
defaultValue: "",
157197
getter: func(c *config.UserConfig) interface{} { return c.Author },
@@ -160,6 +200,8 @@ var configKeys = []configKeyDef{
160200
},
161201
{
162202
name: "subject",
203+
category: categoryMetadata,
204+
description: "PDF document subject (embedded in PDF metadata)",
163205
keyType: configKeyString,
164206
defaultValue: "",
165207
getter: func(c *config.UserConfig) interface{} { return c.Subject },
@@ -169,6 +211,8 @@ var configKeys = []configKeyDef{
169211
// Mermaid settings
170212
{
171213
name: "mermaid-scale",
214+
category: categoryMermaid,
215+
description: "Mermaid diagram scale factor (range: 0.1-10.0)",
172216
keyType: configKeyFloat64,
173217
defaultValue: 2.2,
174218
minValue: core.MermaidScaleMin,
@@ -179,6 +223,8 @@ var configKeys = []configKeyDef{
179223
},
180224
{
181225
name: "mermaid-max-width",
226+
category: categoryMermaid,
227+
description: "Max diagram width in mm, 0=page width (range: 0-1000)",
182228
keyType: configKeyFloat64,
183229
defaultValue: 0.0,
184230
minValue: core.MermaidDimensionMin,
@@ -189,6 +235,8 @@ var configKeys = []configKeyDef{
189235
},
190236
{
191237
name: "mermaid-max-height",
238+
category: categoryMermaid,
239+
description: "Max diagram height in mm (range: 0-1000)",
192240
keyType: configKeyFloat64,
193241
defaultValue: 150.0,
194242
minValue: core.MermaidDimensionMin,
@@ -218,6 +266,24 @@ func validKeysString() string {
218266
return strings.Join(keys, ", ")
219267
}
220268

269+
// getKeysByCategory returns all keys grouped by category in display order.
270+
func getKeysByCategory() map[configCategory][]configKeyDef {
271+
result := make(map[configCategory][]configKeyDef)
272+
for _, k := range configKeys {
273+
result[k.category] = append(result[k.category], k)
274+
}
275+
return result
276+
}
277+
278+
// categoryOrder defines the display order for categories.
279+
var categoryOrder = []configCategory{
280+
categoryTypography,
281+
categoryCode,
282+
categoryPage,
283+
categoryMetadata,
284+
categoryMermaid,
285+
}
286+
221287
var configCmd = &cobra.Command{
222288
Use: "config",
223289
Short: "Manage configuration settings",
@@ -338,6 +404,115 @@ var configResetCmd = &cobra.Command{
338404
},
339405
}
340406

407+
// configKeysJSONMode tracks whether to output JSON format
408+
var configKeysJSONMode bool
409+
410+
var configKeysCmd = &cobra.Command{
411+
Use: "keys",
412+
Short: "List all available configuration keys",
413+
Long: "Display all available configuration keys with descriptions and default values",
414+
RunE: func(cmd *cobra.Command, args []string) error {
415+
if configKeysJSONMode {
416+
return printConfigKeysJSON()
417+
}
418+
return printConfigKeysText()
419+
},
420+
}
421+
422+
// printConfigKeysText outputs configuration keys in human-readable format.
423+
func printConfigKeysText() error {
424+
output := uiOutput
425+
426+
output.Info("Available configuration keys:")
427+
output.Println()
428+
429+
keysByCategory := getKeysByCategory()
430+
431+
for _, cat := range categoryOrder {
432+
keys, ok := keysByCategory[cat]
433+
if !ok {
434+
continue
435+
}
436+
437+
// Print category header
438+
output.Println(output.Bold(string(cat) + ":"))
439+
440+
for _, k := range keys {
441+
// Format: key-name description (default: value)
442+
defaultStr := formatDefaultValue(k.defaultValue)
443+
fmt.Printf(" %s\n", output.Highlight(k.name))
444+
fmt.Printf(" %s (default: %s)\n", k.description, defaultStr)
445+
}
446+
output.Println()
447+
}
448+
449+
return nil
450+
}
451+
452+
// configKeyJSON represents a config key in JSON format.
453+
type configKeyJSON struct {
454+
Name string `json:"name"`
455+
Category string `json:"category"`
456+
Description string `json:"description"`
457+
Type string `json:"type"`
458+
DefaultValue interface{} `json:"default"`
459+
MinValue *float64 `json:"min,omitempty"`
460+
MaxValue *float64 `json:"max,omitempty"`
461+
}
462+
463+
// printConfigKeysJSON outputs configuration keys in JSON format.
464+
func printConfigKeysJSON() error {
465+
var keys []configKeyJSON
466+
467+
for i := range configKeys {
468+
k := &configKeys[i]
469+
keyJSON := configKeyJSON{
470+
Name: k.name,
471+
Category: string(k.category),
472+
Description: k.description,
473+
DefaultValue: k.defaultValue,
474+
}
475+
476+
switch k.keyType {
477+
case configKeyString:
478+
keyJSON.Type = "string"
479+
case configKeyFloat64:
480+
keyJSON.Type = "number"
481+
// Copy values to avoid pointer issues
482+
minVal := k.minValue
483+
maxVal := k.maxValue
484+
keyJSON.MinValue = &minVal
485+
keyJSON.MaxValue = &maxVal
486+
case configKeyPageSize:
487+
keyJSON.Type = "enum"
488+
}
489+
490+
keys = append(keys, keyJSON)
491+
}
492+
493+
encoder := json.NewEncoder(os.Stdout)
494+
encoder.SetIndent("", " ")
495+
return encoder.Encode(keys)
496+
}
497+
498+
// formatDefaultValue returns a string representation of a default value.
499+
func formatDefaultValue(v interface{}) string {
500+
switch val := v.(type) {
501+
case string:
502+
if val == "" {
503+
return "(none)"
504+
}
505+
return fmt.Sprintf("%q", val)
506+
case float64:
507+
if val == float64(int(val)) {
508+
return fmt.Sprintf("%.0f", val)
509+
}
510+
return fmt.Sprintf("%.1f", val)
511+
default:
512+
return fmt.Sprintf("%v", v)
513+
}
514+
}
515+
341516
// printConfigValueFromKey prints a config value using the registry.
342517
func printConfigValueFromKey(userConfig *config.UserConfig, keyName string) {
343518
keyDef := findConfigKey(keyName)
@@ -421,4 +596,8 @@ func init() {
421596
configCmd.AddCommand(configListCmd)
422597
configCmd.AddCommand(configSetCmd)
423598
configCmd.AddCommand(configResetCmd)
599+
configCmd.AddCommand(configKeysCmd)
600+
601+
// Add --json flag to keys command
602+
configKeysCmd.Flags().BoolVar(&configKeysJSONMode, "json", false, "Output in JSON format")
424603
}

go.mod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ module github.com/fredcamaral/md-to-pdf
33
go 1.21
44

55
require (
6+
github.com/briandowns/spinner v1.23.2
7+
github.com/fatih/color v1.18.0
8+
github.com/fsnotify/fsnotify v1.9.0
69
github.com/jung-kurt/gofpdf v1.16.2
10+
github.com/mattn/go-isatty v0.0.20
711
github.com/spf13/cobra v1.8.0
812
github.com/yuin/goldmark v1.6.0
913
gopkg.in/yaml.v3 v3.0.1
1014
)
1115

1216
require (
1317
github.com/inconshreveable/mousetrap v1.1.0 // indirect
18+
github.com/mattn/go-colorable v0.1.13 // indirect
1419
github.com/spf13/pflag v1.0.5 // indirect
20+
golang.org/x/sys v0.25.0 // indirect
21+
golang.org/x/term v0.1.0 // indirect
1522
)

go.sum

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
2+
github.com/briandowns/spinner v1.23.2 h1:Zc6ecUnI+YzLmJniCfDNaMbW0Wid1d5+qcTq4L2FW8w=
3+
github.com/briandowns/spinner v1.23.2/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM=
24
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
35
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
7+
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
8+
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
9+
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
410
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
511
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
612
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
713
github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc=
814
github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0=
15+
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
16+
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
17+
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
18+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
19+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
920
github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
1021
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
1122
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -19,6 +30,12 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
1930
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
2031
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
2132
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
33+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
34+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
35+
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
36+
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
37+
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
38+
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
2239
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
2340
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
2441
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

0 commit comments

Comments
 (0)