diff --git a/apidrawing.go b/apidrawing.go index e42a64f..c42d4d1 100644 --- a/apidrawing.go +++ b/apidrawing.go @@ -99,9 +99,11 @@ func (p *Paragraph) AddInlineDrawing(pic []byte) (*Run, error) { }, }, } + c := make([]interface{}, 1, 64) + c[0] = d run := &Run{ - Drawing: d, RunProperties: &RunProperties{}, + Children: c, } p.Children = append(p.Children, run) return run, nil @@ -207,9 +209,11 @@ func (p *Paragraph) AddAnchorDrawing(pic []byte) (*Run, error) { }, }, } + c := make([]interface{}, 1, 64) + c[0] = d run := &Run{ - Drawing: d, RunProperties: &RunProperties{}, + Children: c, } p.Children = append(p.Children, run) return run, nil diff --git a/apipara.go b/apipara.go index 786e722..dc64074 100644 --- a/apipara.go +++ b/apipara.go @@ -24,8 +24,6 @@ import "unsafe" // AddParagraph adds a new paragraph func (f *Docx) AddParagraph() *Paragraph { - f.Document.Body.mu.Lock() - defer f.Document.Body.mu.Unlock() f.Document.Body.Items = append(f.Document.Body.Items, Paragraph{ Children: make([]interface{}, 0, 64), file: f, @@ -38,9 +36,6 @@ func (f *Docx) AddParagraph() *Paragraph { // AddParagraph adds a new paragraph func (c *WTableCell) AddParagraph() *Paragraph { - c.mu.Lock() - defer c.mu.Unlock() - c.Paragraphs = append(c.Paragraphs, Paragraph{ Children: make([]interface{}, 0, 64), file: c.file, diff --git a/apirun.go b/apirun.go index 2d20aed..3a2f0f2 100644 --- a/apirun.go +++ b/apirun.go @@ -20,8 +20,6 @@ package docxlib -import "encoding/xml" - // Color allows to set run color func (r *Run) Color(color string) *Run { r.RunProperties.Color = &Color{ @@ -42,16 +40,6 @@ func (r *Run) Size(size string) *Run { // AddTab add a tab in front of the run func (r *Run) AddTab() *Run { - r.FrontTab = append(r.FrontTab, struct { - XMLName xml.Name "xml:\"w:tab,omitempty\"" - }{}) - return r -} - -// AppendTab add a tab after the run -func (r *Run) AppendTab() *Run { - r.RearTab = append(r.RearTab, struct { - XMLName xml.Name "xml:\"w:tab,omitempty\"" - }{}) + r.Children = append(r.Children, &WTab{}) return r } diff --git a/apitable.go b/apitable.go index 5ccbd3b..384e9b7 100644 --- a/apitable.go +++ b/apitable.go @@ -42,8 +42,6 @@ func (f *Docx) AddTable(row int, col int) *WTable { TableCells: cells, } } - f.Document.Body.mu.Lock() - defer f.Document.Body.mu.Unlock() f.Document.Body.Items = append(f.Document.Body.Items, WTable{ TableProperties: &WTableProperties{ Width: &WTableWidth{Type: "auto"}, @@ -101,8 +99,6 @@ func (f *Docx) AddTableTwips(rowHeights []int64, colWidths []int64) *WTable { } } } - f.Document.Body.mu.Lock() - defer f.Document.Body.mu.Unlock() f.Document.Body.Items = append(f.Document.Body.Items, WTable{ TableProperties: &WTableProperties{ Width: &WTableWidth{Type: "auto"}, diff --git a/apitext.go b/apitext.go index 29075b0..cbdb6c6 100644 --- a/apitext.go +++ b/apitext.go @@ -20,17 +20,20 @@ package docxlib -import "encoding/xml" +import "strings" // AddTab adds tab to para func (p *Paragraph) AddTab() *Run { + c := make([]interface{}, 1, 64) + c[0] = &WTab{} + run := &Run{ RunProperties: &RunProperties{}, - FrontTab: []struct { - XMLName xml.Name "xml:\"w:tab,omitempty\"" - }{{}}, + Children: c, } + p.Children = append(p.Children, run) + return run } @@ -40,13 +43,22 @@ func (p *Paragraph) AddText(text string) *Run { return p.AddTab() } - t := &Text{ - Text: text, + c := make([]interface{}, 0, 64) + + for i, s := range strings.Split(text, "\t") { + if i > 0 { + c = append(c, &WTab{}) + } + if s != "" { + c = append(c, &Text{ + Text: s, + }) + } } run := &Run{ - Text: t, RunProperties: &RunProperties{}, + Children: c, } p.Children = append(p.Children, run) diff --git a/cmd/main/main.go b/cmd/main/main.go index 9495cc3..07793fc 100644 --- a/cmd/main/main.go +++ b/cmd/main/main.go @@ -46,10 +46,10 @@ func main() { if err != nil { panic(err) } - r.Drawing.Anchor.Size(r.Drawing.Anchor.Extent.CX/4, r.Drawing.Anchor.Extent.CY/4) - r.Drawing.Anchor.BehindDoc = 1 - r.Drawing.Anchor.PositionH.PosOffset = r.Drawing.Anchor.Extent.CX - r.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.AlphaModFix = &docxlib.AAlphaModFix{Amount: 50000} + r.Children[0].(*docxlib.Drawing).Anchor.Size(r.Children[0].(*docxlib.Drawing).Anchor.Extent.CX/4, r.Children[0].(*docxlib.Drawing).Anchor.Extent.CY/4) + r.Children[0].(*docxlib.Drawing).Anchor.BehindDoc = 1 + r.Children[0].(*docxlib.Drawing).Anchor.PositionH.PosOffset = r.Children[0].(*docxlib.Drawing).Anchor.Extent.CX + r.Children[0].(*docxlib.Drawing).Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.AlphaModFix = &docxlib.AAlphaModFix{Amount: 50000} // add text para1.AddText("test") para1.AddText("test font size").Size("44") @@ -70,13 +70,13 @@ func main() { if err != nil { panic(err) } - r.Drawing.Inline.Size(r.Drawing.Inline.Extent.CX*4/5, r.Drawing.Inline.Extent.CY*4/5) + r.Children[0].(*docxlib.Drawing).Inline.Size(r.Children[0].(*docxlib.Drawing).Inline.Extent.CX*4/5, r.Children[0].(*docxlib.Drawing).Inline.Extent.CY*4/5) para4.AddTab().AddTab() r, err = para4.AddInlineDrawingFrom("testdata/fumiama2x.webp") if err != nil { panic(err) } - r.Drawing.Inline.Size(r.Drawing.Inline.Extent.CX*4/5, r.Drawing.Inline.Extent.CY*4/5) + r.Children[0].(*docxlib.Drawing).Inline.Size(r.Children[0].(*docxlib.Drawing).Inline.Extent.CX*4/5, r.Children[0].(*docxlib.Drawing).Inline.Extent.CY*4/5) para5 := w.AddParagraph().Justification("center") // add text diff --git a/link.go b/link.go index b8200e4..db50b53 100644 --- a/link.go +++ b/link.go @@ -66,8 +66,6 @@ func (f *Docx) addImageRelation(m Media) string { // ReferTarget gets the target for a reference func (f *Docx) ReferTarget(id string) (string, error) { - f.docRelation.mu.RLock() - defer f.docRelation.mu.RUnlock() for _, a := range f.docRelation.Relationship { if a.ID == id { return a.Target, nil @@ -78,8 +76,6 @@ func (f *Docx) ReferTarget(id string) (string, error) { // ReferID gets the rId from target func (f *Docx) ReferID(target string) (string, error) { - f.docRelation.mu.RLock() - defer f.docRelation.mu.RUnlock() for _, a := range f.docRelation.Relationship { if a.Target == target { return a.ID, nil diff --git a/structdoc.go b/structdoc.go index 650eedc..9c91676 100644 --- a/structdoc.go +++ b/structdoc.go @@ -24,7 +24,6 @@ import ( "encoding/xml" "io" "strings" - "sync" ) //nolint:revive,stylecheck @@ -48,7 +47,6 @@ func getAtt(atts []xml.Attr, name string) string { // Body type Body struct { - mu sync.Mutex Items []interface{} file *Docx @@ -74,9 +72,7 @@ func (b *Body) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { return err } value.file = b.file - b.mu.Lock() b.Items = append(b.Items, value) - b.mu.Unlock() case "tbl": var value WTable err = d.DecodeElement(&value, &tt) @@ -84,9 +80,7 @@ func (b *Body) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { return err } value.file = b.file - b.mu.Lock() b.Items = append(b.Items, value) - b.mu.Unlock() default: err = d.Skip() // skip unsupported tags if err != nil { diff --git a/structdrawing_test.go b/structdrawing_test.go index 0826a1e..c4d32dc 100644 --- a/structdrawing_test.go +++ b/structdrawing_test.go @@ -38,12 +38,12 @@ func TestDrawingStructure(t *testing.T) { if err != nil { t.Fatal(err) } - r.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.AlphaModFix = &AAlphaModFix{Amount: 50000} - r.Drawing.Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties.CNvPicPr.Locks = &APicLocks{NoChangeAspect: 1} - r.Drawing.Anchor.Graphic.GraphicData.Pic.SpPr.Xfrm.Rot = 50000 + r.Children[0].(*Drawing).Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.AlphaModFix = &AAlphaModFix{Amount: 50000} + r.Children[0].(*Drawing).Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties.CNvPicPr.Locks = &APicLocks{NoChangeAspect: 1} + r.Children[0].(*Drawing).Anchor.Graphic.GraphicData.Pic.SpPr.Xfrm.Rot = 50000 para2 := w.AddParagraph().Justification("center") para2.AddInlineDrawingFrom("testdata/fumiama.JPG") - para2.AddTab().AddTab().AppendTab().AppendTab() + para2.AddTab().AddTab().AddTab().AddTab() para2.AddInlineDrawingFrom("testdata/fumiama2x.webp") para3 := w.AddParagraph() diff --git a/structpara.go b/structpara.go index 29d0ecd..6d35e63 100644 --- a/structpara.go +++ b/structpara.go @@ -93,54 +93,58 @@ func (p *Paragraph) String() string { } sb.WriteByte(')') case *Run: - switch { - case o.Text != nil: - sb.WriteString(o.Text.Text) - case o.Drawing != nil: - if o.Drawing.Inline != nil && o.Drawing.Inline.Graphic != nil && o.Drawing.Inline.Graphic.GraphicData != nil && o.Drawing.Inline.Graphic.GraphicData.Pic != nil { - sb.WriteString("![inlnim ") - switch { - case o.Drawing.Inline.DocPr != nil: - sb.WriteString(o.Drawing.Inline.DocPr.Name) - case o.Drawing.Inline.Graphic.GraphicData.Pic.NonVisualPicProperties != nil: - sb.WriteString(o.Drawing.Inline.Graphic.GraphicData.Pic.NonVisualPicProperties.NonVisualDrawingProperties.Name) - default: - sb.WriteString(o.Drawing.Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) - } - sb.WriteString("](") - if o.Drawing.Inline.Graphic.GraphicData.Pic.BlipFill != nil { - tgt, err := p.file.ReferTarget(o.Drawing.Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) - if err != nil { - sb.WriteString(err.Error()) - } else { - h := md5.Sum(p.file.Media(tgt[6:]).Data) - sb.WriteString(hex.EncodeToString(h[:])) + for _, c := range o.Children { + switch x := c.(type) { + case *Text: + sb.WriteString(x.Text) + case *WTab: + sb.WriteByte('\t') + case *Drawing: + if x.Inline != nil && x.Inline.Graphic != nil && x.Inline.Graphic.GraphicData != nil && x.Inline.Graphic.GraphicData.Pic != nil { + sb.WriteString("![inlnim ") + switch { + case x.Inline.DocPr != nil: + sb.WriteString(x.Inline.DocPr.Name) + case x.Inline.Graphic.GraphicData.Pic.NonVisualPicProperties != nil: + sb.WriteString(x.Inline.Graphic.GraphicData.Pic.NonVisualPicProperties.NonVisualDrawingProperties.Name) + default: + sb.WriteString(x.Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) } - } - sb.WriteByte(')') - continue - } - if o.Drawing.Anchor != nil && o.Drawing.Anchor.Graphic != nil && o.Drawing.Anchor.Graphic.GraphicData != nil && o.Drawing.Anchor.Graphic.GraphicData.Pic != nil { - sb.WriteString("![anchim ") - switch { - case o.Drawing.Anchor.DocPr != nil: - sb.WriteString(o.Drawing.Anchor.DocPr.Name) - case o.Drawing.Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties != nil: - sb.WriteString(o.Drawing.Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties.NonVisualDrawingProperties.Name) - default: - sb.WriteString(o.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) - } - sb.WriteString("](") - if o.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill != nil { - tgt, err := p.file.ReferTarget(o.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) - if err != nil { - sb.WriteString(err.Error()) - } else { - h := md5.Sum(p.file.Media(tgt[6:]).Data) - sb.WriteString(hex.EncodeToString(h[:])) + sb.WriteString("](") + if x.Inline.Graphic.GraphicData.Pic.BlipFill != nil { + tgt, err := p.file.ReferTarget(x.Inline.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) + if err != nil { + sb.WriteString(err.Error()) + } else { + h := md5.Sum(p.file.Media(tgt[6:]).Data) + sb.WriteString(hex.EncodeToString(h[:])) + } } + sb.WriteByte(')') + continue + } + if x.Anchor != nil && x.Anchor.Graphic != nil && x.Anchor.Graphic.GraphicData != nil && x.Anchor.Graphic.GraphicData.Pic != nil { + sb.WriteString("![anchim ") + switch { + case x.Anchor.DocPr != nil: + sb.WriteString(x.Anchor.DocPr.Name) + case x.Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties != nil: + sb.WriteString(x.Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties.NonVisualDrawingProperties.Name) + default: + sb.WriteString(x.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) + } + sb.WriteString("](") + if x.Anchor.Graphic.GraphicData.Pic.BlipFill != nil { + tgt, err := p.file.ReferTarget(x.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.Embed) + if err != nil { + sb.WriteString(err.Error()) + } else { + h := md5.Sum(p.file.Media(tgt[6:]).Data) + sb.WriteString(hex.EncodeToString(h[:])) + } + } + sb.WriteByte(')') } - sb.WriteByte(')') } } case *RunProperties: diff --git a/structrel.go b/structrel.go index 26f9a4c..da3dc09 100644 --- a/structrel.go +++ b/structrel.go @@ -20,10 +20,6 @@ package docxlib -import ( - "sync" -) - //nolint:revive,stylecheck const ( XMLNS_REL = `http://schemas.openxmlformats.org/package/2006/relationships` @@ -35,7 +31,6 @@ const ( // Relationships ... type Relationships struct { - mu sync.RWMutex Xmlns string `xml:"xmlns,attr"` Relationship []Relationship } diff --git a/structrun.go b/structrun.go index 0cb4478..8273828 100644 --- a/structrun.go +++ b/structrun.go @@ -29,17 +29,13 @@ import ( // 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"` + XMLName xml.Name `xml:"w:r,omitempty"` + RunProperties *RunProperties `xml:"w:rPr,omitempty"` - FrontTab []struct { //TODO: replace with variable []RunChild - XMLName xml.Name `xml:"w:tab,omitempty"` - } + InstrText string `xml:"w:instrText,omitempty"` - Text *Text - Drawing *Drawing - RearTab []struct { - XMLName xml.Name `xml:"w:tab,omitempty"` - } + + Children []interface{} } // UnmarshalXML ... @@ -53,6 +49,8 @@ func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { return err } + var child interface{} + if tt, ok := t.(xml.StartElement); ok { switch tt.Name.Local { case "rPr": @@ -62,6 +60,7 @@ func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { return err } r.RunProperties = &value + continue case "instrText": var value string err = d.DecodeElement(&value, &tt) @@ -69,30 +68,23 @@ func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { 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 } - r.Text = &value + child = &value case "drawing": var value Drawing err = d.DecodeElement(&value, &tt) if err != nil && !strings.HasPrefix(err.Error(), "expected") { return err } - r.Drawing = &value + child = &value case "tab": - if r.InstrText == "" && r.Text == nil && r.Drawing == nil { - r.FrontTab = append(r.FrontTab, struct { - XMLName xml.Name "xml:\"w:tab,omitempty\"" - }{}) - } else { - r.RearTab = append(r.RearTab, struct { - XMLName xml.Name "xml:\"w:tab,omitempty\"" - }{}) - } + child = &WTab{} default: err = d.Skip() // skip unsupported tags if err != nil { @@ -100,6 +92,7 @@ func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { } continue } + r.Children = append(r.Children, child) } } diff --git a/structtable.go b/structtable.go index ea37179..431d452 100644 --- a/structtable.go +++ b/structtable.go @@ -25,7 +25,6 @@ import ( "io" "strconv" "strings" - "sync" ) // WTable represents a table within a Word document. @@ -502,8 +501,6 @@ type WTableRowHeight struct { // WTableCell represents a cell within a table. type WTableCell struct { - mu sync.Mutex - XMLName xml.Name `xml:"w:tc,omitempty"` TableCellProperties *WTableCellProperties Paragraphs []Paragraph `xml:"w:p,omitempty"` @@ -532,9 +529,7 @@ func (c *WTableCell) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error } if len(value.Children) > 0 { value.file = c.file - c.mu.Lock() c.Paragraphs = append(c.Paragraphs, value) - c.mu.Unlock() } case "tcPr": var value WTableCellProperties diff --git a/structtable_test.go b/structtable_test.go index 854c012..cc6f9d7 100644 --- a/structtable_test.go +++ b/structtable_test.go @@ -41,9 +41,9 @@ func TestTableStructure(t *testing.T) { if err != nil { t.Fatal(err) } - r.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.AlphaModFix = &AAlphaModFix{Amount: 50000} - r.Drawing.Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties.CNvPicPr.Locks = &APicLocks{NoChangeAspect: 1} - r.Drawing.Anchor.Graphic.GraphicData.Pic.SpPr.Xfrm.Rot = 50000 + r.Children[0].(*Drawing).Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.AlphaModFix = &AAlphaModFix{Amount: 50000} + r.Children[0].(*Drawing).Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties.CNvPicPr.Locks = &APicLocks{NoChangeAspect: 1} + r.Children[0].(*Drawing).Anchor.Graphic.GraphicData.Pic.SpPr.Xfrm.Rot = 50000 para3 := tab1.TableRows[0].TableCells[0].AddParagraph() para3.AddText("first cell")