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
# pre-commit
.pre-commit-config.yaml
.attach_pid*
......@@ -23,7 +23,7 @@ This repository contains a file called flake.nix. You can install this program u
#### Prepare
```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.
......@@ -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.
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 |
|-------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| `<html lang="en"><head>` | `<html lang="en" data-attributes="lang path:lang"><head>` |
| `<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">` |
| `<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">` |
| `<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">` |
| `<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]) {
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 {
if err != nil {
......@@ -97,9 +120,34 @@ func (d *Definition) PrepareTemplate(s *xflags.Settings[Definition]) {
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 {
s.AddError(err)
}
......@@ -109,22 +157,31 @@ func (d *Definition) PrepareTemplate(s *xflags.Settings[Definition]) {
s.AddError(err)
} else {
o := d.Template.Prepare.DataFile
if o == "" {
o = "data.yaml"
}
if !path.IsAbs(o) {
o = path.Join(d.Template.Prepare.Output, o)
}
o := d.GetDataFile()
err = os.WriteFile(o, data, os.ModePerm)
if err != nil {
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]) {
......
......@@ -28,7 +28,7 @@ func GenerateFiles(dataPath, out string) error {
for name, page := range storage {
p := path.Join(dir, name)
html, err := Generate(page, p)
generatedHtml, err := Generate(page, p)
if err != nil {
return err
}
......@@ -40,7 +40,7 @@ func GenerateFiles(dataPath, out string) error {
return err
}
err = os.WriteFile(outFile, []byte(html), 0644)
err = os.WriteFile(outFile, []byte(generatedHtml), 0644)
if err != nil {
return err
}
......
......@@ -9,7 +9,6 @@ import (
"gopkg.in/yaml.v3"
"os"
"path/filepath"
"strings"
)
type Specification struct {
......@@ -202,16 +201,6 @@ func SyncHtml(p string) error {
}
x := cas.MatchAll(destinationFiles[d])
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)
}
......
......@@ -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 + "]")
if err != nil {
return
......@@ -115,6 +124,10 @@ func prepareLanguage(node *html.Node, storage *types.PageData) {
func prepareTitle(node *html.Node, storage *types.PageData) {
if storage.Title != "" {
return
}
selector, err := cascadia.Parse("title")
if err != nil {
return
......@@ -150,6 +163,10 @@ func prepareAnchors(node *html.Node, storage *types.PageData) {
return
}
copyOfAnchors := make([]types.Anchor, len(storage.Anchors))
copy(copyOfAnchors, storage.Anchors)
storage.Anchors = []types.Anchor{}
for _, n := range list {
title := util.GetAttribute(n.Attr, "title")
......@@ -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) {
......@@ -189,6 +221,10 @@ func prepareImages(node *html.Node, storage *types.PageData) {
return
}
copyOfImages := make([]types.Image, len(storage.Images))
copy(copyOfImages, storage.Images)
storage.Images = []types.Image{}
for _, n := range list {
alt := util.GetAttribute(n.Attr, "alt")
......@@ -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) {
......@@ -228,6 +278,10 @@ func prepareTranslationJson(node *html.Node, storage *types.PageData) {
return
}
copyOfTranslations := make([]types.Translations, len(storage.Translations))
copy(copyOfTranslations, storage.Translations)
storage.Translations = []types.Translations{}
for _, n := range list {
id := util.GetAttribute(n.Attr, "id")
......@@ -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) {
......@@ -272,8 +341,26 @@ func prepareTextNodes(node *html.Node, storage *types.PageData) {
return
}
copyOfTextNodes := make([]types.Text, len(storage.Text))
copy(copyOfTextNodes, storage.Text)
storage.Text = []types.Text{}
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) {
......@@ -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)
if err != nil {
return err
return "", err
}
var pd *types.PageData
var ok bool
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)
prepareTitle(node, pd)
prepateMeta(node, "name", "description", pd)
prepateMeta(node, "name", "keywords", pd)
prepateMeta(node, "name", "author", pd)
prepareMeta(node, "name", "description", pd)
prepareMeta(node, "name", "keywords", pd)
prepareMeta(node, "name", "author", pd)
prepareImages(node, pd)
prepareAnchors(node, pd)
......@@ -365,6 +458,6 @@ func PrepareHtmlFile(from, to string, storage types.PageDataStorage) error {
pd.Export = path.Join(pd.Lang, 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 (
"errors"
"golang.org/x/net/html"
"os"
"path"
"strconv"
)
......@@ -76,11 +77,24 @@ func SaveHtml(p string, node *html.Node) error {
_, err = os.Stat(p)
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)
if err != nil {
return err
}
} else if err != nil {
return err
} else {
os.Remove(p)
err := os.Remove(p)
if err != nil {
return err
}
f, err = os.Create(p)
if err != nil {
return err
......
......@@ -3,11 +3,11 @@
"devenv": {
"locked": {
"dir": "src/modules",
"lastModified": 1688925746,
"narHash": "sha256-Lora6gsuAdVeVeGj2nD4joxTu+jZsAwySlxY1XZVq8o=",
"lastModified": 1689667485,
"narHash": "sha256-tLNoMRSPLlW1D4wgNpSIPUUHd6x1GdjAhETLpRTKnfo=",
"owner": "cachix",
"repo": "devenv",
"rev": "b058455b37d2a1833eb71bebd3d2b2aa58ce70d7",
"rev": "6f8add968bc12bf81d845eb7dc684a0733bb1518",
"type": "github"
},
"original": {
......@@ -74,11 +74,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1688925019,
"narHash": "sha256-281HjmJycKt8rZ0/vpYTtJuZrQl6mpGNlUFf8cebmeA=",
"lastModified": 1689631193,
"narHash": "sha256-AGSkBZaiTODQc8eT1rZDrQIjtb8JtFwJ0wVPzArlrnM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2b356dae6208d422236c4cdc48f3bed749f9daea",
"rev": "57695599bdc4f7bfe5d28cfa23f14b3d8bdf8a5f",
"type": "github"
},
"original": {
......@@ -115,11 +115,11 @@
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1688596063,
"narHash": "sha256-9t7RxBiKWHygsqXtiNATTJt4lim/oSYZV3RG8OjDDng=",
"lastModified": 1689668210,
"narHash": "sha256-XAATwDkaUxH958yXLs1lcEOmU6pSEIkatY3qjqk8X0E=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "c8d18ba345730019c3faf412c96a045ade171895",
"rev": "eb433bff05b285258be76513add6f6c57b441775",
"type": "github"
},
"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