Skip to content
Snippets Groups Projects
Verified Commit e2b64018 authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

feat: Keep values in existing file

parent 74647e65
No related branches found
No related tags found
No related merge requests found
...@@ -526,3 +526,4 @@ devenv.local.nix ...@@ -526,3 +526,4 @@ devenv.local.nix
# pre-commit # pre-commit
.pre-commit-config.yaml .pre-commit-config.yaml
.attach_pid*
...@@ -23,7 +23,7 @@ This repository contains a file called flake.nix. You can install this program u ...@@ -23,7 +23,7 @@ This repository contains a file called flake.nix. You can install this program u
#### Prepare #### Prepare
```bash ```bash
bob template prepare --input ./templates/ --output ./output/ bob template prepare --input ./templates/ --output ./output/ --data-file ./data.yaml
``` ```
This will create files in the `./output/` directory with all parsed templates from `./templates/` directory. This will create files in the `./output/` directory with all parsed templates from `./templates/` directory.
...@@ -32,13 +32,15 @@ Also, a data YAML. This data YAML is used to generate the final files. ...@@ -32,13 +32,15 @@ Also, a data YAML. This data YAML is used to generate the final files.
This command prepares the title, description, keywords, and other metadata for the templates. This command prepares the title, description, keywords, and other metadata for the templates.
Furthermore, it will parse the templates for images, anchors, and text. Furthermore, it will parse the templates for images, anchors, and text.
If the argument `--data-file` is not set, the data YAML will be written to `./output/data.yaml`.
| Original | Parsed | | Original | Parsed |
|-------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------| |-------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| `<html lang="en"><head>` | `<html lang="en" data-attributes="lang path:lang"><head>` | | `<html lang="en"><head>` | `<html lang="en" data-attributes="lang path:lang"><head>` |
| `<title>Bob</title>` | `<title data-attributes="title path:title">Bob</title>` | | `<title>Bob</title>` | `<title data-attributes="title path:title">Bob</title>` |
| `<meta name="description" content="Bob is a html and html fragment builder">` | `<meta name="description" content="Bob is a html and html fragment builder" data-attributes="description path:meta.description">` | | `<meta name="description" content="Bob is a html and html fragment builder">` | `<meta name="description" content="Bob is a html and html fragment builder" data-attributes="description path:meta.description">` |
| `<img alt="alt text" title="my title" src="..." ` | `<img alt="alt text" title="my title" src="..." data-attributes="alt path:img.id1003.alt title path:img.id1003.title src path:img.id1003.src">` | | `<img alt="alt text" title="my title" src="..." ` | `<img alt="alt text" title="my title" src="..." data-attributes="alt path:img.id1003.alt title path:img.id1003.title src path:img.id1003.src">` |
| `<a href="https://gitlab.schukai.com/oss/bob">` | `<a href="https://gitlab.schukai.com/oss/bob" data-attributes="href path:a.id1004.href">` | | `<a href="https://gitlab.schukai.com/oss/bob">` | `<a href="https://gitlab.schukai.com/oss/bob" data-attributes="href path:a.id1004.href">` |
| `<p>Bob is a html and html fragment builder</p>` | `<p><span data-attributes="text path:p.id1005.text">Bob is a html and html fragment builder</span></p>` | | `<p>Bob is a html and html fragment builder</p>` | `<p><span data-attributes="text path:p.id1005.text">Bob is a html and html fragment builder</span></p>` |
......
...@@ -82,6 +82,29 @@ func (d *Definition) PrepareTemplate(s *xflags.Settings[Definition]) { ...@@ -82,6 +82,29 @@ func (d *Definition) PrepareTemplate(s *xflags.Settings[Definition]) {
storage := types.NewPageDataStorage() storage := types.NewPageDataStorage()
i := d.GetDataFile()
// unmarshal data file yaml to page data storage
if _, err := os.Stat(i); err == nil {
data, err := os.ReadFile(i)
if err != nil {
s.AddError(err)
} else {
err = yaml.Unmarshal(data, storage)
if err != nil {
s.AddError(err)
}
}
if d.Verbose {
fmt.Printf("Loaded data file %s\n", i)
}
}
toDelete := []string{}
for page, _ := range storage {
toDelete = append(toDelete, page)
}
err := filepath.Walk(d.Template.Prepare.Input, func(path string, info os.FileInfo, err error) error { err := filepath.Walk(d.Template.Prepare.Input, func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
...@@ -97,9 +120,34 @@ func (d *Definition) PrepareTemplate(s *xflags.Settings[Definition]) { ...@@ -97,9 +120,34 @@ func (d *Definition) PrepareTemplate(s *xflags.Settings[Definition]) {
return nil return nil
} }
return template2.PrepareHtmlFile(path, d.Template.Prepare.Output, storage) if d.Verbose {
fmt.Printf("Prepare %s\n", path)
}
key, err := template2.PrepareHtmlFile(path, d.Template.Prepare.Output, storage)
if err != nil {
return err
}
for i, v := range toDelete {
if v == key {
toDelete = append(toDelete[:i], toDelete[i+1:]...)
break
}
}
return nil
}) })
for _, v := range toDelete {
if d.Verbose {
fmt.Printf("Delete %s\n", v)
}
delete(storage, v)
}
if err != nil { if err != nil {
s.AddError(err) s.AddError(err)
} }
...@@ -109,22 +157,31 @@ func (d *Definition) PrepareTemplate(s *xflags.Settings[Definition]) { ...@@ -109,22 +157,31 @@ func (d *Definition) PrepareTemplate(s *xflags.Settings[Definition]) {
s.AddError(err) s.AddError(err)
} else { } else {
o := d.Template.Prepare.DataFile o := d.GetDataFile()
if o == "" {
o = "data.yaml"
}
if !path.IsAbs(o) {
o = path.Join(d.Template.Prepare.Output, o)
}
err = os.WriteFile(o, data, os.ModePerm) err = os.WriteFile(o, data, os.ModePerm)
if err != nil { if err != nil {
s.AddError(err) s.AddError(err)
} }
if d.Verbose {
fmt.Printf("Saved data file %s\n", o)
}
}
}
func (d *Definition) GetDataFile() string {
o := d.Template.Prepare.DataFile
if o == "" {
o = "data.yaml"
} }
if !path.IsAbs(o) {
o = path.Join(d.Template.Prepare.Output, o)
}
return o
} }
func (d *Definition) PrintHelp(s *xflags.Settings[Definition]) { func (d *Definition) PrintHelp(s *xflags.Settings[Definition]) {
......
...@@ -28,7 +28,7 @@ func GenerateFiles(dataPath, out string) error { ...@@ -28,7 +28,7 @@ func GenerateFiles(dataPath, out string) error {
for name, page := range storage { for name, page := range storage {
p := path.Join(dir, name) p := path.Join(dir, name)
html, err := Generate(page, p) generatedHtml, err := Generate(page, p)
if err != nil { if err != nil {
return err return err
} }
...@@ -40,7 +40,7 @@ func GenerateFiles(dataPath, out string) error { ...@@ -40,7 +40,7 @@ func GenerateFiles(dataPath, out string) error {
return err return err
} }
err = os.WriteFile(outFile, []byte(html), 0644) err = os.WriteFile(outFile, []byte(generatedHtml), 0644)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"os" "os"
"path/filepath" "path/filepath"
"strings"
) )
type Specification struct { type Specification struct {
...@@ -202,16 +201,6 @@ func SyncHtml(p string) error { ...@@ -202,16 +201,6 @@ func SyncHtml(p string) error {
} }
x := cas.MatchAll(destinationFiles[d]) x := cas.MatchAll(destinationFiles[d])
if x == nil { if x == nil {
builder := &strings.Builder{}
// Render the HTML to the builder
html.Render(builder, destinationFiles[d])
// Print the captured HTML to the console
a := builder.String()
fmt.Println(a)
return fmt.Errorf("could not find selector %s in %s", sel, d) return fmt.Errorf("could not find selector %s in %s", sel, d)
} }
......
...@@ -73,7 +73,16 @@ func setDataAttributesAttribute(node *html.Node, name, attribute, instruction st ...@@ -73,7 +73,16 @@ func setDataAttributesAttribute(node *html.Node, name, attribute, instruction st
} }
func prepateMeta(node *html.Node, attrKey, attrValue string, storage *types.PageData) { func prepareMeta(node *html.Node, attrKey, attrValue string, storage *types.PageData) {
if storage.Meta == nil {
storage.Meta = make(map[string]string)
}
if _, ok := storage.Meta[attrValue]; ok {
return
}
sel, err := cascadia.Parse("meta[" + attrKey + "=" + attrValue + "]") sel, err := cascadia.Parse("meta[" + attrKey + "=" + attrValue + "]")
if err != nil { if err != nil {
return return
...@@ -115,6 +124,10 @@ func prepareLanguage(node *html.Node, storage *types.PageData) { ...@@ -115,6 +124,10 @@ func prepareLanguage(node *html.Node, storage *types.PageData) {
func prepareTitle(node *html.Node, storage *types.PageData) { func prepareTitle(node *html.Node, storage *types.PageData) {
if storage.Title != "" {
return
}
selector, err := cascadia.Parse("title") selector, err := cascadia.Parse("title")
if err != nil { if err != nil {
return return
...@@ -150,6 +163,10 @@ func prepareAnchors(node *html.Node, storage *types.PageData) { ...@@ -150,6 +163,10 @@ func prepareAnchors(node *html.Node, storage *types.PageData) {
return return
} }
copyOfAnchors := make([]types.Anchor, len(storage.Anchors))
copy(copyOfAnchors, storage.Anchors)
storage.Anchors = []types.Anchor{}
for _, n := range list { for _, n := range list {
title := util.GetAttribute(n.Attr, "title") title := util.GetAttribute(n.Attr, "title")
...@@ -175,6 +192,21 @@ func prepareAnchors(node *html.Node, storage *types.PageData) { ...@@ -175,6 +192,21 @@ func prepareAnchors(node *html.Node, storage *types.PageData) {
}) })
} }
for _, anchor := range copyOfAnchors {
foundIndex := -1
for index, i := range storage.Images {
if i.Id == anchor.Id {
foundIndex = index
break
}
}
if foundIndex > -1 {
storage.Anchors[foundIndex] = anchor
}
}
} }
func prepareImages(node *html.Node, storage *types.PageData) { func prepareImages(node *html.Node, storage *types.PageData) {
...@@ -189,6 +221,10 @@ func prepareImages(node *html.Node, storage *types.PageData) { ...@@ -189,6 +221,10 @@ func prepareImages(node *html.Node, storage *types.PageData) {
return return
} }
copyOfImages := make([]types.Image, len(storage.Images))
copy(copyOfImages, storage.Images)
storage.Images = []types.Image{}
for _, n := range list { for _, n := range list {
alt := util.GetAttribute(n.Attr, "alt") alt := util.GetAttribute(n.Attr, "alt")
...@@ -215,6 +251,20 @@ func prepareImages(node *html.Node, storage *types.PageData) { ...@@ -215,6 +251,20 @@ func prepareImages(node *html.Node, storage *types.PageData) {
} }
for _, image := range copyOfImages {
foundIndex := -1
for index, i := range storage.Images {
if i.Id == image.Id {
foundIndex = index
break
}
}
if foundIndex > -1 {
storage.Images[foundIndex] = image
}
}
} }
func prepareTranslationJson(node *html.Node, storage *types.PageData) { func prepareTranslationJson(node *html.Node, storage *types.PageData) {
...@@ -228,6 +278,10 @@ func prepareTranslationJson(node *html.Node, storage *types.PageData) { ...@@ -228,6 +278,10 @@ func prepareTranslationJson(node *html.Node, storage *types.PageData) {
return return
} }
copyOfTranslations := make([]types.Translations, len(storage.Translations))
copy(copyOfTranslations, storage.Translations)
storage.Translations = []types.Translations{}
for _, n := range list { for _, n := range list {
id := util.GetAttribute(n.Attr, "id") id := util.GetAttribute(n.Attr, "id")
...@@ -258,6 +312,21 @@ func prepareTranslationJson(node *html.Node, storage *types.PageData) { ...@@ -258,6 +312,21 @@ func prepareTranslationJson(node *html.Node, storage *types.PageData) {
}) })
} }
for _, translation := range copyOfTranslations {
foundIndex := -1
for index, t := range storage.Translations {
if t.Id == translation.Id {
foundIndex = index
break
}
}
if foundIndex > -1 {
storage.Translations[foundIndex] = translation
}
}
} }
func prepareTextNodes(node *html.Node, storage *types.PageData) { func prepareTextNodes(node *html.Node, storage *types.PageData) {
...@@ -272,8 +341,26 @@ func prepareTextNodes(node *html.Node, storage *types.PageData) { ...@@ -272,8 +341,26 @@ func prepareTextNodes(node *html.Node, storage *types.PageData) {
return return
} }
copyOfTextNodes := make([]types.Text, len(storage.Text))
copy(copyOfTextNodes, storage.Text)
storage.Text = []types.Text{}
runNodes(body, storage) runNodes(body, storage)
for _, text := range copyOfTextNodes {
foundIndex := -1
for index, t := range storage.Text {
if t.Id == text.Id {
foundIndex = index
break
}
}
if foundIndex > -1 {
storage.Text[foundIndex] = text
}
}
} }
func runNodes(n *html.Node, storage *types.PageData) { func runNodes(n *html.Node, storage *types.PageData) {
...@@ -340,21 +427,27 @@ func checkNodes(n *html.Node, storage *types.PageData) { ...@@ -340,21 +427,27 @@ func checkNodes(n *html.Node, storage *types.PageData) {
} }
func PrepareHtmlFile(from, to string, storage types.PageDataStorage) error { func PrepareHtmlFile(from, to string, storage types.PageDataStorage) (string, error) {
node, err := util.LoadHtml(from) node, err := util.LoadHtml(from)
if err != nil { if err != nil {
return err return "", err
} }
var pd *types.PageData
var ok bool
p := path.Base(from) p := path.Base(from)
pd := types.NewPageData()
storage[p] = pd if pd, ok = storage[p]; !ok {
pd = types.NewPageData()
storage[p] = pd
}
prepareLanguage(node, pd) prepareLanguage(node, pd)
prepareTitle(node, pd) prepareTitle(node, pd)
prepateMeta(node, "name", "description", pd) prepareMeta(node, "name", "description", pd)
prepateMeta(node, "name", "keywords", pd) prepareMeta(node, "name", "keywords", pd)
prepateMeta(node, "name", "author", pd) prepareMeta(node, "name", "author", pd)
prepareImages(node, pd) prepareImages(node, pd)
prepareAnchors(node, pd) prepareAnchors(node, pd)
...@@ -365,6 +458,6 @@ func PrepareHtmlFile(from, to string, storage types.PageDataStorage) error { ...@@ -365,6 +458,6 @@ func PrepareHtmlFile(from, to string, storage types.PageDataStorage) error {
pd.Export = path.Join(pd.Lang, path.Base(from)) pd.Export = path.Join(pd.Lang, path.Base(from))
to = path.Join(to, path.Base(from)) to = path.Join(to, path.Base(from))
return util.SaveHtml(to, node) return p, util.SaveHtml(to, node)
} }
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"errors" "errors"
"golang.org/x/net/html" "golang.org/x/net/html"
"os" "os"
"path"
"strconv" "strconv"
) )
...@@ -76,11 +77,24 @@ func SaveHtml(p string, node *html.Node) error { ...@@ -76,11 +77,24 @@ func SaveHtml(p string, node *html.Node) error {
_, err = os.Stat(p) _, err = os.Stat(p)
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
var dir = path.Dir(p)
err := os.MkdirAll(dir, os.ModePerm)
if err != nil {
return err
}
f, err = os.Create(p) f, err = os.Create(p)
if err != nil {
return err
}
} else if err != nil { } else if err != nil {
return err return err
} else { } else {
os.Remove(p) err := os.Remove(p)
if err != nil {
return err
}
f, err = os.Create(p) f, err = os.Create(p)
if err != nil { if err != nil {
return err return err
......
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
"devenv": { "devenv": {
"locked": { "locked": {
"dir": "src/modules", "dir": "src/modules",
"lastModified": 1688925746, "lastModified": 1689667485,
"narHash": "sha256-Lora6gsuAdVeVeGj2nD4joxTu+jZsAwySlxY1XZVq8o=", "narHash": "sha256-tLNoMRSPLlW1D4wgNpSIPUUHd6x1GdjAhETLpRTKnfo=",
"owner": "cachix", "owner": "cachix",
"repo": "devenv", "repo": "devenv",
"rev": "b058455b37d2a1833eb71bebd3d2b2aa58ce70d7", "rev": "6f8add968bc12bf81d845eb7dc684a0733bb1518",
"type": "github" "type": "github"
}, },
"original": { "original": {
...@@ -74,11 +74,11 @@ ...@@ -74,11 +74,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1688925019, "lastModified": 1689631193,
"narHash": "sha256-281HjmJycKt8rZ0/vpYTtJuZrQl6mpGNlUFf8cebmeA=", "narHash": "sha256-AGSkBZaiTODQc8eT1rZDrQIjtb8JtFwJ0wVPzArlrnM=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "2b356dae6208d422236c4cdc48f3bed749f9daea", "rev": "57695599bdc4f7bfe5d28cfa23f14b3d8bdf8a5f",
"type": "github" "type": "github"
}, },
"original": { "original": {
...@@ -115,11 +115,11 @@ ...@@ -115,11 +115,11 @@
"nixpkgs-stable": "nixpkgs-stable" "nixpkgs-stable": "nixpkgs-stable"
}, },
"locked": { "locked": {
"lastModified": 1688596063, "lastModified": 1689668210,
"narHash": "sha256-9t7RxBiKWHygsqXtiNATTJt4lim/oSYZV3RG8OjDDng=", "narHash": "sha256-XAATwDkaUxH958yXLs1lcEOmU6pSEIkatY3qjqk8X0E=",
"owner": "cachix", "owner": "cachix",
"repo": "pre-commit-hooks.nix", "repo": "pre-commit-hooks.nix",
"rev": "c8d18ba345730019c3faf412c96a045ade171895", "rev": "eb433bff05b285258be76513add6f6c57b441775",
"type": "github" "type": "github"
}, },
"original": { "original": {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment