From 065c344c036414dcf908738527b83d9116f8c8cd Mon Sep 17 00:00:00 2001 From: Daniel Fichtinger Date: Thu, 28 Nov 2024 18:44:47 -0500 Subject: [PATCH] fixed stylesheet embedding --- cmd/zona/main.go | 2 +- internal/builder/build_page.go | 2 +- internal/builder/config.go | 44 +++++++--- internal/util/path.go | 10 +++ test/style/style.css | 148 +++++++++++++++++++++++++++++++++ 5 files changed, 192 insertions(+), 14 deletions(-) create mode 100644 test/style/style.css diff --git a/cmd/zona/main.go b/cmd/zona/main.go index 488cc5f..d61da6c 100644 --- a/cmd/zona/main.go +++ b/cmd/zona/main.go @@ -41,7 +41,7 @@ func main() { } } - settings := builder.GetSettings(*rootPath) + settings := builder.GetSettings(*rootPath, "foobar") err := builder.Traverse(*rootPath, "foobar", settings) if err != nil { fmt.Printf("Error: %s\n", err.Error()) diff --git a/internal/builder/build_page.go b/internal/builder/build_page.go index c78f39e..c5fac75 100644 --- a/internal/builder/build_page.go +++ b/internal/builder/build_page.go @@ -60,7 +60,7 @@ func buildPageData(m Metadata, path string, settings *Settings) *PageData { if style, ok := m["style"].(string); ok { p.Stylesheet = style } else { - p.Stylesheet = settings.StylesheetName + p.Stylesheet = settings.StylePath } if header, ok := m["header"].(string); ok { p.HeaderName = header diff --git a/internal/builder/config.go b/internal/builder/config.go index 6809c36..de88646 100644 --- a/internal/builder/config.go +++ b/internal/builder/config.go @@ -11,13 +11,14 @@ import ( ) var defaultNames = map[string]string{ - "config": "config.yml", - "header": "header.md", - "footer": "footer.md", - "style": "style.css", - "icon": "favicon.png", - "article": "article.html", - "template": "default.html", + "config": "config.yml", + "header": "header.md", + "footer": "footer.md", + "style": "style.css", + "stylePath": filepath.Join("style", "style.css"), + "icon": "favicon.png", + "article": "article.html", + "template": "default.html", } //go:embed embed/article.html @@ -40,9 +41,12 @@ type Settings struct { DefaultTemplateName string ArticleTemplate string Stylesheet []byte + StylePath string Icon []byte } +var isDefaultStyle bool + // processSetting checks the user's configuration for // each option. If set, reads the specified file. If not, // default option is used. @@ -55,12 +59,13 @@ func processSetting(c map[string]interface{}, s string) (string, []byte, error) return name, val, nil } else { val := readEmbed(defaultNames[s]) + isDefaultStyle = true return defaultNames[s], val, nil } } // buildSettings constructs the Settings struct. -func buildSettings(f []byte) (*Settings, error) { +func buildSettings(f []byte, outRoot string) (*Settings, error) { s := &Settings{} var c map[string]interface{} // Parse YAML @@ -79,12 +84,27 @@ func buildSettings(f []byte) (*Settings, error) { } s.FooterName = n s.Footer = template.HTML(MdToHTML(v)) + isDefaultStyle = false n, v, err = processSetting(c, "style") if err != nil { return nil, err } s.StylesheetName = n - s.Stylesheet = MdToHTML(v) + s.Stylesheet = v + + if isDefaultStyle { + stylePath := filepath.Join(outRoot, defaultNames["stylePath"]) + // We convert the stylesheet path to its website root dir format and store it + s.StylePath = "/" + util.StripTopDir(stylePath) + err := util.CreateParents(stylePath) + if err != nil { + return nil, util.ErrorPrepend("Could not create default stylesheet directory: ", err) + } + err = util.WriteFile(s.Stylesheet, stylePath) + if err != nil { + return nil, util.ErrorPrepend("Could not create default stylesheet: ", err) + } + } n, v, err = processSetting(c, "icon") if err != nil { @@ -114,7 +134,7 @@ func readEmbed(name string) []byte { return f } -func GetSettings(root string) *Settings { +func GetSettings(root string, outRoot string) *Settings { var config []byte configPath := filepath.Join(root, defaultNames["config"]) if !util.FileExists(configPath) { @@ -122,12 +142,12 @@ func GetSettings(root string) *Settings { config = readEmbed(defaultNames["config"]) } else { var err error - config, err = util.ReadFile(configPath) + config, err = util.ReadFile(filepath.Join(root, configPath)) if err != nil { log.Fatalln("Fatal internal error: Config file exists but could not be read!") } } - s, err := buildSettings(config) + s, err := buildSettings(config, outRoot) if err != nil { log.Fatalf("Fatal error: could not parse config: %u\n", err) } diff --git a/internal/util/path.go b/internal/util/path.go index 145bc0e..12fa15e 100644 --- a/internal/util/path.go +++ b/internal/util/path.go @@ -47,6 +47,7 @@ func FileExists(path string) bool { return !os.IsNotExist(err) } +// CreateParents creates the parent directories required for a given path func CreateParents(path string) error { dir := filepath.Dir(path) // Check if the parent directory already exists @@ -59,3 +60,12 @@ func CreateParents(path string) error { } return nil } + +func StripTopDir(path string) string { + cleanedPath := filepath.Clean(path) + components := strings.Split(cleanedPath, string(filepath.Separator)) + if len(components) <= 1 { + return path + } + return filepath.Join(components[1:]...) +} diff --git a/test/style/style.css b/test/style/style.css new file mode 100644 index 0000000..7199c84 --- /dev/null +++ b/test/style/style.css @@ -0,0 +1,148 @@ +:root { + --main-text-color: white; + --main-bg-color: #1b1b1b; + --main-transparent: rgba(255, 255, 255, 0.15); + --main-small-text-color: rgba(255, 255, 255, 0.45); +} + +body { + line-height: 1.6; + font-size: 18px; + font-family: sans-serif; + background: var(--main-bg-color); + color: var(--main-text-color); + padding-left: calc(100vw - 100%); +} +h1 { + margin-block-start: 0.67rem; + margin-block-end: 0.67rem; + font-size: 2rem; + font-weight: bold; +} +article h1:first-of-type { + margin-block-start: 1.67rem; +} +h2 { + margin-block-start: 0.83rem; + margin-block-end: 0.83rem; + font-size: 1.5rem; + font-weight: bold; +} +h3 { + margin-block-start: 1rem; + margin-block-end: 1rem; + font-size: 1.17em; + font-weight: bold; +} +h4 { + margin-block-start: 1.33rem; + margin-block-end: 1.33rem; + font-size: 1rem; + font-weight: bold; +} +article h1 + h4:first-of-type { + margin-block-start: 0rem; +} +h5 { + margin-block-start: 1.67rem; + margin-block-end: 1.67rem; + font-size: 0.83rem; + font-weight: bold; +} +h6 { + margin-block-start: 2.33rem; + margin-block-end: 2.33rem; + font-size: 0.67rem; + font-weight: bold; +} +a { + color: var(--main-text-color); +} +a:hover { + background: var(--main-transparent); +} +img { + width: auto; + height: auto; +} +blockquote { + color: var(--main-small-text-color); + border-left: 3px solid var(--main-transparent); + padding: 0 1rem; + margin-left: 0; + margin-right: 0; +} +hr { + border: none; + height: 1px; + background: var(--main-small-text-color); +} +code { + background: var(--main-transparent); + border-radius: 0.1875rem; + /* padding: .0625rem .1875rem; */ + /* margin: 0 .1875rem; */ +} +code, +pre { + white-space: pre-wrap; + word-wrap: break-word; + overflow-wrap: break-word; +} +small { + font-size: 0.95rem; + color: var(--main-small-text-color); +} +small a { + color: inherit; /* Inherit the color of the surrounding text */ + text-decoration: underline; /* Optional: Keep the underline to indicate a link */ +} +.image-container { + text-align: center; + margin: 20px 0; /* Optional: add some spacing around the image container */ +} + +.image-container img { + /* max-width: 308px; */ + max-height: 308px; +} + +.image-container small { + display: block; /* Ensure the caption is on a new line */ + margin-top: 5px; /* Optional: adjust spacing between image and caption */ +} + +.image-container small a { + color: inherit; /* Ensure the link color matches the small text */ + text-decoration: underline; /* Optional: underline to indicate a link */ +} +#header ul { + list-style-type: none; + padding-left: 0; +} +#header li { + display: inline; + font-size: 1.2rem; + margin-right: 1.2rem; +} +#container { + margin: 2.5rem auto; + width: 90%; + max-width: 60ch; +} +#postlistdiv ul { + list-style-type: none; + padding-left: 0; +} +.moreposts { + font-size: 0.95rem; + padding-left: 0.5rem; +} +#nextprev { + text-align: center; + margin-top: 1.4rem; + font-size: 0.95rem; +} +#footer { + color: var(--main-small-text-color); +}