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

feat: add a function to keep parts of a structure.

parent 3d7474e7
No related branches found
No related tags found
No related merge requests found
...@@ -45,7 +45,7 @@ Furthermore, it will parse the templates for images, anchors, and text. ...@@ -45,7 +45,7 @@ Furthermore, it will parse the templates for images, anchors, and text.
This will generate HTML files from the prepared templates. This will generate HTML files from the prepared templates.
```bash ```bash
bob template generate --input ./output/ --output ./output/ bob html generate --input ./output/ --output ./output/
``` ```
##### Sync ##### Sync
...@@ -53,7 +53,7 @@ bob template generate --input ./output/ --output ./output/ ...@@ -53,7 +53,7 @@ bob template generate --input ./output/ --output ./output/
This will sync HTML nodes from a source to a destination. This will sync HTML nodes from a source to a destination.
```bash ```bash
bob template sync --specification ./specification.yaml bob html sync --specification ./specification.yaml
``` ```
The structure of the specification file is as follows: The structure of the specification file is as follows:
...@@ -62,17 +62,19 @@ The structure of the specification file is as follows: ...@@ -62,17 +62,19 @@ The structure of the specification file is as follows:
sync: sync:
- source: - source:
path: './source.html' path: './source.html'
selector: '#mainscript' selector: 'head'
destination: destination:
path: './' path: './'
exclude: exclude:
- ./source.html - ./source.html
keep:
- title
``` ```
The `source` is the source file and the `selector` is the selector to find the node to sync. With the above specification, the `head` node from `./source.html` will be synced to all files in `./` except `./source.html`.
The `destination` is the destination directory and the `exclude` is a list of files to exclude. Furthermore, the `title` node will be kept.
Relative paths are relative to the specification file. Relative paths are relative to the specification file. Absolute paths are absolute, obviously.
#### Cut #### Cut
......
...@@ -44,7 +44,7 @@ func SyncHtml(p string) error { ...@@ -44,7 +44,7 @@ func SyncHtml(p string) error {
sourceFiles := make(map[string]*html.Node) sourceFiles := make(map[string]*html.Node)
destinationFiles := make(map[string]*html.Node) destinationFiles := make(map[string]*html.Node)
sourceDestination := make(map[string][]string) destinationFile := make(map[string][]string)
for _, r := range specification.Sync { for _, r := range specification.Sync {
...@@ -107,7 +107,7 @@ func SyncHtml(p string) error { ...@@ -107,7 +107,7 @@ func SyncHtml(p string) error {
} }
destinationFiles[pp] = dd destinationFiles[pp] = dd
sourceDestination[absSource] = append(sourceDestination[absSource], pp) destinationFile[absSource] = append(destinationFile[absSource], pp)
} }
...@@ -133,7 +133,7 @@ func SyncHtml(p string) error { ...@@ -133,7 +133,7 @@ func SyncHtml(p string) error {
} }
destinationFiles[d] = dd destinationFiles[d] = dd
sourceDestination[absSource] = append(sourceDestination[absSource], d) destinationFile[absSource] = append(destinationFile[absSource], d)
} }
...@@ -154,13 +154,32 @@ func SyncHtml(p string) error { ...@@ -154,13 +154,32 @@ func SyncHtml(p string) error {
sourceNode := query.MatchFirst(sourceFiles[absSource]) sourceNode := query.MatchFirst(sourceFiles[absSource])
dp := sourceDestination[absSource] dp := destinationFile[absSource]
for _, d := range dp { for _, d := range dp {
destinationSelector := r.Destination.Selector destinationSelector := r.Destination.Selector
if destinationSelector == "" { if destinationSelector == "" {
destinationSelector = sourceSelector destinationSelector = sourceSelector
} }
keepMap := make(map[string][]*html.Node)
for _, n := range r.Destination.Keep {
q, err := cascadia.Compile(n)
if err != nil {
return err
}
kNode := q.MatchAll(destinationFiles[d])
if kNode == nil {
return fmt.Errorf("keep node not found: %s", n)
}
for _, k := range kNode {
keepMap[n] = append(keepMap[n], engine.CloneNode(k))
}
}
query, err := cascadia.Compile(destinationSelector) query, err := cascadia.Compile(destinationSelector)
if err != nil { if err != nil {
return err return err
...@@ -174,6 +193,34 @@ func SyncHtml(p string) error { ...@@ -174,6 +193,34 @@ func SyncHtml(p string) error {
n := engine.CloneNode(sourceNode) n := engine.CloneNode(sourceNode)
destinationData.Parent.InsertBefore(n, destinationData) destinationData.Parent.InsertBefore(n, destinationData)
destinationData.Parent.RemoveChild(destinationData) destinationData.Parent.RemoveChild(destinationData)
for sel, k := range keepMap {
cas, err := cascadia.Compile(sel)
if err != nil {
return err
}
x := cas.MatchAll(destinationFiles[d])
if x == nil {
return fmt.Errorf("could not find selector %s in %s", sel, d)
}
for _, n1 := range x {
for _, kk := range k {
// node already removed, for example, by a previous keep
if n1.Parent == nil {
continue
}
n1.Parent.InsertBefore(kk, n1)
n1.Parent.RemoveChild(n1)
}
}
}
} }
} }
......
...@@ -4,9 +4,6 @@ import "gopkg.in/yaml.v3" ...@@ -4,9 +4,6 @@ import "gopkg.in/yaml.v3"
type PathOrList []string type PathOrList []string
// func (p PathOrList) MarshalYAML() (interface{}, error) {
// return yaml.Marshal(p)
// }
func (p *PathOrList) UnmarshalYAML(value *yaml.Node) error { func (p *PathOrList) UnmarshalYAML(value *yaml.Node) error {
var multi []string var multi []string
...@@ -24,15 +21,6 @@ func (p *PathOrList) UnmarshalYAML(value *yaml.Node) error { ...@@ -24,15 +21,6 @@ func (p *PathOrList) UnmarshalYAML(value *yaml.Node) error {
return nil return nil
} }
//func (p *PathOrList) UnmarshalYAML(b interface{}) error {
// var s string
// if err := yaml.Unmarshal(b, &s); err != nil {
// return err
// }
//
// return nil
//}
type Sync struct { type Sync struct {
Source struct { Source struct {
Selector string `yaml:"selector"` Selector string `yaml:"selector"`
...@@ -42,6 +30,7 @@ type Sync struct { ...@@ -42,6 +30,7 @@ type Sync struct {
Selector string `yaml:"selector"` Selector string `yaml:"selector"`
Path PathOrList `yaml:"path"` Path PathOrList `yaml:"path"`
Exclude []string `yaml:"exclude"` Exclude []string `yaml:"exclude"`
Keep []string `yaml:"keep"`
} `yaml:"destination"` } `yaml:"destination"`
} }
......
...@@ -2,19 +2,23 @@ sync: ...@@ -2,19 +2,23 @@ sync:
- source: - source:
path: '../original/test1.html' path: '../original/test1.html'
selector: '#mainscript' selector: head
destination: destination:
path: '../original/' path: '../original/'
exclude: exclude:
- ../original/test1.html - ../original/test1.html
keep:
- title
- meta[name=description]
- meta[name=author]
- source: # - source:
path: '../original/test1.html' # path: '../original/test1.html'
selector: '.deco' # selector: '.deco'
destination: # destination:
path: '../original/' # path: '../original/'
exclude: # exclude:
- ../original/test1.html # - ../original/test1.html
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="robots" content="noindex,noarchive"/> <meta name="robots" content="noindex"/>
<link rel="icon" type="image/x-icon" href="/asset/icon/favicon.svg"/> <link rel="icon" type="image/x-icon" href="/asset/icon/favicon.svg"/>
<meta name="theme-color" content="#c10000"/> <meta name="theme-color" content="#c10000"/>
...@@ -17,10 +17,10 @@ ...@@ -17,10 +17,10 @@
<link rel="icon" type="image/png" sizes="32x32" href="/asset/icon/favicon-32x32.png"/> <link rel="icon" type="image/png" sizes="32x32" href="/asset/icon/favicon-32x32.png"/>
<link rel="icon" type="image/png" sizes="16x16" href="/asset/icon/favicon-16x16.png"/> <link rel="icon" type="image/png" sizes="16x16" href="/asset/icon/favicon-16x16.png"/>
<link rel="mask-icon" href="/asset/icon/safari-pinned-tab.svg" color="#fd1d1d"/> <link rel="mask-icon" href="/asset/icon/safari-pinned-tab.svg" color="#fd1d1d"/>
<meta name="msapplication-TileColor" content="#fd1d1d"/>
<meta name="msapplication-TileImage" content="/asset/icon/mstile-144x144.png"/> <meta name="msapplication-TileImage" content="/asset/icon/mstile-144x144.png"/>
<meta name="msapplication-TileColor" content="#fd1d1d"/>
<title>Bad Request ME</title> <title>TESTx</title>
<meta name="description" content="The request was malformed or invalid."/> <meta name="description" content="The request was malformed or invalid."/>
<meta name="author" content="schukai GmbH"/> <meta name="author" content="schukai GmbH"/>
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="robots" content="noindex,noarchive"/> <meta name="robots" content="noindex"/>
<link rel="icon" type="image/x-icon" href="/asset/icon/favicon.svg"/> <link rel="icon" type="image/x-icon" href="/asset/icon/favicon.svg"/>
<meta name="theme-color" content="#c10000"/> <meta name="theme-color" content="#c10000"/>
...@@ -17,12 +17,12 @@ ...@@ -17,12 +17,12 @@
<link rel="icon" type="image/png" sizes="32x32" href="/asset/icon/favicon-32x32.png"/> <link rel="icon" type="image/png" sizes="32x32" href="/asset/icon/favicon-32x32.png"/>
<link rel="icon" type="image/png" sizes="16x16" href="/asset/icon/favicon-16x16.png"/> <link rel="icon" type="image/png" sizes="16x16" href="/asset/icon/favicon-16x16.png"/>
<link rel="mask-icon" href="/asset/icon/safari-pinned-tab.svg" color="#fd1d1d"/> <link rel="mask-icon" href="/asset/icon/safari-pinned-tab.svg" color="#fd1d1d"/>
<meta name="msapplication-TileColor" content="#fd1d1d"/>
<meta name="msapplication-TileImage" content="/asset/icon/mstile-144x144.png"/> <meta name="msapplication-TileImage" content="/asset/icon/mstile-144x144.png"/>
<meta name="msapplication-TileColor" content="#fd1d1d"/>
<title>Bad Request ME</title> <title>TEST2</title>
<meta name="description" content="The request was malformed or invalid."/> <meta name="description" content="The 2request was malformed or invalid."/>
<meta name="author" content="schukai GmbH"/> <meta name="author" content="sch2ukai GmbH"/>
<link rel="icon" href="/favicon.ico"/> <link rel="icon" href="/favicon.ico"/>
<link rel="icon" href="/favicon.svg" type="image/svg+xml"/> <link rel="icon" href="/favicon.svg" type="image/svg+xml"/>
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="robots" content="noindex,noarchive"/> <meta name="robots" content="noindex"/>
<link rel="icon" type="image/x-icon" href="/asset/icon/favicon.svg"/> <link rel="icon" type="image/x-icon" href="/asset/icon/favicon.svg"/>
<meta name="theme-color" content="#c10000"/> <meta name="theme-color" content="#c10000"/>
...@@ -17,12 +17,12 @@ ...@@ -17,12 +17,12 @@
<link rel="icon" type="image/png" sizes="32x32" href="/asset/icon/favicon-32x32.png"/> <link rel="icon" type="image/png" sizes="32x32" href="/asset/icon/favicon-32x32.png"/>
<link rel="icon" type="image/png" sizes="16x16" href="/asset/icon/favicon-16x16.png"/> <link rel="icon" type="image/png" sizes="16x16" href="/asset/icon/favicon-16x16.png"/>
<link rel="mask-icon" href="/asset/icon/safari-pinned-tab.svg" color="#fd1d1d"/> <link rel="mask-icon" href="/asset/icon/safari-pinned-tab.svg" color="#fd1d1d"/>
<meta name="msapplication-TileColor" content="#fd1d1d"/>
<meta name="msapplication-TileImage" content="/asset/icon/mstile-144x144.png"/> <meta name="msapplication-TileImage" content="/asset/icon/mstile-144x144.png"/>
<meta name="msapplication-TileColor" content="#fd1d1d"/>
<title>Bad Request ME</title> <title>TEST3</title>
<meta name="description" content="The request was malformed or invalid."/> <meta name="description" content="The 3request was malformed or invalid."/>
<meta name="author" content="schukai GmbH"/> <meta name="author" content="schukai3 GmbH"/>
<link rel="icon" href="/favicon.ico"/> <link rel="icon" href="/favicon.ico"/>
<link rel="icon" href="/favicon.svg" type="image/svg+xml"/> <link rel="icon" href="/favicon.svg" type="image/svg+xml"/>
......
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