🏷️ Created HTML domain
This commit is contained in:
parent
2428c890e7
commit
8d3ef5c7fc
2
go.mod
2
go.mod
|
@ -1,3 +1,5 @@
|
|||
module source.toby3d.me/toby3d/jf2
|
||||
|
||||
go 1.21.4
|
||||
|
||||
require golang.org/x/net v0.18.0 // indirect
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
|
@ -0,0 +1,71 @@
|
|||
package jf2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
nethtml "golang.org/x/net/html"
|
||||
)
|
||||
|
||||
// HTML is the text/html version of the containing object.
|
||||
type HTML struct {
|
||||
node *nethtml.Node
|
||||
value string
|
||||
}
|
||||
|
||||
func NewHTML(r io.Reader) (*HTML, error) {
|
||||
value, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read r HTML value as string: %w", err)
|
||||
}
|
||||
|
||||
node, err := nethtml.Parse(bytes.NewReader(value))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse r as HTML: %w", err)
|
||||
}
|
||||
|
||||
return &HTML{
|
||||
node: node,
|
||||
value: string(value),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *HTML) UnmarshalJSON(v []byte) error {
|
||||
unquoted, err := strconv.Unquote(string(v))
|
||||
if err != nil {
|
||||
return fmt.Errorf("JF2: HTML: cannot unquote value: %w", err)
|
||||
}
|
||||
|
||||
parsed, err := NewHTML(strings.NewReader(html.UnescapeString(unquoted)))
|
||||
if err != nil {
|
||||
return fmt.Errorf("JF2: HTML: cannot parse value as HTML node: %w", err)
|
||||
}
|
||||
|
||||
*h = *parsed
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h HTML) MarshalJSON() ([]byte, error) {
|
||||
if h.value != "" {
|
||||
return []byte(strconv.Quote(h.value)), nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (h HTML) GoString() string {
|
||||
return "jf2.HTML(" + h.String() + ")"
|
||||
}
|
||||
|
||||
func (h HTML) String() string {
|
||||
if h.value != "" {
|
||||
return h.value
|
||||
}
|
||||
|
||||
return "und"
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package jf2_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"source.toby3d.me/toby3d/jf2"
|
||||
)
|
||||
|
||||
func TestHTML_UnmarshalJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
v := new(struct {
|
||||
Content struct {
|
||||
HTML jf2.HTML `json:"html"`
|
||||
} `json:"content"`
|
||||
})
|
||||
if err := json.Unmarshal([]byte(`{"content":{"html":"<p>Hello World</p>"}}`), v); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expect, err := jf2.NewHTML(strings.NewReader(`<p>Hello World</p>`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if v.Content.HTML.String() != expect.String() {
|
||||
t.Errorf("got '%s', want '%s'", v.Content.HTML, *expect)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTML_MarshalJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
v, err := jf2.NewHTML(strings.NewReader(`<p>Hello World</p>`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
body, err := json.Marshal(struct {
|
||||
Content *jf2.HTML `json:"content"`
|
||||
}{
|
||||
Content: v,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
const expect string = `{"content":"\u003cp\u003eHello World\u003c/p\u003e"}`
|
||||
if actual := string(body); actual != expect {
|
||||
t.Errorf("got '%s', want '%s'", actual, expect)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue