Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Rich Text Lists #1155

Merged
merged 4 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 80 additions & 1 deletion block_rich_text.go
Original file line number Diff line number Diff line change
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"`
daniel-pieper-personio marked this conversation as resolved.
Show resolved Hide resolved
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"`
daniel-pieper-personio marked this conversation as resolved.
Show resolved Hide resolved
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,
daniel-pieper-personio marked this conversation as resolved.
Show resolved Hide resolved
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
Original file line number Diff line number Diff line change
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,
},
daniel-pieper-personio marked this conversation as resolved.
Show resolved Hide resolved
{
[]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)
}
}
}
Loading