/* Copyright (c) 2020 gingfrederik Copyright (c) 2021 Gonzalo Fernandez-Victorio Copyright (c) 2021 Basement Crowd Ltd (https://www.basementcrowd.com) Copyright (c) 2023 Fumiama Minamoto (源文雨) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package docxlib import ( "encoding/xml" "io" "strings" ) // Run is part of a paragraph that has its own style. It could be // a piece of text in bold, or a link type Run struct { XMLName xml.Name `xml:"w:r,omitempty"` RunProperties *RunProperties `xml:"w:rPr,omitempty"` InstrText string `xml:"w:instrText,omitempty"` Children []interface{} } // UnmarshalXML ... func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { for { t, err := d.Token() if err == io.EOF { break } if err != nil { return err } var child interface{} if tt, ok := t.(xml.StartElement); ok { switch tt.Name.Local { case "rPr": var value RunProperties err = d.DecodeElement(&value, &tt) if err != nil && !strings.HasPrefix(err.Error(), "expected") { return err } r.RunProperties = &value continue case "instrText": var value string err = d.DecodeElement(&value, &tt) if err != nil && !strings.HasPrefix(err.Error(), "expected") { return err } r.InstrText = value continue case "t": var value Text err = d.DecodeElement(&value, &tt) if err != nil && !strings.HasPrefix(err.Error(), "expected") { return err } child = &value case "drawing": var value Drawing err = d.DecodeElement(&value, &tt) if err != nil && !strings.HasPrefix(err.Error(), "expected") { return err } child = &value case "tab": child = &WTab{} default: err = d.Skip() // skip unsupported tags if err != nil { return err } continue } r.Children = append(r.Children, child) } } return nil } // WTab is the literal tab type WTab struct { XMLName xml.Name `xml:"w:tab,omitempty"` } // RunProperties encapsulates visual properties of a run type RunProperties struct { XMLName xml.Name `xml:"w:rPr,omitempty"` Color *Color `xml:"w:color,omitempty"` Size *Size `xml:"w:sz,omitempty"` RunStyle *RunStyle `xml:"w:rStyle,omitempty"` Style *Style `xml:"w:pStyle,omitempty"` } // UnmarshalXML ... func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { for { t, err := d.Token() if err == io.EOF { break } if err != nil { return err } if tt, ok := t.(xml.StartElement); ok { switch tt.Name.Local { case "color": var value Color value.Val = getAtt(tt.Attr, "val") r.Color = &value case "sz": var value Size value.Val = getAtt(tt.Attr, "val") r.Size = &value case "rStyle": var value RunStyle value.Val = getAtt(tt.Attr, "val") r.RunStyle = &value case "pStyle": var value Style value.Val = getAtt(tt.Attr, "val") r.Style = &value default: err = d.Skip() // skip unsupported tags if err != nil { return err } continue } } } return nil } // RunStyle contains styling for a run type RunStyle struct { XMLName xml.Name `xml:"w:rStyle,omitempty"` Val string `xml:"w:val,attr"` } // Style contains styling for a paragraph type Style struct { XMLName xml.Name `xml:"w:pStyle,omitempty"` Val string `xml:"w:val,attr"` } // Color contains the sound of music. :D // I'm kidding. It contains the color type Color struct { XMLName xml.Name `xml:"w:color"` Val string `xml:"w:val,attr"` } // Size contains the font size type Size struct { XMLName xml.Name `xml:"w:sz"` Val string `xml:"w:val,attr"` } // Justification contains the way of the horizonal alignment // // w:jc 属性的取值可以是以下之一: // start:左对齐。 // center:居中对齐。 // end:右对齐。 // both:两端对齐。 // distribute:分散对齐。 type Justification struct { // XMLName xml.Name `xml:"w:jc"` Val string `xml:"w:val,attr"` }