Skip to content

Commit 96f1798

Browse files
adds support for infobox in Go
1 parent 5fefcd2 commit 96f1798

File tree

4 files changed

+322
-3
lines changed

4 files changed

+322
-3
lines changed

content_tree.go

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ const (
8282
TimelineEventType = "timeline-event"
8383
TimelineEventChildType = "timeline-event-child"
8484

85+
CardType = "card"
86+
CardChildType = "card-child"
87+
InfoBoxType = "info-box"
88+
8589
DefinitionType = "definition"
8690
InNumbersType = "in-numbers"
8791

@@ -406,6 +410,7 @@ type BodyBlock struct {
406410
*Timeline
407411
*InNumbers
408412
*ImagePair
413+
*InfoBox
409414
}
410415

411416
func (n *BodyBlock) GetType() string {
@@ -482,6 +487,9 @@ func (n *BodyBlock) GetEmbedded() Node {
482487
if n.ImagePair != nil {
483488
return n.ImagePair
484489
}
490+
if n.InfoBox != nil {
491+
return n.InfoBox
492+
}
485493
return nil
486494
}
487495

@@ -555,6 +563,9 @@ func (n *BodyBlock) GetChildren() []Node {
555563
if n.ImagePair != nil {
556564
return n.ImagePair.GetChildren()
557565
}
566+
if n.InfoBox != nil {
567+
return n.InfoBox.GetChildren()
568+
}
558569
return nil
559570
}
560571

@@ -705,6 +716,12 @@ func (n *BodyBlock) UnmarshalJSON(data []byte) error {
705716
return err
706717
}
707718
n.ImagePair = &v
719+
case InfoBoxType:
720+
var v InfoBox
721+
if err := json.Unmarshal(data, &v); err != nil {
722+
return err
723+
}
724+
n.InfoBox = &v
708725
default:
709726
return fmt.Errorf("failed to unmarshal BodyBlock from %s: %w", data, ErrUnmarshalInvalidNode)
710727
}
@@ -759,6 +776,8 @@ func (n *BodyBlock) MarshalJSON() ([]byte, error) {
759776
return json.Marshal(n.InNumbers)
760777
case n.ImagePair != nil:
761778
return json.Marshal(n.ImagePair)
779+
case n.InfoBox != nil:
780+
return json.Marshal(n.InfoBox)
762781
default:
763782
return []byte(`{}`), nil
764783
}
@@ -813,6 +832,8 @@ func makeBodyBlock(n Node) (*BodyBlock, error) {
813832
return &BodyBlock{InNumbers: n.(*InNumbers)}, nil
814833
case ImagePairType:
815834
return &BodyBlock{ImagePair: n.(*ImagePair)}, nil
835+
case InfoBoxType:
836+
return &BodyBlock{InfoBox: n.(*InfoBox)}, nil
816837
default:
817838
return nil, ErrInvalidChildType
818839
}
@@ -2883,3 +2904,203 @@ func (ip *ImagePair) AppendChild(child Node) error {
28832904
ip.Children = append(ip.Children, child.(*ImageSet))
28842905
return nil
28852906
}
2907+
2908+
type Card struct {
2909+
Type string `json:"type"`
2910+
Title string `json:"title,omitempty"`
2911+
Children []*CardChild `json:"children"`
2912+
}
2913+
2914+
func (n *Card) GetType() string {
2915+
return n.Type
2916+
}
2917+
2918+
func (n *Card) GetEmbedded() Node {
2919+
return nil
2920+
}
2921+
2922+
func (n *Card) GetChildren() []Node {
2923+
result := make([]Node, len(n.Children))
2924+
for i, v := range n.Children {
2925+
result[i] = v
2926+
}
2927+
return result
2928+
}
2929+
2930+
func (n *Card) AppendChild(child Node) error {
2931+
c, err := makeCardChild(child)
2932+
if err != nil {
2933+
return err
2934+
}
2935+
n.Children = append(n.Children, c)
2936+
return nil
2937+
}
2938+
2939+
type CardChild struct {
2940+
*Paragraph
2941+
*List
2942+
*Blockquote
2943+
*ThematicBreak
2944+
*Text
2945+
*ImageSet
2946+
}
2947+
2948+
func (n *CardChild) GetType() string {
2949+
return CardChildType
2950+
}
2951+
2952+
func (n *CardChild) GetEmbedded() Node {
2953+
switch {
2954+
case n.Paragraph != nil:
2955+
return n.Paragraph
2956+
case n.List != nil:
2957+
return n.List
2958+
case n.Blockquote != nil:
2959+
return n.Blockquote
2960+
case n.ThematicBreak != nil:
2961+
return n.ThematicBreak
2962+
case n.Text != nil:
2963+
return n.Text
2964+
case n.ImageSet != nil:
2965+
return n.ImageSet
2966+
default:
2967+
return nil
2968+
}
2969+
}
2970+
2971+
func (n *CardChild) GetChildren() []Node {
2972+
switch {
2973+
case n.Paragraph != nil:
2974+
return n.Paragraph.GetChildren()
2975+
case n.List != nil:
2976+
return n.List.GetChildren()
2977+
case n.Blockquote != nil:
2978+
return n.Blockquote.GetChildren()
2979+
case n.ThematicBreak != nil:
2980+
return n.ThematicBreak.GetChildren()
2981+
case n.Text != nil:
2982+
return n.Text.GetChildren()
2983+
case n.ImageSet != nil:
2984+
return n.ImageSet.GetChildren()
2985+
default:
2986+
return nil
2987+
}
2988+
}
2989+
2990+
func (n *CardChild) AppendChild(_ Node) error { return ErrCannotHaveChildren }
2991+
2992+
func (n *CardChild) UnmarshalJSON(data []byte) error {
2993+
var tn typedNode
2994+
if err := json.Unmarshal(data, &tn); err != nil {
2995+
return err
2996+
}
2997+
switch tn.Type {
2998+
case ParagraphType:
2999+
var v Paragraph
3000+
if err := json.Unmarshal(data, &v); err != nil {
3001+
return err
3002+
}
3003+
n.Paragraph = &v
3004+
case ListType:
3005+
var v List
3006+
if err := json.Unmarshal(data, &v); err != nil {
3007+
return err
3008+
}
3009+
n.List = &v
3010+
case BlockquoteType:
3011+
var v Blockquote
3012+
if err := json.Unmarshal(data, &v); err != nil {
3013+
return err
3014+
}
3015+
n.Blockquote = &v
3016+
case ThematicBreakType:
3017+
var v ThematicBreak
3018+
if err := json.Unmarshal(data, &v); err != nil {
3019+
return err
3020+
}
3021+
n.ThematicBreak = &v
3022+
case TextType:
3023+
var v Text
3024+
if err := json.Unmarshal(data, &v); err != nil {
3025+
return err
3026+
}
3027+
n.Text = &v
3028+
case ImageSetType:
3029+
var v ImageSet
3030+
if err := json.Unmarshal(data, &v); err != nil {
3031+
return err
3032+
}
3033+
n.ImageSet = &v
3034+
default:
3035+
return fmt.Errorf("failed to unmarshal CardChild from %s: %w", data, ErrUnmarshalInvalidNode)
3036+
}
3037+
return nil
3038+
}
3039+
3040+
func (n *CardChild) MarshalJSON() ([]byte, error) {
3041+
switch {
3042+
case n.Paragraph != nil:
3043+
return json.Marshal(n.Paragraph)
3044+
case n.List != nil:
3045+
return json.Marshal(n.List)
3046+
case n.Blockquote != nil:
3047+
return json.Marshal(n.Blockquote)
3048+
case n.ThematicBreak != nil:
3049+
return json.Marshal(n.ThematicBreak)
3050+
case n.Text != nil:
3051+
return json.Marshal(n.Text)
3052+
case n.ImageSet != nil:
3053+
return json.Marshal(n.ImageSet)
3054+
default:
3055+
return []byte(`{}`), nil
3056+
}
3057+
}
3058+
3059+
func makeCardChild(n Node) (*CardChild, error) {
3060+
switch n.GetType() {
3061+
case ParagraphType:
3062+
return &CardChild{Paragraph: n.(*Paragraph)}, nil
3063+
case ListType:
3064+
return &CardChild{List: n.(*List)}, nil
3065+
case BlockquoteType:
3066+
return &CardChild{Blockquote: n.(*Blockquote)}, nil
3067+
case ThematicBreakType:
3068+
return &CardChild{ThematicBreak: n.(*ThematicBreak)}, nil
3069+
case TextType:
3070+
return &CardChild{Text: n.(*Text)}, nil
3071+
case ImageSetType:
3072+
return &CardChild{ImageSet: n.(*ImageSet)}, nil
3073+
default:
3074+
return nil, ErrInvalidChildType
3075+
}
3076+
}
3077+
3078+
type InfoBox struct {
3079+
Type string `json:"type"`
3080+
LayoutWidth string `json:"layoutWidth"`
3081+
Children []*Card `json:"children"`
3082+
}
3083+
3084+
func (n *InfoBox) GetType() string {
3085+
return n.Type
3086+
}
3087+
3088+
func (n *InfoBox) GetEmbedded() Node {
3089+
return nil
3090+
}
3091+
3092+
func (n *InfoBox) GetChildren() []Node {
3093+
result := make([]Node, len(n.Children))
3094+
for i, v := range n.Children {
3095+
result[i] = v
3096+
}
3097+
return result
3098+
}
3099+
3100+
func (n *InfoBox) AppendChild(child Node) error {
3101+
if child.GetType() != CardType {
3102+
return ErrInvalidChildType
3103+
}
3104+
n.Children = append(n.Children, child.(*Card))
3105+
return nil
3106+
}

libraries/from-bodyxml/go/html_transformers.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,24 @@ var defaultTransformers = map[string]transformer{
336336
}
337337
},
338338
"div": func(div *etree.Element) contenttree.Node {
339-
dataType := attr(div, "data-type")
340-
if dataType == "in-numbers-definition" {
339+
switch attr(div, "data-type") {
340+
case "in-numbers-definition":
341341
return newLiftChildrenNode()
342+
case "card":
343+
{
344+
title := ""
345+
if h4Element := findChild(div, "h4"); h4Element != nil {
346+
title = textContent(h4Element)
347+
div.RemoveChild(h4Element)
348+
}
349+
return &contenttree.Card{
350+
Type: contenttree.CardType,
351+
Title: title,
352+
Children: []*contenttree.CardChild{},
353+
}
354+
}
342355
}
356+
343357
switch attr(div, "class") {
344358
case "n-content-layout":
345359
return &contenttree.Layout{
@@ -425,7 +439,15 @@ var defaultTransformers = map[string]transformer{
425439
Children: []*contenttree.ImageSet{},
426440
}
427441
}
428-
442+
case "info-box":
443+
{
444+
lw := attr(section, "data-layout-width")
445+
return &contenttree.InfoBox{
446+
Type: contenttree.InfoBoxType,
447+
LayoutWidth: lw,
448+
Children: []*contenttree.Card{},
449+
}
450+
}
429451
}
430452
return newUnknownNode("", section)
431453
},
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<body><section data-type="info-box" data-layout-width="inset-left"><div data-type="card"><h4>Title</h4><p>paragraph</p><ul><li><p>para inside list</p></li></ul><blockquote><p>para inside blockquote</p></blockquote>text<hr></hr><content data-embedded="true" type="http://www.ft.com/ontology/content/ImageSet" id="23925844-4d8d-11ea-0bc6-d44b54b3bebc"></content></div></section></body>
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
"type":"root",
3+
"body":{
4+
"type":"body",
5+
"children":[
6+
{
7+
"type":"info-box",
8+
"layoutWidth":"inset-left",
9+
"children":[
10+
{
11+
"type":"card",
12+
"title":"Title",
13+
"children":[
14+
{
15+
"type":"paragraph",
16+
"children":[
17+
{
18+
"type":"text",
19+
"value":"paragraph"
20+
}
21+
]
22+
},
23+
{
24+
"type":"list",
25+
"children":[
26+
{
27+
"type":"list-item",
28+
"children":[
29+
{
30+
"type":"paragraph",
31+
"children":[
32+
{
33+
"type":"text",
34+
"value":"para inside list"
35+
}
36+
]
37+
}
38+
]
39+
}
40+
],
41+
"ordered":false
42+
},
43+
{
44+
"type":"blockquote",
45+
"children":[
46+
{
47+
"type":"paragraph",
48+
"children":[
49+
{
50+
"type":"text",
51+
"value":"para inside blockquote"
52+
}
53+
]
54+
}
55+
]
56+
},
57+
{
58+
"type":"text",
59+
"value":"text"
60+
},
61+
{
62+
"type":"thematic-break"
63+
},
64+
{
65+
"type":"image-set",
66+
"id":"23925844-4d8d-11ea-0bc6-d44b54b3bebc"
67+
}
68+
]
69+
}
70+
]
71+
}
72+
],
73+
"version":1
74+
}
75+
}

0 commit comments

Comments
 (0)