Go CLI that turns the markdown currency of this stack (Redmine notes, Discourse posts, briefing output) into typeset PDFs: two embedded typst templates (report with title page/TOC/headers, dense brief), front-matter (title/subtitle/author/date/classification/template), GFM tables, and bar charts rendered in pure Go (go-chart) from fenced chart data blocks. Engine is a prebuilt typst 0.15.1 container pinned by digest and run --network none; PDF bytes to stdout or -o. Exit codes 0/1/2. All dev in docker (dev.sh/Makefile); unit tests + golden typst fixtures plus a host-side smoke against the real engine container. Generated with Crush Assisted-by: Crush:glm-5.2
38 lines
1.1 KiB
Go
38 lines
1.1 KiB
Go
package chart
|
|
|
|
import "fmt"
|
|
|
|
// FirstValueAnnotation returns an annotation series of just the first value of a value provider as an annotation.
|
|
func FirstValueAnnotation(innerSeries ValuesProvider, vfs ...ValueFormatter) AnnotationSeries {
|
|
var vf ValueFormatter
|
|
if len(vfs) > 0 {
|
|
vf = vfs[0]
|
|
} else if typed, isTyped := innerSeries.(ValueFormatterProvider); isTyped {
|
|
_, vf = typed.GetValueFormatters()
|
|
} else {
|
|
vf = FloatValueFormatter
|
|
}
|
|
|
|
var firstValue Value2
|
|
if typed, isTyped := innerSeries.(FirstValuesProvider); isTyped {
|
|
firstValue.XValue, firstValue.YValue = typed.GetFirstValues()
|
|
firstValue.Label = vf(firstValue.YValue)
|
|
} else {
|
|
firstValue.XValue, firstValue.YValue = innerSeries.GetValues(0)
|
|
firstValue.Label = vf(firstValue.YValue)
|
|
}
|
|
|
|
var seriesName string
|
|
var seriesStyle Style
|
|
if typed, isTyped := innerSeries.(Series); isTyped {
|
|
seriesName = fmt.Sprintf("%s - First Value", typed.GetName())
|
|
seriesStyle = typed.GetStyle()
|
|
}
|
|
|
|
return AnnotationSeries{
|
|
Name: seriesName,
|
|
Style: seriesStyle,
|
|
Annotations: []Value2{firstValue},
|
|
}
|
|
}
|