Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
HTML
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Terraform modules
Monitor
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
OSS
Libraries
Go
Markup
HTML
Commits
d8a8ed9b
Verified
Commit
d8a8ed9b
authored
2 years ago
by
Volker Schukai
Browse files
Options
Downloads
Patches
Plain Diff
feat: basic feature
parent
5b9aa060
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
engine/engine.go
+390
-62
390 additions, 62 deletions
engine/engine.go
engine/engine_test.go
+140
-23
140 additions, 23 deletions
engine/engine_test.go
with
530 additions
and
85 deletions
engine/engine.go
+
390
−
62
View file @
d8a8ed9b
...
@@ -3,6 +3,7 @@ package engine
...
@@ -3,6 +3,7 @@ package engine
import
(
import
(
"fmt"
"fmt"
"github.com/andybalholm/cascadia"
"github.com/andybalholm/cascadia"
"gitlab.schukai.com/oss/libraries/go/utilities/data.git"
"golang.org/x/net/html"
"golang.org/x/net/html"
"io"
"io"
"reflect"
"reflect"
...
@@ -14,8 +15,8 @@ const attributePrefix = "data-"
...
@@ -14,8 +15,8 @@ const attributePrefix = "data-"
type
Engine
struct
{
type
Engine
struct
{
attributePrefix
string
attributePrefix
string
errors
[]
error
errors
[]
error
data
*
map
[
string
]
any
logNode
*
html
.
Node
logNode
*
html
.
Node
transformer
*
data
.
Transformer
}
}
func
(
e
*
Engine
)
SetLogNode
(
node
*
html
.
Node
)
*
Engine
{
func
(
e
*
Engine
)
SetLogNode
(
node
*
html
.
Node
)
*
Engine
{
...
@@ -36,10 +37,11 @@ func (e *Engine) GetLogNode() *html.Node {
...
@@ -36,10 +37,11 @@ func (e *Engine) GetLogNode() *html.Node {
return
e
.
logNode
return
e
.
logNode
}
}
func
New
(
data
*
map
[
string
]
any
)
*
Engine
{
func
New
(
dataset
map
[
any
]
any
)
*
Engine
{
return
&
Engine
{
return
&
Engine
{
attributePrefix
:
attributePrefix
,
attributePrefix
:
attributePrefix
,
data
:
data
,
transformer
:
data
.
NewTransformer
(
&
dataset
)
,
}
}
}
}
...
@@ -56,7 +58,7 @@ func (e *Engine) ProcessNode(node *html.Node) *Engine {
...
@@ -56,7 +58,7 @@ func (e *Engine) ProcessNode(node *html.Node) *Engine {
return
e
return
e
}
}
if
node
.
Type
==
html
.
ElementNode
{
if
node
.
Type
==
html
.
ElementNode
||
node
.
Type
==
html
.
DocumentNode
{
e
.
ProcessElement
(
node
)
e
.
ProcessElement
(
node
)
}
}
return
e
return
e
...
@@ -71,17 +73,19 @@ func functionExists(obj interface{}, funcName string) bool {
...
@@ -71,17 +73,19 @@ func functionExists(obj interface{}, funcName string) bool {
return
false
return
false
}
}
func
(
e
*
Engine
)
callFunction
(
funcName
string
,
node
*
html
.
Node
,
value
string
)
*
Engine
{
//
func (e *Engine) callFunction(funcName string, node *html.Node, value string) *Engine {
reflect
.
ValueOf
(
e
)
.
MethodByName
(
funcName
)
.
Call
([]
reflect
.
Value
{
reflect
.
ValueOf
(
node
),
reflect
.
ValueOf
(
value
)})
//
reflect.ValueOf(e).MethodByName(funcName).Call([]reflect.Value{reflect.ValueOf(node), reflect.ValueOf(value)})
return
e
//
return e
}
//
}
func
(
e
*
Engine
)
ProcessElement
(
node
*
html
.
Node
)
*
Engine
{
func
(
e
*
Engine
)
ProcessElement
(
node
*
html
.
Node
)
*
Engine
{
if
node
.
Type
!=
html
.
ElementNode
{
if
node
.
Type
!=
html
.
ElementNode
&&
node
.
Type
!=
html
.
DocumentNode
{
e
.
errors
=
append
(
e
.
errors
,
&
UnsupportedTypeError
{
Message
:
"Unsupported element type"
,
NodeType
:
node
.
Type
})
e
.
errors
=
append
(
e
.
errors
,
&
UnsupportedTypeError
{
Message
:
"Unsupported element type"
,
NodeType
:
node
.
Type
})
return
e
return
e
}
}
runChildren
:=
true
for
_
,
attr
:=
range
node
.
Attr
{
for
_
,
attr
:=
range
node
.
Attr
{
if
attr
.
Namespace
!=
""
||
if
attr
.
Namespace
!=
""
||
len
(
attr
.
Key
)
<
len
(
e
.
attributePrefix
)
||
len
(
attr
.
Key
)
<
len
(
e
.
attributePrefix
)
||
...
@@ -90,22 +94,366 @@ func (e *Engine) ProcessElement(node *html.Node) *Engine {
...
@@ -90,22 +94,366 @@ func (e *Engine) ProcessElement(node *html.Node) *Engine {
}
}
fktName
:=
attr
.
Key
[
len
(
e
.
attributePrefix
)
:
]
fktName
:=
attr
.
Key
[
len
(
e
.
attributePrefix
)
:
]
fktName
=
buildFunctionName
(
fktName
,
true
)
fktName
=
strings
.
ToLower
(
fktName
)
fmt
.
Println
(
fktName
)
switch
fktName
{
if
!
functionExists
(
e
,
fktName
)
{
case
"repeat"
:
// e.errors = append(e.errors, &UnsupportedFunctionError{Message: "Unsupported function", FunctionName: fktName})
runChildren
=
false
node
.
Attr
=
removeAttribute
(
node
.
Attr
,
attr
.
Key
)
e
.
processRepeat
(
node
,
attr
)
case
"debug"
:
node
.
Attr
=
removeAttribute
(
node
.
Attr
,
attr
.
Key
)
e
.
processDebug
(
node
,
attr
)
case
"attributes"
:
node
.
Attr
=
removeAttribute
(
node
.
Attr
,
attr
.
Key
)
e
.
processAttributes
(
node
,
attr
)
case
"condition"
:
node
.
Attr
=
removeAttribute
(
node
.
Attr
,
attr
.
Key
)
e
.
processCondition
(
node
,
attr
)
case
"replace"
:
node
.
Attr
=
removeAttribute
(
node
.
Attr
,
attr
.
Key
)
e
.
processReplace
(
node
,
attr
)
case
"replace-self"
:
node
.
Attr
=
removeAttribute
(
node
.
Attr
,
attr
.
Key
)
e
.
processReplaceSelf
(
node
,
attr
)
case
"remove"
:
node
.
Attr
=
removeAttribute
(
node
.
Attr
,
attr
.
Key
)
e
.
processRemove
(
node
,
attr
)
case
"removetag"
:
node
.
Attr
=
removeAttribute
(
node
.
Attr
,
attr
.
Key
)
e
.
processRemoveTag
(
node
,
attr
)
default
:
continue
continue
}
}
e
.
callFunction
(
fktName
,
node
,
attr
.
Val
)
}
if
runChildren
{
e
.
walkNodes
(
node
)
}
}
return
e
return
e
}
}
func
(
e
*
Engine
)
processRepeat
(
node
*
html
.
Node
,
attr
html
.
Attribute
)
*
Engine
{
parent
:=
node
.
Parent
if
parent
==
nil
{
e
.
errors
=
append
(
e
.
errors
,
&
UnsupportedTypeError
{
Message
:
"Node has no parent"
,
NodeType
:
node
.
Type
})
return
e
}
v
:=
attr
.
Val
if
v
==
""
{
return
e
}
p
:=
strings
.
Index
(
v
,
" "
)
if
p
==
-
1
{
return
e
}
key
:=
v
[
:
p
]
instruction
:=
v
[
p
+
1
:
]
iterator
,
err
:=
e
.
transformer
.
Transform
(
instruction
)
if
err
!=
nil
{
e
.
errors
=
append
(
e
.
errors
,
err
)
return
e
}
var
nextSibling
*
html
.
Node
for
child
:=
parent
.
FirstChild
;
child
!=
nil
;
child
=
child
.
NextSibling
{
if
child
==
node
{
nextSibling
=
node
.
NextSibling
parent
.
RemoveChild
(
node
)
break
}
}
data
:=
e
.
transformer
.
Dataset
()
if
data
==
nil
{
data
=
&
map
[
any
]
any
{}
}
var
errors
[]
error
switch
reflect
.
TypeOf
(
iterator
)
.
Kind
()
{
case
reflect
.
Map
:
listValue
:=
reflect
.
ValueOf
(
iterator
)
for
_
,
key
:=
range
listValue
.
MapKeys
()
{
item
:=
listValue
.
MapIndex
(
key
)
.
Interface
()
errors
=
runNode
(
node
,
data
,
key
.
String
(),
item
,
nextSibling
,
parent
)
}
case
reflect
.
Slice
:
listValue
:=
reflect
.
ValueOf
(
iterator
)
for
i
:=
0
;
i
<
listValue
.
Len
();
i
++
{
item
:=
listValue
.
Index
(
i
)
.
Interface
()
errors
=
runNode
(
node
,
data
,
key
,
item
,
nextSibling
,
parent
)
}
default
:
e
.
errors
=
append
(
e
.
errors
,
&
UnsupportedTypeError
{
Message
:
"Unsupported iterator type"
,
NodeType
:
node
.
Type
})
}
if
errors
!=
nil
{
e
.
errors
=
append
(
e
.
errors
,
errors
...
)
}
return
e
}
func
runNode
(
node
*
html
.
Node
,
data
*
map
[
any
]
any
,
key
string
,
item
interface
{},
nextSibling
*
html
.
Node
,
parent
*
html
.
Node
)
[]
error
{
_
,
ok
:=
(
*
data
)[
key
]
if
ok
{
return
[]
error
{
&
UnsupportedTypeError
{
Message
:
"Key already exists"
,
NodeType
:
node
.
Type
}}
}
(
*
data
)[
key
]
=
item
defer
delete
(
*
data
,
key
)
x
:=
New
(
*
data
)
template
:=
cloneNode
(
node
,
make
(
map
[
*
html
.
Node
]
*
html
.
Node
))
template
.
Parent
=
nil
template
.
PrevSibling
=
nil
template
.
NextSibling
=
nil
x
.
ProcessNodes
(
template
)
if
nextSibling
!=
nil
{
parent
.
InsertBefore
(
template
,
nextSibling
)
nextSibling
=
template
}
else
{
parent
.
AppendChild
(
template
)
}
return
x
.
errors
}
func
cloneNode
(
n
*
html
.
Node
,
cache
map
[
*
html
.
Node
]
*
html
.
Node
)
*
html
.
Node
{
if
n
==
nil
{
return
nil
}
if
val
,
ok
:=
cache
[
n
];
ok
{
return
val
}
val
:=
&
html
.
Node
{}
cache
[
n
]
=
val
val
.
Type
=
n
.
Type
val
.
Data
=
n
.
Data
val
.
DataAtom
=
n
.
DataAtom
val
.
Namespace
=
n
.
Namespace
val
.
Attr
=
make
([]
html
.
Attribute
,
len
(
n
.
Attr
))
copy
(
val
.
Attr
,
n
.
Attr
)
for
child
:=
n
.
FirstChild
;
child
!=
nil
;
child
=
child
.
NextSibling
{
val
.
AppendChild
(
cloneNode
(
child
,
cache
))
}
return
val
}
func
(
e
*
Engine
)
processReplaceSelf
(
node
*
html
.
Node
,
attr
html
.
Attribute
)
*
Engine
{
replace
:=
attr
.
Val
if
replace
==
""
{
return
e
}
r
,
err
:=
e
.
transformer
.
Transform
(
replace
)
if
err
!=
nil
{
e
.
errors
=
append
(
e
.
errors
,
err
)
return
e
}
if
node
.
Parent
==
nil
{
e
.
errors
=
append
(
e
.
errors
,
&
UnsupportedTypeError
{
Message
:
"Node has no parent"
,
NodeType
:
node
.
Type
})
return
e
}
parent
:=
node
.
Parent
parent
.
InsertBefore
(
&
html
.
Node
{
Type
:
html
.
TextNode
,
Data
:
r
.
(
string
),
},
node
)
parent
.
RemoveChild
(
node
)
return
e
}
func
(
e
*
Engine
)
processReplace
(
node
*
html
.
Node
,
attr
html
.
Attribute
)
*
Engine
{
replace
:=
attr
.
Val
if
replace
==
""
{
return
e
}
r
,
err
:=
e
.
transformer
.
Transform
(
replace
)
if
err
!=
nil
{
e
.
errors
=
append
(
e
.
errors
,
err
)
return
e
}
for
child
:=
node
.
FirstChild
;
child
!=
nil
;
child
=
child
.
NextSibling
{
node
.
RemoveChild
(
child
)
}
nn
:=
&
html
.
Node
{
Type
:
html
.
TextNode
,
}
switch
r
.
(
type
)
{
case
string
:
nn
.
Data
=
r
.
(
string
)
default
:
nn
.
Data
=
fmt
.
Sprintf
(
"%v"
,
r
)
}
node
.
AppendChild
(
nn
)
return
e
}
func
(
e
*
Engine
)
processRemove
(
node
*
html
.
Node
,
attr
html
.
Attribute
)
*
Engine
{
if
node
.
Parent
==
nil
{
e
.
errors
=
append
(
e
.
errors
,
&
UnsupportedTypeError
{
Message
:
"Node has no parent"
,
NodeType
:
node
.
Type
})
return
e
}
var
condition
any
var
err
error
v
:=
attr
.
Val
if
v
!=
""
{
condition
,
err
=
e
.
transformer
.
Transform
(
v
)
if
err
!=
nil
{
e
.
errors
=
append
(
e
.
errors
,
err
)
return
e
}
switch
condition
.
(
type
)
{
case
bool
:
if
!
condition
.
(
bool
)
{
return
e
}
}
}
removeNode
(
node
,
e
,
v
)
return
e
}
func
(
e
*
Engine
)
processRemoveTag
(
node
*
html
.
Node
,
attr
html
.
Attribute
)
*
Engine
{
parent
:=
node
.
Parent
var
condition
any
var
err
error
v
:=
attr
.
Val
if
v
!=
""
{
condition
,
err
=
e
.
transformer
.
Transform
(
v
)
if
err
!=
nil
{
e
.
errors
=
append
(
e
.
errors
,
err
)
return
e
}
switch
condition
.
(
type
)
{
case
bool
:
if
!
condition
.
(
bool
)
{
return
e
}
}
}
if
parent
==
nil
{
prefix
:=
e
.
attributePrefix
node
.
Attr
=
append
(
node
.
Attr
,
html
.
Attribute
{
Key
:
prefix
+
"condition-hide"
,
Val
:
v
,
})
return
e
}
for
node
.
FirstChild
!=
nil
{
child
:=
node
.
FirstChild
node
.
RemoveChild
(
child
)
parent
.
InsertBefore
(
child
,
node
)
}
parent
.
RemoveChild
(
node
)
return
e
}
func
(
e
*
Engine
)
processDebug
(
node
*
html
.
Node
,
attr
html
.
Attribute
)
*
Engine
{
e
.
logNode
=
node
return
e
}
func
(
e
*
Engine
)
processCondition
(
node
*
html
.
Node
,
attr
html
.
Attribute
)
*
Engine
{
condition
:=
attr
.
Val
if
condition
==
""
{
return
e
}
r
,
err
:=
e
.
transformer
.
Transform
(
condition
)
if
err
!=
nil
{
e
.
errors
=
append
(
e
.
errors
,
err
)
return
e
}
shouldRemove
:=
true
switch
r
.
(
type
)
{
case
bool
:
if
r
==
true
{
shouldRemove
=
false
}
}
if
shouldRemove
{
removeNode
(
node
,
e
,
condition
)
}
return
e
}
func
removeNode
(
node
*
html
.
Node
,
e
*
Engine
,
condition
string
)
{
if
node
.
Parent
!=
nil
{
node
.
Parent
.
RemoveChild
(
node
)
}
else
{
prefix
:=
e
.
attributePrefix
node
.
Attr
=
append
(
node
.
Attr
,
html
.
Attribute
{
Key
:
prefix
+
"condition-hide"
,
Val
:
condition
,
})
}
}
func
isHtmlFragment
(
html
string
)
bool
{
func
isHtmlFragment
(
html
string
)
bool
{
if
strings
.
HasPrefix
(
html
,
"<!DOCTYPE html>"
)
{
if
strings
.
HasPrefix
(
html
,
"<!DOCTYPE html>"
)
{
...
@@ -165,7 +513,7 @@ func (e *Engine) ProcessHtml(w io.Writer, r io.Reader) *Engine {
...
@@ -165,7 +513,7 @@ func (e *Engine) ProcessHtml(w io.Writer, r io.Reader) *Engine {
return
e
return
e
}
}
e
.
ProcessNode
(
doc
)
e
.
ProcessNode
s
(
doc
)
if
isFragment
{
if
isFragment
{
...
@@ -218,9 +566,10 @@ func (e *Engine) walkNodes(n *html.Node) *Engine {
...
@@ -218,9 +566,10 @@ func (e *Engine) walkNodes(n *html.Node) *Engine {
return
e
return
e
}
}
for
c
:=
n
.
FirstChild
;
c
!=
nil
;
c
=
c
.
NextSibling
{
for
c
:=
n
.
FirstChild
;
c
!=
nil
;
{
//ns := c.NextSibling
e
.
ProcessNode
(
c
)
e
.
ProcessNode
(
c
)
e
.
walkNodes
(
c
)
c
=
c
.
NextSibling
}
}
return
e
return
e
...
@@ -237,7 +586,9 @@ func (e *Engine) ProcessNodes(node *html.Node) *Engine {
...
@@ -237,7 +586,9 @@ func (e *Engine) ProcessNodes(node *html.Node) *Engine {
return
e
return
e
}
}
func
(
e
*
Engine
)
ProcessAttributes
(
node
*
html
.
Node
,
value
string
)
*
Engine
{
func
(
e
*
Engine
)
processAttributes
(
node
*
html
.
Node
,
attr
html
.
Attribute
)
*
Engine
{
value
:=
attr
.
Val
value
=
strings
.
TrimSpace
(
value
)
value
=
strings
.
TrimSpace
(
value
)
values
:=
strings
.
Split
(
value
,
","
)
values
:=
strings
.
Split
(
value
,
","
)
...
@@ -264,7 +615,17 @@ func (e *Engine) ProcessAttributes(node *html.Node, value string) *Engine {
...
@@ -264,7 +615,17 @@ func (e *Engine) ProcessAttributes(node *html.Node, value string) *Engine {
key
:=
v
[
:
pos
]
key
:=
v
[
:
pos
]
instruction
:=
v
[
pos
+
1
:
]
instruction
:=
v
[
pos
+
1
:
]
cVal
:=
e
.
getValue
(
instruction
)
val
,
err
:=
e
.
transformer
.
Transform
(
instruction
)
if
err
!=
nil
{
e
.
errors
=
append
(
e
.
errors
,
err
)
continue
}
var
cVal
string
if
val
!=
nil
{
cVal
=
val
.
(
string
)
}
node
.
Attr
=
append
(
node
.
Attr
,
html
.
Attribute
{
node
.
Attr
=
append
(
node
.
Attr
,
html
.
Attribute
{
Key
:
key
,
Key
:
key
,
Val
:
cVal
,
Val
:
cVal
,
...
@@ -275,50 +636,17 @@ func (e *Engine) ProcessAttributes(node *html.Node, value string) *Engine {
...
@@ -275,50 +636,17 @@ func (e *Engine) ProcessAttributes(node *html.Node, value string) *Engine {
return
e
return
e
}
}
func
(
e
*
Engine
)
getValue
(
instruction
string
)
string
{
func
removeAttribute
(
attrs
[]
html
.
Attribute
,
key
string
)
[]
html
.
Attribute
{
return
""
}
var
uppercaseAcronym
=
map
[
string
]
string
{
var
result
[]
html
.
Attribute
"ID"
:
"id"
,
}
// Converts a string to CamelCase
for
_
,
attr
:=
range
attrs
{
func
buildFunctionName
(
s
string
,
initCase
bool
)
string
{
if
attr
.
Key
==
key
{
s
=
strings
.
TrimSpace
(
s
)
continue
if
s
==
""
{
return
s
}
if
a
,
ok
:=
uppercaseAcronym
[
s
];
ok
{
s
=
a
}
n
:=
strings
.
Builder
{}
n
.
Grow
(
len
(
s
))
capNext
:=
initCase
for
i
,
v
:=
range
[]
byte
(
s
)
{
vIsCap
:=
v
>=
'A'
&&
v
<=
'Z'
vIsLow
:=
v
>=
'a'
&&
v
<=
'z'
if
capNext
{
if
vIsLow
{
v
+=
'A'
v
-=
'a'
}
}
else
if
i
==
0
{
if
vIsCap
{
v
+=
'a'
v
-=
'A'
}
}
if
vIsCap
||
vIsLow
{
n
.
WriteByte
(
v
)
capNext
=
false
}
else
if
vIsNum
:=
v
>=
'0'
&&
v
<=
'9'
;
vIsNum
{
n
.
WriteByte
(
v
)
capNext
=
true
}
else
{
capNext
=
v
==
'_'
||
v
==
' '
||
v
==
'-'
||
v
==
'.'
}
}
result
=
append
(
result
,
attr
)
}
}
return
"Process"
+
n
.
String
()
return
result
}
}
This diff is collapsed.
Click to expand it.
engine/engine_test.go
+
140
−
23
View file @
d8a8ed9b
...
@@ -18,13 +18,13 @@ func TestProcessNode(t *testing.T) {
...
@@ -18,13 +18,13 @@ func TestProcessNode(t *testing.T) {
html
string
html
string
hasErrors
bool
hasErrors
bool
expected
string
expected
string
data
map
[
string
]
any
data
map
[
any
]
any
}{
}{
{
{
html
:
`<div data-test="test"></div>`
,
html
:
`<div data-test="test"></div>`
,
hasErrors
:
false
,
hasErrors
:
false
,
expected
:
`<div data-test="test"></div>`
,
expected
:
`<div data-test="test"></div>`
,
data
:
map
[
string
]
any
{
data
:
map
[
any
]
any
{
"test"
:
"test"
,
"test"
:
"test"
,
},
},
},
},
...
@@ -32,14 +32,14 @@ func TestProcessNode(t *testing.T) {
...
@@ -32,14 +32,14 @@ func TestProcessNode(t *testing.T) {
html
:
`<div data-test="test"></div>`
,
html
:
`<div data-test="test"></div>`
,
hasErrors
:
false
,
hasErrors
:
false
,
expected
:
`<div data-test="test"></div>`
,
expected
:
`<div data-test="test"></div>`
,
data
:
map
[
string
]
any
{
data
:
map
[
any
]
any
{
"test"
:
"test"
,
"test"
:
"test"
,
},
},
},
},
}
}
for
_
,
td
:=
range
testData
{
for
_
,
td
:=
range
testData
{
e
:=
New
(
&
td
.
data
)
e
:=
New
(
td
.
data
)
doc
,
_
:=
html
.
Parse
(
strings
.
NewReader
(
td
.
html
))
doc
,
_
:=
html
.
Parse
(
strings
.
NewReader
(
td
.
html
))
e
.
ProcessNode
(
doc
)
e
.
ProcessNode
(
doc
)
assert
.
Equal
(
t
,
td
.
hasErrors
,
e
.
HasErrors
())
assert
.
Equal
(
t
,
td
.
hasErrors
,
e
.
HasErrors
())
...
@@ -54,42 +54,42 @@ func TestProcessHtml(t *testing.T) {
...
@@ -54,42 +54,42 @@ func TestProcessHtml(t *testing.T) {
html
string
html
string
hasErrors
bool
hasErrors
bool
expected
string
expected
string
data
map
[
string
]
any
data
map
[
any
]
any
}{
}{
{
{
html
:
`<div data-test="test"></div>`
,
html
:
`<div data-test="test"></div>`
,
hasErrors
:
false
,
hasErrors
:
false
,
expected
:
`<div data-test="test"></div>`
,
expected
:
`<div data-test="test"></div>`
,
data
:
map
[
string
]
any
{},
data
:
map
[
any
]
any
{},
},
},
{
{
html
:
`<div data-test="test"></div>`
,
html
:
`<div data-test="test"></div>`
,
hasErrors
:
false
,
hasErrors
:
false
,
expected
:
`<div data-test="test"></div>`
,
expected
:
`<div data-test="test"></div>`
,
data
:
map
[
string
]
any
{},
data
:
map
[
any
]
any
{},
},
},
{
{
html
:
`<li>test1</li><li>test2</li>`
,
html
:
`<li>test1</li><li>test2</li>`
,
hasErrors
:
false
,
hasErrors
:
false
,
expected
:
`<li>test1</li><li>test2</li>`
,
expected
:
`<li>test1</li><li>test2</li>`
,
data
:
map
[
string
]
any
{},
data
:
map
[
any
]
any
{},
},
},
{
{
html
:
`<tr><td>test1</td><td>test2</td></tr><tr><td>test1</td><td>test2</td></tr>`
,
html
:
`<tr><td>test1</td><td>test2</td></tr><tr><td>test1</td><td>test2</td></tr>`
,
hasErrors
:
false
,
hasErrors
:
false
,
expected
:
`<tr><td>test1</td><td>test2</td></tr><tr><td>test1</td><td>test2</td></tr>`
,
expected
:
`<tr><td>test1</td><td>test2</td></tr><tr><td>test1</td><td>test2</td></tr>`
,
data
:
map
[
string
]
any
{},
data
:
map
[
any
]
any
{},
},
},
{
{
html
:
`<td>test1</td><td>test2</td>`
,
html
:
`<td>test1</td><td>test2</td>`
,
hasErrors
:
false
,
hasErrors
:
false
,
expected
:
`<td>test1</td><td>test2</td>`
,
expected
:
`<td>test1</td><td>test2</td>`
,
data
:
map
[
string
]
any
{},
data
:
map
[
any
]
any
{},
},
},
}
}
for
_
,
td
:=
range
testData
{
for
_
,
td
:=
range
testData
{
e
:=
New
(
&
td
.
data
)
e
:=
New
(
td
.
data
)
stringWriter
:=
&
strings
.
Builder
{}
stringWriter
:=
&
strings
.
Builder
{}
e
.
ProcessHtml
(
stringWriter
,
strings
.
NewReader
(
td
.
html
))
e
.
ProcessHtml
(
stringWriter
,
strings
.
NewReader
(
td
.
html
))
...
@@ -133,21 +133,138 @@ func TestGetAttributePrefix(t *testing.T) {
...
@@ -133,21 +133,138 @@ func TestGetAttributePrefix(t *testing.T) {
assert
.
Equal
(
t
,
"test"
,
e
.
GetAttributePrefix
())
assert
.
Equal
(
t
,
"test"
,
e
.
GetAttributePrefix
())
}
}
func
TestProcessNodes
(
t
*
testing
.
T
)
{
func
TestProcessNodesSingleForDebug
(
t
*
testing
.
T
)
{
e
:=
New
(
nil
)
doc
,
_
:=
html
.
Parse
(
strings
.
NewReader
(
`<div data-test="test">
html
:=
`<div><div data-repeat="city path:cities"><p data-replace="path:city.name"></p></div></div>`
<ul data-attributes="class static:hello">
expected
:=
`<div><div><p>London</p></div><div><p>Paris</p></div></div>`
<li>test1</li>
<li>test2</li>
mapData
:=
map
[
any
]
any
{
<li><a href="test"></a></li>
"cities"
:
[]
map
[
any
]
any
{
</ul>
map
[
any
]
any
{
"name"
:
"London"
,
"population"
:
1000000
,
},
map
[
any
]
any
{
"name"
:
"Paris"
,
"population"
:
2000000
,
},
},
}
</div>`
))
e
:=
New
(
mapData
)
e
.
ProcessNodes
(
doc
)
stringWriter
:=
&
strings
.
Builder
{}
stringWriter
:=
&
strings
.
Builder
{}
html
.
Render
(
stringWriter
,
doc
)
e
.
ProcessHtml
(
stringWriter
,
strings
.
NewReader
(
html
))
assert
.
Equal
(
t
,
`<div data-test="test">`
,
stringWriter
.
String
())
processedDoc
:=
stringWriter
.
String
()
assert
.
Equal
(
t
,
expected
,
processedDoc
)
if
e
.
HasErrors
()
{
for
_
,
err
:=
range
e
.
GetErrors
()
{
t
.
Log
(
err
)
}
t
.
Fail
()
}
}
func
TestProcessNodes
(
t
*
testing
.
T
)
{
testData
:=
[]
struct
{
html
string
hasErrors
bool
expected
string
}{
{
html
:
`<div><div data-repeat="city path:cities"><p data-replace="path:city.name"></p></div></div>`
,
hasErrors
:
false
,
expected
:
`<div><div><p>London</p></div><div><p>Paris</p></div></div>`
,
},
{
html
:
`<div><div data-replace="path:test"></div></div>`
,
hasErrors
:
false
,
expected
:
`<div><div>test</div></div>`
,
},
{
html
:
`<div><div data-replace-self="path:test"></div></div>`
,
hasErrors
:
false
,
expected
:
`<div>test</div>`
,
},
{
html
:
`<div><div data-attributes="class path:test | toupper"></div></div>`
,
hasErrors
:
false
,
expected
:
`<div><div class="TEST"></div></div>`
,
},
{
html
:
`<div><div data-attributes="class path:test | toupper, style path:cities.0.name | lowercase"></div></div>`
,
hasErrors
:
false
,
expected
:
`<div><div class="TEST" style="london"></div></div>`
,
},
{
html
:
`<div><div data-repeat="sub path:list"><p data-replace-self="index:sub"></p></div></div>`
,
hasErrors
:
false
,
expected
:
`<div><div>test1</div><div>test2</div><div>test3</div></div>`
,
},
}
for
_
,
td
:=
range
testData
{
t
.
Run
(
"test"
,
func
(
t
*
testing
.
T
)
{
mapData
:=
map
[
any
]
any
{
"test"
:
"test"
,
"cities"
:
[]
map
[
any
]
any
{
map
[
any
]
any
{
"name"
:
"London"
,
"population"
:
1000000
,
},
map
[
any
]
any
{
"name"
:
"Paris"
,
"population"
:
2000000
,
},
},
"list"
:
[]
string
{
"test1"
,
"test2"
,
"test3"
},
}
e
:=
New
(
mapData
)
stringWriter
:=
&
strings
.
Builder
{}
e
.
ProcessHtml
(
stringWriter
,
strings
.
NewReader
(
td
.
html
))
processedDoc
:=
stringWriter
.
String
()
assert
.
Equal
(
t
,
td
.
expected
,
processedDoc
)
if
e
.
HasErrors
()
{
for
_
,
err
:=
range
e
.
GetErrors
()
{
t
.
Log
(
err
)
}
t
.
Fail
()
}
})
}
}
func
BenchmarkProcessNodes
(
b
*
testing
.
B
)
{
mapData
:=
map
[
any
]
any
{
"test"
:
"test"
,
"cities"
:
[]
map
[
any
]
any
{
map
[
any
]
any
{
"name"
:
"London"
,
"population"
:
1000000
,
},
map
[
any
]
any
{
"name"
:
"Paris"
,
"population"
:
2000000
,
},
},
}
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
e
:=
New
(
mapData
)
stringWriter
:=
&
strings
.
Builder
{}
e
.
ProcessHtml
(
stringWriter
,
strings
.
NewReader
(
`<div><div data-repeat="city path:cities"><p data-replace="path:city.name"></p></div></div>`
))
}
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment