Skip to content

Commit

Permalink
Merge pull request #1155 from daniel-pieper-personio/richtext-list
Browse files Browse the repository at this point in the history
Add support for Rich Text Lists
  • Loading branch information
parsley42 committed Feb 9, 2024
2 parents 86cd1bd + bc6223b commit f6b09b8
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 2 deletions.
81 changes: 80 additions & 1 deletion block_rich_text.go
Expand Up @@ -40,6 +40,9 @@ func (e *RichTextBlock) UnmarshalJSON(b []byte) error {
switch s.Type {
case RTESection:
elem = &RichTextSection{}
case RTEList:
elem = &RichTextList{}

default:
elems = append(elems, &RichTextUnknown{
Type: s.Type,
Expand Down Expand Up @@ -92,12 +95,88 @@ func (u RichTextUnknown) RichTextElementType() RichTextElementType {
return u.Type
}

type RichTextListElementType string

const (
RTEListOrdered RichTextListElementType = "ordered"
RTEListBullet RichTextListElementType = "bullet"
)

type RichTextList struct {
Type RichTextElementType `json:"type"`
Elements []RichTextElement `json:"elements"`
Style RichTextListElementType `json:"style"`
Indent int `json:"indent"`
}

// NewRichTextList returns a new rich text list element.
func NewRichTextList(style RichTextListElementType, indent int, elements ...RichTextElement) *RichTextList {
return &RichTextList{
Type: RTEList,
Elements: elements,
Style: style,
Indent: indent,
}
}

// ElementType returns the type of the Element
func (s RichTextList) RichTextElementType() RichTextElementType {
return s.Type
}

func (e *RichTextList) UnmarshalJSON(b []byte) error {
var raw struct {
RawElements []json.RawMessage `json:"elements"`
Style RichTextListElementType `json:"style"`
Indent int `json:"indent"`
}
if string(b) == "{}" {
return nil
}
if err := json.Unmarshal(b, &raw); err != nil {
return err
}
elems := make([]RichTextElement, 0, len(raw.RawElements))
for _, r := range raw.RawElements {
var s struct {
Type RichTextElementType `json:"type"`
}
if err := json.Unmarshal(r, &s); err != nil {
return err
}
var elem RichTextElement
switch s.Type {
case RTESection:
elem = &RichTextSection{}
case RTEList:
elem = &RichTextList{}
default:
elems = append(elems, &RichTextUnknown{
Type: s.Type,
Raw: string(r),
})
continue
}
if err := json.Unmarshal(r, elem); err != nil {
return err
}
elems = append(elems, elem)
}
*e = RichTextList{
Type: RTEList,
Elements: elems,
Style: raw.Style,
Indent: raw.Indent,
}
return nil
}

type RichTextSection struct {
Type RichTextElementType `json:"type"`
Elements []RichTextSectionElement `json:"elements"`
}

// ElementType returns the type of the Element
// RichTextElementType returns the type of the Element
func (s RichTextSection) RichTextElementType() RichTextElementType {
return s.Type
}
Expand Down
84 changes: 83 additions & 1 deletion block_rich_text_test.go
Expand Up @@ -36,11 +36,12 @@ func TestRichTextBlock_UnmarshalJSON(t *testing.T) {
err error
}{
{
[]byte(`{"elements":[{"type":"rich_text_unknown"},{"type":"rich_text_section"}]}`),
[]byte(`{"elements":[{"type":"rich_text_unknown"},{"type":"rich_text_section"},{"type":"rich_text_list"}]}`),
RichTextBlock{
Elements: []RichTextElement{
&RichTextUnknown{Type: RTEUnknown, Raw: `{"type":"rich_text_unknown"}`},
&RichTextSection{Type: RTESection, Elements: []RichTextSectionElement{}},
&RichTextList{Type: RTEList, Elements: []RichTextElement{}},
},
},
nil,
Expand Down Expand Up @@ -117,3 +118,84 @@ func TestRichTextSection_UnmarshalJSON(t *testing.T) {
}
}
}

func TestRichTextList_UnmarshalJSON(t *testing.T) {
cases := []struct {
raw []byte
expected RichTextList
err error
}{
{
[]byte(`{"style":"ordered","elements":[{"type":"rich_text_unknown","value":10},{"type":"rich_text_section","elements":[{"type":"text","text":"hi"}]}]}`),
RichTextList{
Type: RTEList,
Style: RTEListOrdered,
Elements: []RichTextElement{
&RichTextUnknown{Type: RTEUnknown, Raw: `{"type":"rich_text_unknown","value":10}`},
&RichTextSection{
Type: RTESection,
Elements: []RichTextSectionElement{
&RichTextSectionTextElement{Type: RTSEText, Text: "hi"},
},
},
},
},
nil,
},
{
[]byte(`{"style":"ordered","elements":[{"type":"rich_text_list","style":"bullet","elements":[{"type":"rich_text_section","elements":[{"type":"text","text":"hi"}]}]}]}`),
RichTextList{
Type: RTEList,
Style: RTEListOrdered,
Elements: []RichTextElement{
&RichTextList{
Type: RTEList,
Style: RTEListBullet,
Elements: []RichTextElement{
&RichTextSection{
Type: RTESection,
Elements: []RichTextSectionElement{
&RichTextSectionTextElement{Type: RTSEText, Text: "hi"},
},
},
},
},
},
},
nil,
},
{
[]byte(`{"type": "rich_text_list","elements":[]}`),
RichTextList{
Type: RTEList,
Elements: []RichTextElement{},
},
nil,
},
{
[]byte(`{"type": "rich_text_list","elements":[],"indent":2}`),
RichTextList{
Type: RTEList,
Indent: 2,
Elements: []RichTextElement{},
},
nil,
},
}
for _, tc := range cases {
var actual RichTextList
err := json.Unmarshal(tc.raw, &actual)
if err != nil {
if tc.err == nil {
t.Errorf("unexpected error: %s", err)
}
t.Errorf("expected error is %s, but got %s", tc.err, err)
}
if tc.err != nil {
t.Errorf("expected to raise an error %s", tc.err)
}
if diff := deep.Equal(actual, tc.expected); diff != nil {
t.Errorf("actual value does not match expected one\n%s", diff)
}
}
}

0 comments on commit f6b09b8

Please sign in to comment.