mirror of
https://github.com/fumiama/go-docx.git
synced 2026-06-04 23:30:25 +08:00
优化完善 table canvas
This commit is contained in:
@@ -69,7 +69,7 @@ func (p *Paragraph) AddInlineDrawing(pic []byte) (*Run, error) {
|
|||||||
XMLA: XMLNS_DRAWINGML_MAIN,
|
XMLA: XMLNS_DRAWINGML_MAIN,
|
||||||
GraphicData: &AGraphicData{
|
GraphicData: &AGraphicData{
|
||||||
URI: XMLNS_PICTURE,
|
URI: XMLNS_PICTURE,
|
||||||
Pic: &PICPic{
|
Pic: &Picture{
|
||||||
XMLPIC: XMLNS_DRAWINGML_PICTURE,
|
XMLPIC: XMLNS_DRAWINGML_PICTURE,
|
||||||
NonVisualPicProperties: &PICNonVisualPicProperties{
|
NonVisualPicProperties: &PICNonVisualPicProperties{
|
||||||
NonVisualDrawingProperties: PICNonVisualDrawingProperties{
|
NonVisualDrawingProperties: PICNonVisualDrawingProperties{
|
||||||
@@ -179,7 +179,7 @@ func (p *Paragraph) AddAnchorDrawing(pic []byte) (*Run, error) {
|
|||||||
XMLA: XMLNS_DRAWINGML_MAIN,
|
XMLA: XMLNS_DRAWINGML_MAIN,
|
||||||
GraphicData: &AGraphicData{
|
GraphicData: &AGraphicData{
|
||||||
URI: XMLNS_PICTURE,
|
URI: XMLNS_PICTURE,
|
||||||
Pic: &PICPic{
|
Pic: &Picture{
|
||||||
XMLPIC: XMLNS_DRAWINGML_PICTURE,
|
XMLPIC: XMLNS_DRAWINGML_PICTURE,
|
||||||
NonVisualPicProperties: &PICNonVisualPicProperties{
|
NonVisualPicProperties: &PICNonVisualPicProperties{
|
||||||
NonVisualDrawingProperties: PICNonVisualDrawingProperties{
|
NonVisualDrawingProperties: PICNonVisualDrawingProperties{
|
||||||
|
|||||||
83
apishape.go
83
apishape.go
@@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package docx
|
package docx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -5,8 +25,63 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddShape adds wsp named drawing to paragraph
|
// AddInlineShape adds wsp named drawing to paragraph
|
||||||
func (p *Paragraph) AddShape(w, h int64, name, bwMode, prst string, elems []interface{}) (*Run, error) {
|
func (p *Paragraph) AddInlineShape(w, h int64, name, bwMode, prst string, ln *ALine) (*Run, error) {
|
||||||
|
idn := int(atomic.AddUintptr(&p.file.docID, 1))
|
||||||
|
id := strconv.Itoa(int(p.file.IncreaseID(name)))
|
||||||
|
d := &Drawing{
|
||||||
|
Inline: &WPInline{
|
||||||
|
Extent: &WPExtent{
|
||||||
|
CX: w,
|
||||||
|
CY: h,
|
||||||
|
},
|
||||||
|
EffectExtent: &WPEffectExtent{},
|
||||||
|
DocPr: &WPDocPr{
|
||||||
|
ID: idn,
|
||||||
|
Name: name + " " + id,
|
||||||
|
},
|
||||||
|
CNvGraphicFramePr: &WPCNvGraphicFramePr{},
|
||||||
|
Graphic: &AGraphic{
|
||||||
|
XMLA: XMLNS_DRAWINGML_MAIN,
|
||||||
|
GraphicData: &AGraphicData{
|
||||||
|
URI: XMLNS_WPS,
|
||||||
|
Shape: &WordprocessingShape{
|
||||||
|
CNvCnPr: &WPSCNvCnPr{
|
||||||
|
ConnShapeLocks: &struct{}{},
|
||||||
|
},
|
||||||
|
SpPr: &WPSSpPr{
|
||||||
|
BWMode: bwMode,
|
||||||
|
|
||||||
|
Xfrm: AXfrm{
|
||||||
|
Ext: AExt{
|
||||||
|
CX: w,
|
||||||
|
CY: h,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PrstGeom: APrstGeom{
|
||||||
|
Prst: prst,
|
||||||
|
},
|
||||||
|
NoFill: &struct{}{},
|
||||||
|
Line: ln,
|
||||||
|
},
|
||||||
|
BodyPr: &WPSBodyPr{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c := make([]interface{}, 1, 64)
|
||||||
|
c[0] = d
|
||||||
|
run := &Run{
|
||||||
|
RunProperties: &RunProperties{},
|
||||||
|
Children: c,
|
||||||
|
}
|
||||||
|
p.Children = append(p.Children, run)
|
||||||
|
return run, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAnchorShape adds wsp named drawing to paragraph
|
||||||
|
func (p *Paragraph) AddAnchorShape(w, h int64, name, bwMode, prst string, ln *ALine) (*Run, error) {
|
||||||
idn := int(atomic.AddUintptr(&p.file.docID, 1))
|
idn := int(atomic.AddUintptr(&p.file.docID, 1))
|
||||||
id := strconv.Itoa(int(p.file.IncreaseID(name)))
|
id := strconv.Itoa(int(p.file.IncreaseID(name)))
|
||||||
d := &Drawing{
|
d := &Drawing{
|
||||||
@@ -37,7 +112,7 @@ func (p *Paragraph) AddShape(w, h int64, name, bwMode, prst string, elems []inte
|
|||||||
XMLA: XMLNS_DRAWINGML_MAIN,
|
XMLA: XMLNS_DRAWINGML_MAIN,
|
||||||
GraphicData: &AGraphicData{
|
GraphicData: &AGraphicData{
|
||||||
URI: XMLNS_WPS,
|
URI: XMLNS_WPS,
|
||||||
Shape: &WPSWordprocessingShape{
|
Shape: &WordprocessingShape{
|
||||||
CNvCnPr: &WPSCNvCnPr{
|
CNvCnPr: &WPSCNvCnPr{
|
||||||
ConnShapeLocks: &struct{}{},
|
ConnShapeLocks: &struct{}{},
|
||||||
},
|
},
|
||||||
@@ -54,7 +129,7 @@ func (p *Paragraph) AddShape(w, h int64, name, bwMode, prst string, elems []inte
|
|||||||
Prst: prst,
|
Prst: prst,
|
||||||
},
|
},
|
||||||
NoFill: &struct{}{},
|
NoFill: &struct{}{},
|
||||||
Elems: elems,
|
Line: ln,
|
||||||
},
|
},
|
||||||
BodyPr: &WPSBodyPr{},
|
BodyPr: &WPSBodyPr{},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ func main() {
|
|||||||
|
|
||||||
p := w.AddParagraph().Justification("center")
|
p := w.AddParagraph().Justification("center")
|
||||||
p.AddText("测试 AutoShape w:ln").Size("44")
|
p.AddText("测试 AutoShape w:ln").Size("44")
|
||||||
p.AddShape(808355, 238760, "AutoShape", "auto", "straightConnector1", []interface{}{
|
p.AddAnchorShape(808355, 238760, "AutoShape", "auto", "straightConnector1",
|
||||||
&docx.ALine{
|
&docx.ALine{
|
||||||
W: 9525,
|
W: 9525,
|
||||||
SolidFill: &docx.ASolidFill{SrgbClr: &docx.ASrgbClr{Val: "000000"}},
|
SolidFill: &docx.ASolidFill{SrgbClr: &docx.ASrgbClr{Val: "000000"}},
|
||||||
@@ -133,7 +133,16 @@ func main() {
|
|||||||
HeadEnd: &docx.AHeadEnd{},
|
HeadEnd: &docx.AHeadEnd{},
|
||||||
TailEnd: &docx.ATailEnd{},
|
TailEnd: &docx.ATailEnd{},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
p.AddInlineShape(808355, 238760, "AutoShape", "auto", "straightConnector1",
|
||||||
|
&docx.ALine{
|
||||||
|
W: 9525,
|
||||||
|
SolidFill: &docx.ASolidFill{SrgbClr: &docx.ASrgbClr{Val: "000000"}},
|
||||||
|
Round: &struct{}{},
|
||||||
|
HeadEnd: &docx.AHeadEnd{},
|
||||||
|
TailEnd: &docx.ATailEnd{},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
f, err := os.Create(*fileLocation)
|
f, err := os.Create(*fileLocation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -193,7 +202,7 @@ func main() {
|
|||||||
if len(c.Paragraphs) > 0 && len(c.Paragraphs[0].Children) > 0 {
|
if len(c.Paragraphs) > 0 && len(c.Paragraphs[0].Children) > 0 {
|
||||||
fmt.Printf("<%d> %v\t", y, &c.Paragraphs[0])
|
fmt.Printf("<%d> %v\t", y, &c.Paragraphs[0])
|
||||||
} else {
|
} else {
|
||||||
fmt.Print("\t")
|
fmt.Printf("<%d> \t\t", y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Print("\n")
|
fmt.Print("\n")
|
||||||
|
|||||||
14
empty.go
14
empty.go
@@ -60,21 +60,11 @@ func newEmptyA4File() *Docx {
|
|||||||
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable`,
|
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable`,
|
||||||
Target: "fontTable.xml",
|
Target: "fontTable.xml",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
ID: "rId4",
|
|
||||||
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings`,
|
|
||||||
Target: "settings.xml",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "rId5",
|
|
||||||
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings`,
|
|
||||||
Target: "webSettings.xml",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
media: make([]Media, 0, 64),
|
media: make([]Media, 0, 64),
|
||||||
mediaNameIdx: make(map[string]int, 64),
|
mediaNameIdx: make(map[string]int, 64),
|
||||||
rID: 5,
|
rID: 3,
|
||||||
slowIDs: make(map[string]uintptr, 64),
|
slowIDs: make(map[string]uintptr, 64),
|
||||||
template: "a4",
|
template: "a4",
|
||||||
tmpfslst: []string{
|
tmpfslst: []string{
|
||||||
@@ -83,9 +73,7 @@ func newEmptyA4File() *Docx {
|
|||||||
"docProps/core.xml",
|
"docProps/core.xml",
|
||||||
"word/theme/theme1.xml",
|
"word/theme/theme1.xml",
|
||||||
"word/fontTable.xml",
|
"word/fontTable.xml",
|
||||||
"word/settings.xml",
|
|
||||||
"word/styles.xml",
|
"word/styles.xml",
|
||||||
"word/webSettings.xml",
|
|
||||||
"[Content_Types].xml",
|
"[Content_Types].xml",
|
||||||
},
|
},
|
||||||
buf: bytes.NewBuffer(make([]byte, 0, 1024*1024)),
|
buf: bytes.NewBuffer(make([]byte, 0, 1024*1024)),
|
||||||
|
|||||||
20
id.go
20
id.go
@@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package docx
|
package docx
|
||||||
|
|
||||||
func (f *Docx) IncreaseID(name string) (n uintptr) {
|
func (f *Docx) IncreaseID(name string) (n uintptr) {
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package docx
|
package docx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -12,6 +32,8 @@ type WordprocessingCanvas struct {
|
|||||||
Whole *WPCWhole
|
Whole *WPCWhole
|
||||||
|
|
||||||
Items []interface{}
|
Items []interface{}
|
||||||
|
|
||||||
|
file *Docx
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
@@ -40,7 +62,8 @@ func (c *WordprocessingCanvas) UnmarshalXML(d *xml.Decoder, start xml.StartEleme
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "wsp":
|
case "wsp":
|
||||||
var value WPSWordprocessingShape
|
var value WordprocessingShape
|
||||||
|
value.file = c.file
|
||||||
err = d.DecodeElement(&value, &tt)
|
err = d.DecodeElement(&value, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ type Drawing struct {
|
|||||||
XMLName xml.Name `xml:"w:drawing,omitempty"`
|
XMLName xml.Name `xml:"w:drawing,omitempty"`
|
||||||
Inline *WPInline
|
Inline *WPInline
|
||||||
Anchor *WPAnchor
|
Anchor *WPAnchor
|
||||||
|
|
||||||
|
file *Docx
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
@@ -61,12 +63,14 @@ func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
switch tt.Name.Local {
|
switch tt.Name.Local {
|
||||||
case "inline":
|
case "inline":
|
||||||
r.Inline = new(WPInline)
|
r.Inline = new(WPInline)
|
||||||
|
r.Inline.file = r.file
|
||||||
err = d.DecodeElement(r.Inline, &tt)
|
err = d.DecodeElement(r.Inline, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "anchor":
|
case "anchor":
|
||||||
r.Anchor = new(WPAnchor)
|
r.Anchor = new(WPAnchor)
|
||||||
|
r.Anchor.file = r.file
|
||||||
err = d.DecodeElement(r.Anchor, &tt)
|
err = d.DecodeElement(r.Anchor, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
@@ -105,6 +109,8 @@ type WPInline struct {
|
|||||||
DocPr *WPDocPr
|
DocPr *WPDocPr
|
||||||
CNvGraphicFramePr *WPCNvGraphicFramePr
|
CNvGraphicFramePr *WPCNvGraphicFramePr
|
||||||
Graphic *AGraphic
|
Graphic *AGraphic
|
||||||
|
|
||||||
|
file *Docx
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
@@ -191,6 +197,7 @@ func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err err
|
|||||||
r.CNvGraphicFramePr = &value
|
r.CNvGraphicFramePr = &value
|
||||||
case "graphic":
|
case "graphic":
|
||||||
var value AGraphic
|
var value AGraphic
|
||||||
|
value.file = r.file
|
||||||
err = d.DecodeElement(&value, &tt)
|
err = d.DecodeElement(&value, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
@@ -360,6 +367,8 @@ type AGraphic struct {
|
|||||||
XMLName xml.Name `xml:"a:graphic,omitempty"`
|
XMLName xml.Name `xml:"a:graphic,omitempty"`
|
||||||
XMLA string `xml:"xmlns:a,attr,omitempty"`
|
XMLA string `xml:"xmlns:a,attr,omitempty"`
|
||||||
GraphicData *AGraphicData
|
GraphicData *AGraphicData
|
||||||
|
|
||||||
|
file *Docx
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
@@ -385,6 +394,7 @@ func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
switch tt.Name.Local {
|
switch tt.Name.Local {
|
||||||
case "graphicData":
|
case "graphicData":
|
||||||
var value AGraphicData
|
var value AGraphicData
|
||||||
|
value.file = a.file
|
||||||
err = d.DecodeElement(&value, &tt)
|
err = d.DecodeElement(&value, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
@@ -407,8 +417,11 @@ func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
type AGraphicData struct {
|
type AGraphicData struct {
|
||||||
XMLName xml.Name `xml:"a:graphicData,omitempty"`
|
XMLName xml.Name `xml:"a:graphicData,omitempty"`
|
||||||
URI string `xml:"uri,attr"`
|
URI string `xml:"uri,attr"`
|
||||||
Pic *PICPic
|
Pic *Picture
|
||||||
Shape *WPSWordprocessingShape
|
Shape *WordprocessingShape
|
||||||
|
Canvas *WordprocessingCanvas
|
||||||
|
|
||||||
|
file *Docx
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
@@ -425,7 +438,7 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
|
|||||||
if tt, ok := t.(xml.StartElement); ok {
|
if tt, ok := t.(xml.StartElement); ok {
|
||||||
switch tt.Name.Local {
|
switch tt.Name.Local {
|
||||||
case "pic":
|
case "pic":
|
||||||
var value PICPic
|
var value Picture
|
||||||
err = d.DecodeElement(&value, &tt)
|
err = d.DecodeElement(&value, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
@@ -433,12 +446,21 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
|
|||||||
value.XMLPIC = getAtt(tt.Attr, "pic")
|
value.XMLPIC = getAtt(tt.Attr, "pic")
|
||||||
a.Pic = &value
|
a.Pic = &value
|
||||||
case "wsp":
|
case "wsp":
|
||||||
var value WPSWordprocessingShape
|
var value WordprocessingShape
|
||||||
|
value.file = a.file
|
||||||
err = d.DecodeElement(&value, &tt)
|
err = d.DecodeElement(&value, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
a.Shape = &value
|
a.Shape = &value
|
||||||
|
case "wpc":
|
||||||
|
var value WordprocessingCanvas
|
||||||
|
value.file = a.file
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.Canvas = &value
|
||||||
default:
|
default:
|
||||||
err = d.Skip() // skip unsupported tags
|
err = d.Skip() // skip unsupported tags
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -451,8 +473,8 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PICPic represents a picture in a Word document.
|
// Picture represents a picture in a Word document.
|
||||||
type PICPic struct {
|
type Picture struct {
|
||||||
XMLName xml.Name `xml:"pic:pic,omitempty"`
|
XMLName xml.Name `xml:"pic:pic,omitempty"`
|
||||||
XMLPIC string `xml:"xmlns:pic,attr,omitempty"`
|
XMLPIC string `xml:"xmlns:pic,attr,omitempty"`
|
||||||
NonVisualPicProperties *PICNonVisualPicProperties
|
NonVisualPicProperties *PICNonVisualPicProperties
|
||||||
@@ -461,7 +483,7 @@ type PICPic struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
func (p *PICPic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
func (p *Picture) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
for {
|
for {
|
||||||
t, err := d.Token()
|
t, err := d.Token()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@@ -649,7 +671,7 @@ func (p *PICBlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
|||||||
type ABlip struct {
|
type ABlip struct {
|
||||||
XMLName xml.Name `xml:"a:blip,omitempty"`
|
XMLName xml.Name `xml:"a:blip,omitempty"`
|
||||||
Embed string `xml:"r:embed,attr"`
|
Embed string `xml:"r:embed,attr"`
|
||||||
Cstate string `xml:"cstate,attr"`
|
Cstate string `xml:"cstate,attr,omitempty"`
|
||||||
AlphaModFix *AAlphaModFix
|
AlphaModFix *AAlphaModFix
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -934,6 +956,8 @@ type WPAnchor struct {
|
|||||||
DocPr *WPDocPr
|
DocPr *WPDocPr
|
||||||
CNvGraphicFramePr *WPCNvGraphicFramePr
|
CNvGraphicFramePr *WPCNvGraphicFramePr
|
||||||
Graphic *AGraphic
|
Graphic *AGraphic
|
||||||
|
|
||||||
|
file *Docx
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
@@ -1061,6 +1085,7 @@ func (r *WPAnchor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err err
|
|||||||
}
|
}
|
||||||
case "graphic":
|
case "graphic":
|
||||||
r.Graphic = new(AGraphic)
|
r.Graphic = new(AGraphic)
|
||||||
|
r.Graphic.file = r.file
|
||||||
err = d.DecodeElement(&r.Graphic, &tt)
|
err = d.DecodeElement(&r.Graphic, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package docx
|
package docx
|
||||||
|
|
||||||
import "encoding/xml"
|
import "encoding/xml"
|
||||||
@@ -27,6 +47,12 @@ type Size struct {
|
|||||||
Val string `xml:"w:val,attr"`
|
Val string `xml:"w:val,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SizeCs contains the cs font size
|
||||||
|
type SizeCs struct {
|
||||||
|
XMLName xml.Name `xml:"w:szCs,omitempty"`
|
||||||
|
Val string `xml:"w:val,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
// Bold ...
|
// Bold ...
|
||||||
type Bold struct {
|
type Bold struct {
|
||||||
XMLName xml.Name `xml:"w:b,omitempty"`
|
XMLName xml.Name `xml:"w:b,omitempty"`
|
||||||
@@ -52,7 +78,7 @@ type Highlight struct {
|
|||||||
// Kern ...
|
// Kern ...
|
||||||
type Kern struct {
|
type Kern struct {
|
||||||
XMLName xml.Name `xml:"w:kern,omitempty"`
|
XMLName xml.Name `xml:"w:kern,omitempty"`
|
||||||
Val int64 `xml:"w:val,attr,omitempty"`
|
Val int64 `xml:"w:val,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Justification contains the way of the horizonal alignment
|
// Justification contains the way of the horizonal alignment
|
||||||
@@ -68,6 +94,18 @@ type Justification struct {
|
|||||||
Val string `xml:"w:val,attr"`
|
Val string `xml:"w:val,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TextAlignment ...
|
||||||
|
type TextAlignment struct {
|
||||||
|
XMLName xml.Name `xml:"w:textAlignment,omitempty"`
|
||||||
|
Val string `xml:"w:val,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// VertAlign ...
|
||||||
|
type VertAlign struct {
|
||||||
|
XMLName xml.Name `xml:"w:vertAlign,omitempty"`
|
||||||
|
Val string `xml:"w:val,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
// Shade is an element that represents a shading pattern applied to a document element.
|
// Shade is an element that represents a shading pattern applied to a document element.
|
||||||
type Shade struct {
|
type Shade struct {
|
||||||
XMLName xml.Name `xml:"w:shd,omitempty"`
|
XMLName xml.Name `xml:"w:shd,omitempty"`
|
||||||
@@ -100,3 +138,27 @@ func (s *Shade) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
_, err := d.Token()
|
_, err := d.Token()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdjustRightInd ...
|
||||||
|
type AdjustRightInd struct {
|
||||||
|
XMLName xml.Name `xml:"w:adjustRightInd,omitempty"`
|
||||||
|
Val int `xml:"w:val,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SnapToGrid ...
|
||||||
|
type SnapToGrid struct {
|
||||||
|
XMLName xml.Name `xml:"w:snapToGrid,omitempty"`
|
||||||
|
Val int `xml:"w:val,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kinsoku ...
|
||||||
|
type Kinsoku struct {
|
||||||
|
XMLName xml.Name `xml:"w:kinsoku,omitempty"`
|
||||||
|
Val int `xml:"w:val,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// OverflowPunct ...
|
||||||
|
type OverflowPunct struct {
|
||||||
|
XMLName xml.Name `xml:"w:overflowPunct,omitempty"`
|
||||||
|
Val int `xml:"w:val,attr"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,10 +31,18 @@ import (
|
|||||||
|
|
||||||
// ParagraphProperties <w:pPr>
|
// ParagraphProperties <w:pPr>
|
||||||
type ParagraphProperties struct {
|
type ParagraphProperties struct {
|
||||||
XMLName xml.Name `xml:"w:pPr,omitempty"`
|
XMLName xml.Name `xml:"w:pPr,omitempty"`
|
||||||
Justification *Justification
|
Justification *Justification
|
||||||
Shade *Shade
|
Shade *Shade
|
||||||
Kern *Kern
|
Kern *Kern
|
||||||
|
Style *Style
|
||||||
|
TextAlignment *TextAlignment
|
||||||
|
AdjustRightInd *AdjustRightInd
|
||||||
|
SnapToGrid *SnapToGrid
|
||||||
|
Kinsoku *Kinsoku
|
||||||
|
OverflowPunct *OverflowPunct
|
||||||
|
|
||||||
|
RunProperties *RunProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
@@ -69,6 +77,61 @@ func (p *ParagraphProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.Kern = &value
|
p.Kern = &value
|
||||||
|
case "rPr":
|
||||||
|
var value RunProperties
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.RunProperties = &value
|
||||||
|
case "pStyle":
|
||||||
|
p.Style = &Style{Val: getAtt(tt.Attr, "val")}
|
||||||
|
case "textAlignment":
|
||||||
|
p.TextAlignment = &TextAlignment{Val: getAtt(tt.Attr, "val")}
|
||||||
|
case "adjustRightInd":
|
||||||
|
var value AdjustRightInd
|
||||||
|
v := getAtt(tt.Attr, "val")
|
||||||
|
if v == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value.Val, err = strconv.Atoi(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.AdjustRightInd = &value
|
||||||
|
case "snapToGrid":
|
||||||
|
var value SnapToGrid
|
||||||
|
v := getAtt(tt.Attr, "val")
|
||||||
|
if v == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value.Val, err = strconv.Atoi(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.SnapToGrid = &value
|
||||||
|
case "kinsoku":
|
||||||
|
var value Kinsoku
|
||||||
|
v := getAtt(tt.Attr, "val")
|
||||||
|
if v == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value.Val, err = strconv.Atoi(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.Kinsoku = &value
|
||||||
|
case "overflowPunct":
|
||||||
|
var value OverflowPunct
|
||||||
|
v := getAtt(tt.Attr, "val")
|
||||||
|
if v == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value.Val, err = strconv.Atoi(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.OverflowPunct = &value
|
||||||
default:
|
default:
|
||||||
err = d.Skip() // skip unsupported tags
|
err = d.Skip() // skip unsupported tags
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -177,27 +240,6 @@ func (p *Paragraph) String() string {
|
|||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalXML ...
|
|
||||||
func (p *Paragraph) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
|
||||||
err := e.EncodeToken(start)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if p.Properties != nil {
|
|
||||||
err = e.Encode(p.Properties)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, c := range p.Children {
|
|
||||||
err = e.Encode(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return e.EncodeToken(start.End())
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
func (p *Paragraph) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
func (p *Paragraph) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
for _, attr := range start.Attr {
|
for _, attr := range start.Attr {
|
||||||
@@ -243,6 +285,7 @@ func (p *Paragraph) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
elem = &value
|
elem = &value
|
||||||
case "r":
|
case "r":
|
||||||
var value Run
|
var value Run
|
||||||
|
value.file = p.file
|
||||||
err = d.DecodeElement(&value, &tt)
|
err = d.DecodeElement(&value, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -47,16 +47,6 @@ func TestRelationships(t *testing.T) {
|
|||||||
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable`,
|
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable`,
|
||||||
Target: "fontTable.xml",
|
Target: "fontTable.xml",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
ID: "rId4",
|
|
||||||
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings`,
|
|
||||||
Target: "settings.xml",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "rId5",
|
|
||||||
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings`,
|
|
||||||
Target: "webSettings.xml",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f, err := os.Create("TestRelationships.xml")
|
f, err := os.Create("TestRelationships.xml")
|
||||||
@@ -69,7 +59,7 @@ func TestRelationships(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
m := hex.EncodeToString(h.Sum(make([]byte, 0, 16)))
|
m := hex.EncodeToString(h.Sum(make([]byte, 0, 16)))
|
||||||
if m != "c75af73ef6cc9536a193669c4a3605c3" {
|
if m != "62c753dc14365fce007fc4c7c3bd0c82" {
|
||||||
t.Fatal("real md5:", m)
|
t.Fatal("real md5:", m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
structrun.go
35
structrun.go
@@ -31,16 +31,27 @@ import (
|
|||||||
// a piece of text in bold, or a link
|
// a piece of text in bold, or a link
|
||||||
type Run struct {
|
type Run struct {
|
||||||
XMLName xml.Name `xml:"w:r,omitempty"`
|
XMLName xml.Name `xml:"w:r,omitempty"`
|
||||||
|
RsidRPr string `xml:"w:rsidRPr,attr,omitempty"`
|
||||||
|
|
||||||
RunProperties *RunProperties `xml:"w:rPr,omitempty"`
|
RunProperties *RunProperties `xml:"w:rPr,omitempty"`
|
||||||
|
|
||||||
InstrText string `xml:"w:instrText,omitempty"`
|
InstrText string `xml:"w:instrText,omitempty"`
|
||||||
|
|
||||||
Children []interface{}
|
Children []interface{}
|
||||||
|
|
||||||
|
file *Docx
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
for _, attr := range start.Attr {
|
||||||
|
switch attr.Name.Local {
|
||||||
|
case "rsidRPr":
|
||||||
|
r.RsidRPr = attr.Value
|
||||||
|
default:
|
||||||
|
// ignore other attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
t, err := d.Token()
|
t, err := d.Token()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@@ -91,6 +102,7 @@ func (r *Run) parse(d *xml.Decoder, tt xml.StartElement) (child interface{}, err
|
|||||||
child = &value
|
child = &value
|
||||||
case "drawing":
|
case "drawing":
|
||||||
var value Drawing
|
var value Drawing
|
||||||
|
value.file = r.file
|
||||||
err = d.DecodeElement(&value, &tt)
|
err = d.DecodeElement(&value, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -112,8 +124,14 @@ func (r *Run) parse(d *xml.Decoder, tt xml.StartElement) (child interface{}, err
|
|||||||
if ttt, ok := tok.(xml.StartElement); ok && ttt.Name.Local == "Choice" {
|
if ttt, ok := tok.(xml.StartElement); ok && ttt.Name.Local == "Choice" {
|
||||||
for _, attr := range ttt.Attr {
|
for _, attr := range ttt.Attr {
|
||||||
if attr.Name.Local == "Requires" {
|
if attr.Name.Local == "Requires" {
|
||||||
if attr.Value == "wps" {
|
if attr.Value == "wps" || attr.Value == "wpc" {
|
||||||
child, err = r.parse(d, ttt)
|
tok, err = d.Token() // go into choice
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ttt, ok := tok.(xml.StartElement); ok {
|
||||||
|
child, err = r.parse(d, ttt)
|
||||||
|
}
|
||||||
break altcont
|
break altcont
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@@ -141,15 +159,18 @@ type RunProperties struct {
|
|||||||
XMLName xml.Name `xml:"w:rPr,omitempty"`
|
XMLName xml.Name `xml:"w:rPr,omitempty"`
|
||||||
Fonts *RunFonts
|
Fonts *RunFonts
|
||||||
Bold *Bold
|
Bold *Bold
|
||||||
|
ICs *struct{} `xml:"w:iCs,omitempty"`
|
||||||
Italic *Italic
|
Italic *Italic
|
||||||
Underline *Underline
|
Underline *Underline
|
||||||
Highlight *Highlight
|
Highlight *Highlight
|
||||||
Color *Color
|
Color *Color
|
||||||
Size *Size
|
Size *Size
|
||||||
|
SizeCs *SizeCs
|
||||||
RunStyle *RunStyle
|
RunStyle *RunStyle
|
||||||
Style *Style
|
Style *Style
|
||||||
Shade *Shade
|
Shade *Shade
|
||||||
Kern *Kern
|
Kern *Kern
|
||||||
|
VertAlign *VertAlign
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
@@ -174,6 +195,8 @@ func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
|
|||||||
r.Fonts = &value
|
r.Fonts = &value
|
||||||
case "b":
|
case "b":
|
||||||
r.Bold = &Bold{}
|
r.Bold = &Bold{}
|
||||||
|
case "iCs":
|
||||||
|
r.ICs = &struct{}{}
|
||||||
case "i":
|
case "i":
|
||||||
r.Italic = &Italic{}
|
r.Italic = &Italic{}
|
||||||
case "u":
|
case "u":
|
||||||
@@ -192,6 +215,10 @@ func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
|
|||||||
var value Size
|
var value Size
|
||||||
value.Val = getAtt(tt.Attr, "val")
|
value.Val = getAtt(tt.Attr, "val")
|
||||||
r.Size = &value
|
r.Size = &value
|
||||||
|
case "szCs":
|
||||||
|
var value SizeCs
|
||||||
|
value.Val = getAtt(tt.Attr, "val")
|
||||||
|
r.SizeCs = &value
|
||||||
case "rStyle":
|
case "rStyle":
|
||||||
var value RunStyle
|
var value RunStyle
|
||||||
value.Val = getAtt(tt.Attr, "val")
|
value.Val = getAtt(tt.Attr, "val")
|
||||||
@@ -218,6 +245,10 @@ func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.Kern = &value
|
r.Kern = &value
|
||||||
|
case "vertAlign":
|
||||||
|
var value VertAlign
|
||||||
|
value.Val = getAtt(tt.Attr, "val")
|
||||||
|
r.VertAlign = &value
|
||||||
default:
|
default:
|
||||||
err = d.Skip() // skip unsupported tags
|
err = d.Skip() // skip unsupported tags
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
441
structshape.go
441
structshape.go
@@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package docx
|
package docx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -7,16 +27,21 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WPSWordprocessingShape is a container for a WordprocessingML DrawingML shape.
|
// WordprocessingShape is a container for a WordprocessingML DrawingML shape.
|
||||||
type WPSWordprocessingShape struct {
|
type WordprocessingShape struct {
|
||||||
XMLName xml.Name `xml:"wps:wsp,omitempty"`
|
XMLName xml.Name `xml:"wps:wsp,omitempty"`
|
||||||
|
CNvPr *WPSCNvPr
|
||||||
CNvCnPr *WPSCNvCnPr
|
CNvCnPr *WPSCNvCnPr
|
||||||
|
CNvSpPr *WPSCNvSpPr
|
||||||
SpPr *WPSSpPr
|
SpPr *WPSSpPr
|
||||||
|
TextBox *WPSTextBox
|
||||||
BodyPr *WPSBodyPr
|
BodyPr *WPSBodyPr
|
||||||
|
|
||||||
|
file *Docx
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
func (w *WPSWordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
func (w *WordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
for {
|
for {
|
||||||
t, err := d.Token()
|
t, err := d.Token()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@@ -28,18 +53,38 @@ func (w *WPSWordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartEle
|
|||||||
|
|
||||||
if tt, ok := t.(xml.StartElement); ok {
|
if tt, ok := t.(xml.StartElement); ok {
|
||||||
switch tt.Name.Local {
|
switch tt.Name.Local {
|
||||||
|
case "cNvPr":
|
||||||
|
w.CNvPr = new(WPSCNvPr)
|
||||||
|
err = d.DecodeElement(w.CNvPr, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case "cNvCnPr":
|
case "cNvCnPr":
|
||||||
w.CNvCnPr = new(WPSCNvCnPr)
|
w.CNvCnPr = new(WPSCNvCnPr)
|
||||||
err = d.DecodeElement(w.CNvCnPr, &tt)
|
err = d.DecodeElement(w.CNvCnPr, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case "cNvSpPr":
|
||||||
|
w.CNvSpPr = new(WPSCNvSpPr)
|
||||||
|
err = d.DecodeElement(w.CNvSpPr, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case "spPr":
|
case "spPr":
|
||||||
w.SpPr = new(WPSSpPr)
|
w.SpPr = new(WPSSpPr)
|
||||||
err = d.DecodeElement(w.SpPr, &tt)
|
err = d.DecodeElement(w.SpPr, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case "txbx":
|
||||||
|
var value WPSTextBox
|
||||||
|
value.file = w.file
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.TextBox = &value
|
||||||
case "bodyPr":
|
case "bodyPr":
|
||||||
w.BodyPr = new(WPSBodyPr)
|
w.BodyPr = new(WPSBodyPr)
|
||||||
err = d.DecodeElement(w.BodyPr, &tt)
|
err = d.DecodeElement(w.BodyPr, &tt)
|
||||||
@@ -57,6 +102,33 @@ func (w *WPSWordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartEle
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WPSCNvPr is an element that represents the non-visual properties of a content control.
|
||||||
|
type WPSCNvPr struct {
|
||||||
|
XMLName xml.Name `xml:"wps:cNvPr,omitempty"`
|
||||||
|
ID int `xml:"id,attr"`
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (r *WPSCNvPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
|
||||||
|
for _, attr := range start.Attr {
|
||||||
|
switch attr.Name.Local {
|
||||||
|
case "id":
|
||||||
|
r.ID, err = strconv.Atoi(attr.Value)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "name":
|
||||||
|
r.Name = attr.Value
|
||||||
|
default:
|
||||||
|
// ignore other attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Consume the end element
|
||||||
|
_, err = d.Token()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// WPSCNvCnPr represents the non-visual drawing properties of a connector.
|
// WPSCNvCnPr represents the non-visual drawing properties of a connector.
|
||||||
type WPSCNvCnPr struct {
|
type WPSCNvCnPr struct {
|
||||||
XMLName xml.Name `xml:"wps:cNvCnPr,omitempty"`
|
XMLName xml.Name `xml:"wps:cNvCnPr,omitempty"`
|
||||||
@@ -90,15 +162,76 @@ func (w *WPSCNvCnPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WPSCNvSpPr represents the non-visual properties of a WordArt object.
|
||||||
|
type WPSCNvSpPr struct {
|
||||||
|
XMLName xml.Name `xml:"wps:cNvSpPr,omitempty"`
|
||||||
|
TxBox int `xml:"txBox,attr,omitempty"`
|
||||||
|
|
||||||
|
SPLocks *ASPLocks
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (w *WPSCNvSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
|
||||||
|
for _, attr := range start.Attr {
|
||||||
|
switch attr.Name.Local {
|
||||||
|
case "txBox":
|
||||||
|
w.TxBox, err = strconv.Atoi(attr.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// ignore other attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 "spLocks":
|
||||||
|
var value ASPLocks
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.SPLocks = &value
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported tags
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASPLocks represents the locks applied to a shape.
|
||||||
|
type ASPLocks struct {
|
||||||
|
XMLName xml.Name `xml:"a:spLocks,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// WPSSpPr is a container element that represents the visual properties of a shape.
|
// WPSSpPr is a container element that represents the visual properties of a shape.
|
||||||
type WPSSpPr struct {
|
type WPSSpPr struct {
|
||||||
XMLName xml.Name `xml:"wps:spPr,omitempty"`
|
XMLName xml.Name `xml:"wps:spPr,omitempty"`
|
||||||
BWMode string `xml:"bwMode,attr"`
|
BWMode string `xml:"bwMode,attr"`
|
||||||
|
|
||||||
Xfrm AXfrm
|
Xfrm AXfrm
|
||||||
PrstGeom APrstGeom
|
PrstGeom APrstGeom
|
||||||
NoFill *struct{} `xml:"a:noFill,omitempty"`
|
SolidFill *ASolidFill
|
||||||
Elems []interface{}
|
BlipFill *ABlipFill
|
||||||
|
NoFill *struct{} `xml:"a:noFill,omitempty"`
|
||||||
|
Line *ALine
|
||||||
|
|
||||||
|
EffectList struct{} `xml:"a:effectLst"`
|
||||||
|
ExtList struct{} `xml:"a:extLst"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
@@ -129,6 +262,20 @@ func (w *WPSSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
}
|
}
|
||||||
case "prstGeom":
|
case "prstGeom":
|
||||||
w.PrstGeom.Prst = getAtt(tt.Attr, "prst")
|
w.PrstGeom.Prst = getAtt(tt.Attr, "prst")
|
||||||
|
case "solidFill":
|
||||||
|
var value ASolidFill
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.SolidFill = &value
|
||||||
|
case "blipFill":
|
||||||
|
var value ABlipFill
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.BlipFill = &value
|
||||||
case "noFill":
|
case "noFill":
|
||||||
w.NoFill = &struct{}{}
|
w.NoFill = &struct{}{}
|
||||||
case "ln":
|
case "ln":
|
||||||
@@ -137,7 +284,7 @@ func (w *WPSSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.Elems = append(w.Elems, &ln)
|
w.Line = &ln
|
||||||
default:
|
default:
|
||||||
err = d.Skip() // skip unsupported tags
|
err = d.Skip() // skip unsupported tags
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -150,14 +297,137 @@ func (w *WPSSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ABlipFill represents a fill that contains a reference to an image.
|
||||||
|
type ABlipFill struct {
|
||||||
|
XMLName xml.Name `xml:"a:blipFill,omitempty"`
|
||||||
|
DPI int `xml:"dpi,attr"`
|
||||||
|
RotWithShape int `xml:"rotWithShape,attr"`
|
||||||
|
|
||||||
|
Blip *ABlip
|
||||||
|
SrcRect *ASrcRect
|
||||||
|
Tile *ATile
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (r *ABlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
|
||||||
|
for _, attr := range start.Attr {
|
||||||
|
switch attr.Name.Local {
|
||||||
|
case "dpi":
|
||||||
|
r.DPI, err = strconv.Atoi(attr.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "rotWithShape":
|
||||||
|
r.RotWithShape, err = strconv.Atoi(attr.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// ignore other attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 "blip":
|
||||||
|
var value ABlip
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Blip = &value
|
||||||
|
case "srcRect":
|
||||||
|
r.SrcRect = new(ASrcRect)
|
||||||
|
case "tile":
|
||||||
|
var value ATile
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Tile = &value
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported tags
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASrcRect represents the source rectangle of a tiled image fill.
|
||||||
|
type ASrcRect struct {
|
||||||
|
XMLName xml.Name `xml:"a:srcRect,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ATile represents the tiling information of a fill or border
|
||||||
|
type ATile struct {
|
||||||
|
XMLName xml.Name `xml:"a:tile,omitempty"`
|
||||||
|
TX int64 `xml:"tx,attr"`
|
||||||
|
TY int64 `xml:"ty,attr"`
|
||||||
|
SX int64 `xml:"sx,attr"`
|
||||||
|
SY int64 `xml:"sy,attr"`
|
||||||
|
Flip string `xml:"flip,attr"`
|
||||||
|
Algn string `xml:"algn,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (t *ATile) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
|
||||||
|
for _, attr := range start.Attr {
|
||||||
|
switch attr.Name.Local {
|
||||||
|
case "tx":
|
||||||
|
t.TX, err = strconv.ParseInt(attr.Value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "ty":
|
||||||
|
t.TY, err = strconv.ParseInt(attr.Value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "sx":
|
||||||
|
t.SX, err = strconv.ParseInt(attr.Value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "sy":
|
||||||
|
t.SY, err = strconv.ParseInt(attr.Value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "flip":
|
||||||
|
t.Flip = attr.Value
|
||||||
|
case "algn":
|
||||||
|
t.Algn = attr.Value
|
||||||
|
default:
|
||||||
|
// ignore other attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Consume the end element
|
||||||
|
_, err = d.Token()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// ALine represents a line element in a Word document.
|
// ALine represents a line element in a Word document.
|
||||||
type ALine struct {
|
type ALine struct {
|
||||||
XMLName xml.Name `xml:"a:ln,omitempty"`
|
XMLName xml.Name `xml:"a:ln,omitempty"`
|
||||||
W int64 `xml:"w,attr"`
|
W int64 `xml:"w,attr,omitempty"`
|
||||||
Cap string `xml:"cap,attr,omitempty"`
|
Cap string `xml:"cap,attr,omitempty"`
|
||||||
Compound string `xml:"cmpd,attr,omitempty"`
|
Compound string `xml:"cmpd,attr,omitempty"`
|
||||||
Align string `xml:"algn,attr,omitempty"`
|
Align string `xml:"algn,attr,omitempty"`
|
||||||
|
|
||||||
|
NoFill *struct{} `xml:"a:noFill,omitempty"`
|
||||||
SolidFill *ASolidFill
|
SolidFill *ASolidFill
|
||||||
PrstDash *APrstDash
|
PrstDash *APrstDash
|
||||||
Miter *AMiter
|
Miter *AMiter
|
||||||
@@ -196,6 +466,8 @@ func (l *ALine) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error)
|
|||||||
|
|
||||||
if tt, ok := t.(xml.StartElement); ok {
|
if tt, ok := t.(xml.StartElement); ok {
|
||||||
switch tt.Name.Local {
|
switch tt.Name.Local {
|
||||||
|
case "noFill":
|
||||||
|
l.NoFill = &struct{}{}
|
||||||
case "solidFill":
|
case "solidFill":
|
||||||
l.SolidFill = new(ASolidFill)
|
l.SolidFill = new(ASolidFill)
|
||||||
err = d.DecodeElement(l.SolidFill, &tt)
|
err = d.DecodeElement(l.SolidFill, &tt)
|
||||||
@@ -351,7 +623,156 @@ func (r *ATailEnd) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WPSTextBox ...
|
||||||
|
type WPSTextBox struct {
|
||||||
|
XMLName xml.Name `xml:"wps:txbx,omitempty"`
|
||||||
|
Content *WTextBoxContent
|
||||||
|
|
||||||
|
file *Docx
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (b *WPSTextBox) 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 "txbxContent":
|
||||||
|
var value WTextBoxContent
|
||||||
|
value.file = b.file
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.Content = &value
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported tags
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WTextBoxContent ...
|
||||||
|
type WTextBoxContent struct {
|
||||||
|
XMLName xml.Name `xml:"w:txbxContent,omitempty"`
|
||||||
|
Paragraphs []Paragraph `xml:"w:p,omitempty"`
|
||||||
|
|
||||||
|
file *Docx
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (c *WTextBoxContent) 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 "p":
|
||||||
|
var value Paragraph
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(value.Children) > 0 {
|
||||||
|
value.file = c.file
|
||||||
|
c.Paragraphs = append(c.Paragraphs, value)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported tags
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// WPSBodyPr represents the body properties for a WordprocessingML DrawingML shape.
|
// WPSBodyPr represents the body properties for a WordprocessingML DrawingML shape.
|
||||||
type WPSBodyPr struct {
|
type WPSBodyPr struct {
|
||||||
XMLName xml.Name `xml:"wps:bodyPr,omitempty"`
|
XMLName xml.Name `xml:"wps:bodyPr,omitempty"`
|
||||||
|
Rot int `xml:"rot,attr,omitempty"`
|
||||||
|
Vert string `xml:"vert,attr,omitempty"`
|
||||||
|
Wrap string `xml:"wrap,attr,omitempty"`
|
||||||
|
LIns int64 `xml:"lIns,attr,omitempty"`
|
||||||
|
TIns int64 `xml:"tIns,attr,omitempty"`
|
||||||
|
RIns int64 `xml:"rIns,attr,omitempty"`
|
||||||
|
BIns int64 `xml:"bIns,attr,omitempty"`
|
||||||
|
Anchor string `xml:"anchor,attr,omitempty"`
|
||||||
|
AnchorCtr int `xml:"anchorCtr,attr,omitempty"`
|
||||||
|
Upright int `xml:"upright,attr,omitempty"`
|
||||||
|
|
||||||
|
NoAutofit *struct{} `xml:"a:noAutofit,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (r *WPSBodyPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
for _, attr := range start.Attr {
|
||||||
|
switch attr.Name.Local {
|
||||||
|
case "rot":
|
||||||
|
r.Rot, _ = strconv.Atoi(attr.Value)
|
||||||
|
case "vert":
|
||||||
|
r.Vert = attr.Value
|
||||||
|
case "wrap":
|
||||||
|
r.Wrap = attr.Value
|
||||||
|
case "lIns":
|
||||||
|
r.LIns, _ = strconv.ParseInt(attr.Value, 10, 64)
|
||||||
|
case "tIns":
|
||||||
|
r.TIns, _ = strconv.ParseInt(attr.Value, 10, 64)
|
||||||
|
case "rIns":
|
||||||
|
r.RIns, _ = strconv.ParseInt(attr.Value, 10, 64)
|
||||||
|
case "bIns":
|
||||||
|
r.BIns, _ = strconv.ParseInt(attr.Value, 10, 64)
|
||||||
|
case "anchor":
|
||||||
|
r.Anchor = attr.Value
|
||||||
|
case "anchorCtr":
|
||||||
|
r.AnchorCtr, _ = strconv.Atoi(attr.Value)
|
||||||
|
case "upright":
|
||||||
|
r.Upright, _ = strconv.Atoi(attr.Value)
|
||||||
|
default:
|
||||||
|
// ignore other attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 "noAutofit":
|
||||||
|
r.NoAutofit = &struct{}{}
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported elements
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package docx
|
package docx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -13,8 +33,8 @@ func TestShapeStructure(t *testing.T) {
|
|||||||
// add new paragraph
|
// add new paragraph
|
||||||
para1 := w.AddParagraph()
|
para1 := w.AddParagraph()
|
||||||
// add text
|
// add text
|
||||||
para1.AddText("test shape")
|
para1.AddText("test anchor shape")
|
||||||
para1.AddShape(808355, 238760, "AutoShape", "auto", "straightConnector1", []interface{}{
|
para1.AddAnchorShape(808355, 238760, "AutoShape", "auto", "straightConnector1",
|
||||||
&ALine{
|
&ALine{
|
||||||
W: 9525,
|
W: 9525,
|
||||||
SolidFill: &ASolidFill{SrgbClr: &ASrgbClr{Val: "000000"}},
|
SolidFill: &ASolidFill{SrgbClr: &ASrgbClr{Val: "000000"}},
|
||||||
@@ -22,7 +42,19 @@ func TestShapeStructure(t *testing.T) {
|
|||||||
HeadEnd: &AHeadEnd{},
|
HeadEnd: &AHeadEnd{},
|
||||||
TailEnd: &ATailEnd{},
|
TailEnd: &ATailEnd{},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
|
para2 := w.AddParagraph()
|
||||||
|
para2.AddText("test inline shape")
|
||||||
|
para2.AddInlineShape(808355, 238760, "AutoShape", "auto", "straightConnector1",
|
||||||
|
&ALine{
|
||||||
|
W: 9525,
|
||||||
|
SolidFill: &ASolidFill{SrgbClr: &ASrgbClr{Val: "000000"}},
|
||||||
|
Round: &struct{}{},
|
||||||
|
HeadEnd: &AHeadEnd{},
|
||||||
|
TailEnd: &ATailEnd{},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
f, err := os.Create("TestMarshalShapeStructure.xml")
|
f, err := os.Create("TestMarshalShapeStructure.xml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -51,11 +51,11 @@ func (t *WTable) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
switch tt.Name.Local {
|
switch tt.Name.Local {
|
||||||
case "tr":
|
case "tr":
|
||||||
var value WTableRow
|
var value WTableRow
|
||||||
|
value.file = t.file
|
||||||
err = d.DecodeElement(&value, &tt)
|
err = d.DecodeElement(&value, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
value.file = t.file
|
|
||||||
t.TableRows = append(t.TableRows, &value)
|
t.TableRows = append(t.TableRows, &value)
|
||||||
case "tblPr":
|
case "tblPr":
|
||||||
t.TableProperties = new(WTableProperties)
|
t.TableProperties = new(WTableProperties)
|
||||||
@@ -421,11 +421,11 @@ func (w *WTableRow) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
}
|
}
|
||||||
case "tc":
|
case "tc":
|
||||||
var value WTableCell
|
var value WTableCell
|
||||||
|
value.file = w.file
|
||||||
err = d.DecodeElement(&value, &tt)
|
err = d.DecodeElement(&value, &tt)
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
value.file = w.file
|
|
||||||
w.TableCells = append(w.TableCells, &value)
|
w.TableCells = append(w.TableCells, &value)
|
||||||
default:
|
default:
|
||||||
err = d.Skip() // skip unsupported tags
|
err = d.Skip() // skip unsupported tags
|
||||||
@@ -504,7 +504,7 @@ func (t *WTableRowProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
|
|||||||
// WTableRowHeight represents the height of a row within a table.
|
// WTableRowHeight represents the height of a row within a table.
|
||||||
type WTableRowHeight struct {
|
type WTableRowHeight struct {
|
||||||
XMLName xml.Name `xml:"w:trHeight,omitempty"`
|
XMLName xml.Name `xml:"w:trHeight,omitempty"`
|
||||||
Rule string `xml:"w:hRule,omitempty"`
|
Rule string `xml:"w:hRule,attr,omitempty"`
|
||||||
Val int64 `xml:"w:val,attr"`
|
Val int64 `xml:"w:val,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,9 +565,9 @@ type WTableCellProperties struct {
|
|||||||
TableCellWidth *WTableCellWidth
|
TableCellWidth *WTableCellWidth
|
||||||
VMerge *WvMerge
|
VMerge *WvMerge
|
||||||
GridSpan *WGridSpan
|
GridSpan *WGridSpan
|
||||||
VAlign *WVerticalAlignment
|
|
||||||
TableBorders *WTableBorders `xml:"w:tcBorders"`
|
TableBorders *WTableBorders `xml:"w:tcBorders"`
|
||||||
Shade *Shade
|
Shade *Shade
|
||||||
|
VAlign *WVerticalAlignment
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML ...
|
// UnmarshalXML ...
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
<Default Extension="xml" ContentType="application/xml"/>
|
<Default Extension="xml" ContentType="application/xml"/>
|
||||||
<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
|
<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
|
||||||
<Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
|
<Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
|
||||||
<Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/>
|
|
||||||
<Override PartName="/word/webSettings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"/>
|
|
||||||
<Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"/>
|
<Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"/>
|
||||||
<Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
|
<Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
|
||||||
<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
|
<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
||||||
<w:settings xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:o="urn:schemas-microsoft-com:office:office"
|
|
||||||
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
|
||||||
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
|
|
||||||
xmlns:v="urn:schemas-microsoft-com:vml"
|
|
||||||
xmlns:w10="urn:schemas-microsoft-com:office:word"
|
|
||||||
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
|
||||||
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
|
|
||||||
xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
|
|
||||||
xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex"
|
|
||||||
xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
|
|
||||||
xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml"
|
|
||||||
xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash"
|
|
||||||
xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
|
|
||||||
xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh">
|
|
||||||
<w:zoom w:percent="179"/>
|
|
||||||
<w:bordersDoNotSurroundHeader/>
|
|
||||||
<w:bordersDoNotSurroundFooter/>
|
|
||||||
<w:proofState w:spelling="clean" w:grammar="clean"/>
|
|
||||||
<w:defaultTabStop w:val="420"/>
|
|
||||||
<w:characterSpacingControl w:val="doNotCompress"/>
|
|
||||||
<w:compat>
|
|
||||||
<w:useFELayout/>
|
|
||||||
<w:compatSetting w:name="compatibilityMode" w:uri="http://schemas.microsoft.com/office/word" w:val="15"/>
|
|
||||||
<w:compatSetting w:name="overrideTableStyleFontSizeAndJustification" w:uri="http://schemas.microsoft.com/office/word" w:val="1"/>
|
|
||||||
<w:compatSetting w:name="enableOpenTypeFeatures" w:uri="http://schemas.microsoft.com/office/word" w:val="1"/>
|
|
||||||
<w:compatSetting w:name="doNotFlipMirrorIndents" w:uri="http://schemas.microsoft.com/office/word" w:val="1"/>
|
|
||||||
<w:compatSetting w:name="differentiateMultirowTableHeaders" w:uri="http://schemas.microsoft.com/office/word" w:val="1"/>
|
|
||||||
<w:compatSetting w:name="useWord2013TrackBottomHyphenation" w:uri="http://schemas.microsoft.com/office/word" w:val="0"/>
|
|
||||||
</w:compat>
|
|
||||||
<w:rsids>
|
|
||||||
<w:rsidRoot w:val="008E4657"/>
|
|
||||||
<w:rsid w:val="006A5E36"/>
|
|
||||||
<w:rsid w:val="008E4657"/>
|
|
||||||
</w:rsids>
|
|
||||||
<m:mathPr>
|
|
||||||
<m:mathFont m:val="Cambria Math"/>
|
|
||||||
<m:brkBin m:val="before"/>
|
|
||||||
<m:brkBinSub m:val="--"/>
|
|
||||||
<m:smallFrac m:val="0"/>
|
|
||||||
<m:dispDef/>
|
|
||||||
<m:lMargin m:val="0"/>
|
|
||||||
<m:rMargin m:val="0"/>
|
|
||||||
<m:defJc m:val="centerGroup"/>
|
|
||||||
<m:wrapIndent m:val="1440"/>
|
|
||||||
<m:intLim m:val="subSup"/>
|
|
||||||
<m:naryLim m:val="undOvr"/>
|
|
||||||
</m:mathPr>
|
|
||||||
<w:themeFontLang w:val="en-US" w:eastAsia="zh-CN"/>
|
|
||||||
<w:clrSchemeMapping w:bg1="light1" w:t1="dark1" w:bg2="light2" w:t2="dark2" w:accent1="accent1" w:accent2="accent2" w:accent3="accent3" w:accent4="accent4" w:accent5="accent5" w:accent6="accent6" w:hyperlink="hyperlink" w:followedHyperlink="followedHyperlink"/>
|
|
||||||
<w:decimalSymbol w:val="."/>
|
|
||||||
<w:listSeparator w:val=","/>
|
|
||||||
<w14:docId w14:val="1FCC31E2"/>
|
|
||||||
<w15:docId w15:val="{E96752AD-97D3-6946-8F9F-89449BD2C27F}"/>
|
|
||||||
</w:settings>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
||||||
<w:webSettings xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
|
||||||
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
|
||||||
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
|
|
||||||
xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
|
|
||||||
xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex"
|
|
||||||
xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
|
|
||||||
xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml"
|
|
||||||
xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash"
|
|
||||||
xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh"/>
|
|
||||||
Reference in New Issue
Block a user