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,
|
||||
GraphicData: &AGraphicData{
|
||||
URI: XMLNS_PICTURE,
|
||||
Pic: &PICPic{
|
||||
Pic: &Picture{
|
||||
XMLPIC: XMLNS_DRAWINGML_PICTURE,
|
||||
NonVisualPicProperties: &PICNonVisualPicProperties{
|
||||
NonVisualDrawingProperties: PICNonVisualDrawingProperties{
|
||||
@@ -179,7 +179,7 @@ func (p *Paragraph) AddAnchorDrawing(pic []byte) (*Run, error) {
|
||||
XMLA: XMLNS_DRAWINGML_MAIN,
|
||||
GraphicData: &AGraphicData{
|
||||
URI: XMLNS_PICTURE,
|
||||
Pic: &PICPic{
|
||||
Pic: &Picture{
|
||||
XMLPIC: XMLNS_DRAWINGML_PICTURE,
|
||||
NonVisualPicProperties: &PICNonVisualPicProperties{
|
||||
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
|
||||
|
||||
import (
|
||||
@@ -5,8 +25,63 @@ import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// AddShape adds wsp named drawing to paragraph
|
||||
func (p *Paragraph) AddShape(w, h int64, name, bwMode, prst string, elems []interface{}) (*Run, error) {
|
||||
// AddInlineShape adds wsp named drawing to paragraph
|
||||
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))
|
||||
id := strconv.Itoa(int(p.file.IncreaseID(name)))
|
||||
d := &Drawing{
|
||||
@@ -37,7 +112,7 @@ func (p *Paragraph) AddShape(w, h int64, name, bwMode, prst string, elems []inte
|
||||
XMLA: XMLNS_DRAWINGML_MAIN,
|
||||
GraphicData: &AGraphicData{
|
||||
URI: XMLNS_WPS,
|
||||
Shape: &WPSWordprocessingShape{
|
||||
Shape: &WordprocessingShape{
|
||||
CNvCnPr: &WPSCNvCnPr{
|
||||
ConnShapeLocks: &struct{}{},
|
||||
},
|
||||
@@ -54,7 +129,7 @@ func (p *Paragraph) AddShape(w, h int64, name, bwMode, prst string, elems []inte
|
||||
Prst: prst,
|
||||
},
|
||||
NoFill: &struct{}{},
|
||||
Elems: elems,
|
||||
Line: ln,
|
||||
},
|
||||
BodyPr: &WPSBodyPr{},
|
||||
},
|
||||
|
||||
@@ -125,7 +125,7 @@ func main() {
|
||||
|
||||
p := w.AddParagraph().Justification("center")
|
||||
p.AddText("测试 AutoShape w:ln").Size("44")
|
||||
p.AddShape(808355, 238760, "AutoShape", "auto", "straightConnector1", []interface{}{
|
||||
p.AddAnchorShape(808355, 238760, "AutoShape", "auto", "straightConnector1",
|
||||
&docx.ALine{
|
||||
W: 9525,
|
||||
SolidFill: &docx.ASolidFill{SrgbClr: &docx.ASrgbClr{Val: "000000"}},
|
||||
@@ -133,7 +133,16 @@ func main() {
|
||||
HeadEnd: &docx.AHeadEnd{},
|
||||
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)
|
||||
if err != nil {
|
||||
@@ -193,7 +202,7 @@ func main() {
|
||||
if len(c.Paragraphs) > 0 && len(c.Paragraphs[0].Children) > 0 {
|
||||
fmt.Printf("<%d> %v\t", y, &c.Paragraphs[0])
|
||||
} else {
|
||||
fmt.Print("\t")
|
||||
fmt.Printf("<%d> \t\t", y)
|
||||
}
|
||||
}
|
||||
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`,
|
||||
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),
|
||||
mediaNameIdx: make(map[string]int, 64),
|
||||
rID: 5,
|
||||
rID: 3,
|
||||
slowIDs: make(map[string]uintptr, 64),
|
||||
template: "a4",
|
||||
tmpfslst: []string{
|
||||
@@ -83,9 +73,7 @@ func newEmptyA4File() *Docx {
|
||||
"docProps/core.xml",
|
||||
"word/theme/theme1.xml",
|
||||
"word/fontTable.xml",
|
||||
"word/settings.xml",
|
||||
"word/styles.xml",
|
||||
"word/webSettings.xml",
|
||||
"[Content_Types].xml",
|
||||
},
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
@@ -12,6 +32,8 @@ type WordprocessingCanvas struct {
|
||||
Whole *WPCWhole
|
||||
|
||||
Items []interface{}
|
||||
|
||||
file *Docx
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
@@ -40,7 +62,8 @@ func (c *WordprocessingCanvas) UnmarshalXML(d *xml.Decoder, start xml.StartEleme
|
||||
return err
|
||||
}
|
||||
case "wsp":
|
||||
var value WPSWordprocessingShape
|
||||
var value WordprocessingShape
|
||||
value.file = c.file
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
|
||||
@@ -44,6 +44,8 @@ type Drawing struct {
|
||||
XMLName xml.Name `xml:"w:drawing,omitempty"`
|
||||
Inline *WPInline
|
||||
Anchor *WPAnchor
|
||||
|
||||
file *Docx
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
@@ -61,12 +63,14 @@ func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
switch tt.Name.Local {
|
||||
case "inline":
|
||||
r.Inline = new(WPInline)
|
||||
r.Inline.file = r.file
|
||||
err = d.DecodeElement(r.Inline, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "anchor":
|
||||
r.Anchor = new(WPAnchor)
|
||||
r.Anchor.file = r.file
|
||||
err = d.DecodeElement(r.Anchor, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
@@ -105,6 +109,8 @@ type WPInline struct {
|
||||
DocPr *WPDocPr
|
||||
CNvGraphicFramePr *WPCNvGraphicFramePr
|
||||
Graphic *AGraphic
|
||||
|
||||
file *Docx
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
@@ -191,6 +197,7 @@ func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err err
|
||||
r.CNvGraphicFramePr = &value
|
||||
case "graphic":
|
||||
var value AGraphic
|
||||
value.file = r.file
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
@@ -360,6 +367,8 @@ type AGraphic struct {
|
||||
XMLName xml.Name `xml:"a:graphic,omitempty"`
|
||||
XMLA string `xml:"xmlns:a,attr,omitempty"`
|
||||
GraphicData *AGraphicData
|
||||
|
||||
file *Docx
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
@@ -385,6 +394,7 @@ func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
switch tt.Name.Local {
|
||||
case "graphicData":
|
||||
var value AGraphicData
|
||||
value.file = a.file
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
@@ -407,8 +417,11 @@ func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
type AGraphicData struct {
|
||||
XMLName xml.Name `xml:"a:graphicData,omitempty"`
|
||||
URI string `xml:"uri,attr"`
|
||||
Pic *PICPic
|
||||
Shape *WPSWordprocessingShape
|
||||
Pic *Picture
|
||||
Shape *WordprocessingShape
|
||||
Canvas *WordprocessingCanvas
|
||||
|
||||
file *Docx
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
@@ -425,7 +438,7 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
|
||||
if tt, ok := t.(xml.StartElement); ok {
|
||||
switch tt.Name.Local {
|
||||
case "pic":
|
||||
var value PICPic
|
||||
var value Picture
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
@@ -433,12 +446,21 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
|
||||
value.XMLPIC = getAtt(tt.Attr, "pic")
|
||||
a.Pic = &value
|
||||
case "wsp":
|
||||
var value WPSWordprocessingShape
|
||||
var value WordprocessingShape
|
||||
value.file = a.file
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
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:
|
||||
err = d.Skip() // skip unsupported tags
|
||||
if err != nil {
|
||||
@@ -451,8 +473,8 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
// PICPic represents a picture in a Word document.
|
||||
type PICPic struct {
|
||||
// Picture represents a picture in a Word document.
|
||||
type Picture struct {
|
||||
XMLName xml.Name `xml:"pic:pic,omitempty"`
|
||||
XMLPIC string `xml:"xmlns:pic,attr,omitempty"`
|
||||
NonVisualPicProperties *PICNonVisualPicProperties
|
||||
@@ -461,7 +483,7 @@ type PICPic struct {
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
func (p *PICPic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
func (p *Picture) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err == io.EOF {
|
||||
@@ -649,7 +671,7 @@ func (p *PICBlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
||||
type ABlip struct {
|
||||
XMLName xml.Name `xml:"a:blip,omitempty"`
|
||||
Embed string `xml:"r:embed,attr"`
|
||||
Cstate string `xml:"cstate,attr"`
|
||||
Cstate string `xml:"cstate,attr,omitempty"`
|
||||
AlphaModFix *AAlphaModFix
|
||||
}
|
||||
|
||||
@@ -934,6 +956,8 @@ type WPAnchor struct {
|
||||
DocPr *WPDocPr
|
||||
CNvGraphicFramePr *WPCNvGraphicFramePr
|
||||
Graphic *AGraphic
|
||||
|
||||
file *Docx
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
@@ -1061,6 +1085,7 @@ func (r *WPAnchor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err err
|
||||
}
|
||||
case "graphic":
|
||||
r.Graphic = new(AGraphic)
|
||||
r.Graphic.file = r.file
|
||||
err = d.DecodeElement(&r.Graphic, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
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
|
||||
|
||||
import "encoding/xml"
|
||||
@@ -27,6 +47,12 @@ type Size struct {
|
||||
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 ...
|
||||
type Bold struct {
|
||||
XMLName xml.Name `xml:"w:b,omitempty"`
|
||||
@@ -52,7 +78,7 @@ type Highlight struct {
|
||||
// Kern ...
|
||||
type Kern struct {
|
||||
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
|
||||
@@ -68,6 +94,18 @@ type Justification struct {
|
||||
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.
|
||||
type Shade struct {
|
||||
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()
|
||||
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>
|
||||
type ParagraphProperties struct {
|
||||
XMLName xml.Name `xml:"w:pPr,omitempty"`
|
||||
Justification *Justification
|
||||
Shade *Shade
|
||||
Kern *Kern
|
||||
XMLName xml.Name `xml:"w:pPr,omitempty"`
|
||||
Justification *Justification
|
||||
Shade *Shade
|
||||
Kern *Kern
|
||||
Style *Style
|
||||
TextAlignment *TextAlignment
|
||||
AdjustRightInd *AdjustRightInd
|
||||
SnapToGrid *SnapToGrid
|
||||
Kinsoku *Kinsoku
|
||||
OverflowPunct *OverflowPunct
|
||||
|
||||
RunProperties *RunProperties
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
@@ -69,6 +77,61 @@ func (p *ParagraphProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
|
||||
return err
|
||||
}
|
||||
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:
|
||||
err = d.Skip() // skip unsupported tags
|
||||
if err != nil {
|
||||
@@ -177,27 +240,6 @@ func (p *Paragraph) String() 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 ...
|
||||
func (p *Paragraph) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
for _, attr := range start.Attr {
|
||||
@@ -243,6 +285,7 @@ func (p *Paragraph) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
elem = &value
|
||||
case "r":
|
||||
var value Run
|
||||
value.file = p.file
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
|
||||
@@ -47,16 +47,6 @@ func TestRelationships(t *testing.T) {
|
||||
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable`,
|
||||
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")
|
||||
@@ -69,7 +59,7 @@ func TestRelationships(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m := hex.EncodeToString(h.Sum(make([]byte, 0, 16)))
|
||||
if m != "c75af73ef6cc9536a193669c4a3605c3" {
|
||||
if m != "62c753dc14365fce007fc4c7c3bd0c82" {
|
||||
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
|
||||
type Run struct {
|
||||
XMLName xml.Name `xml:"w:r,omitempty"`
|
||||
RsidRPr string `xml:"w:rsidRPr,attr,omitempty"`
|
||||
|
||||
RunProperties *RunProperties `xml:"w:rPr,omitempty"`
|
||||
|
||||
InstrText string `xml:"w:instrText,omitempty"`
|
||||
|
||||
Children []interface{}
|
||||
|
||||
file *Docx
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
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 {
|
||||
t, err := d.Token()
|
||||
if err == io.EOF {
|
||||
@@ -91,6 +102,7 @@ func (r *Run) parse(d *xml.Decoder, tt xml.StartElement) (child interface{}, err
|
||||
child = &value
|
||||
case "drawing":
|
||||
var value Drawing
|
||||
value.file = r.file
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
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" {
|
||||
for _, attr := range ttt.Attr {
|
||||
if attr.Name.Local == "Requires" {
|
||||
if attr.Value == "wps" {
|
||||
child, err = r.parse(d, ttt)
|
||||
if attr.Value == "wps" || attr.Value == "wpc" {
|
||||
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
|
||||
@@ -141,15 +159,18 @@ type RunProperties struct {
|
||||
XMLName xml.Name `xml:"w:rPr,omitempty"`
|
||||
Fonts *RunFonts
|
||||
Bold *Bold
|
||||
ICs *struct{} `xml:"w:iCs,omitempty"`
|
||||
Italic *Italic
|
||||
Underline *Underline
|
||||
Highlight *Highlight
|
||||
Color *Color
|
||||
Size *Size
|
||||
SizeCs *SizeCs
|
||||
RunStyle *RunStyle
|
||||
Style *Style
|
||||
Shade *Shade
|
||||
Kern *Kern
|
||||
VertAlign *VertAlign
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
@@ -174,6 +195,8 @@ func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
|
||||
r.Fonts = &value
|
||||
case "b":
|
||||
r.Bold = &Bold{}
|
||||
case "iCs":
|
||||
r.ICs = &struct{}{}
|
||||
case "i":
|
||||
r.Italic = &Italic{}
|
||||
case "u":
|
||||
@@ -192,6 +215,10 @@ func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
|
||||
var value Size
|
||||
value.Val = getAtt(tt.Attr, "val")
|
||||
r.Size = &value
|
||||
case "szCs":
|
||||
var value SizeCs
|
||||
value.Val = getAtt(tt.Attr, "val")
|
||||
r.SizeCs = &value
|
||||
case "rStyle":
|
||||
var value RunStyle
|
||||
value.Val = getAtt(tt.Attr, "val")
|
||||
@@ -218,6 +245,10 @@ func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
|
||||
return err
|
||||
}
|
||||
r.Kern = &value
|
||||
case "vertAlign":
|
||||
var value VertAlign
|
||||
value.Val = getAtt(tt.Attr, "val")
|
||||
r.VertAlign = &value
|
||||
default:
|
||||
err = d.Skip() // skip unsupported tags
|
||||
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
|
||||
|
||||
import (
|
||||
@@ -7,16 +27,21 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// WPSWordprocessingShape is a container for a WordprocessingML DrawingML shape.
|
||||
type WPSWordprocessingShape struct {
|
||||
// WordprocessingShape is a container for a WordprocessingML DrawingML shape.
|
||||
type WordprocessingShape struct {
|
||||
XMLName xml.Name `xml:"wps:wsp,omitempty"`
|
||||
CNvPr *WPSCNvPr
|
||||
CNvCnPr *WPSCNvCnPr
|
||||
CNvSpPr *WPSCNvSpPr
|
||||
SpPr *WPSSpPr
|
||||
TextBox *WPSTextBox
|
||||
BodyPr *WPSBodyPr
|
||||
|
||||
file *Docx
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
func (w *WPSWordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
func (w *WordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
for {
|
||||
t, err := d.Token()
|
||||
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 {
|
||||
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":
|
||||
w.CNvCnPr = new(WPSCNvCnPr)
|
||||
err = d.DecodeElement(w.CNvCnPr, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
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":
|
||||
w.SpPr = new(WPSSpPr)
|
||||
err = d.DecodeElement(w.SpPr, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
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":
|
||||
w.BodyPr = new(WPSBodyPr)
|
||||
err = d.DecodeElement(w.BodyPr, &tt)
|
||||
@@ -57,6 +102,33 @@ func (w *WPSWordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartEle
|
||||
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.
|
||||
type WPSCNvCnPr struct {
|
||||
XMLName xml.Name `xml:"wps:cNvCnPr,omitempty"`
|
||||
@@ -90,15 +162,76 @@ func (w *WPSCNvCnPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
||||
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.
|
||||
type WPSSpPr struct {
|
||||
XMLName xml.Name `xml:"wps:spPr,omitempty"`
|
||||
BWMode string `xml:"bwMode,attr"`
|
||||
|
||||
Xfrm AXfrm
|
||||
PrstGeom APrstGeom
|
||||
NoFill *struct{} `xml:"a:noFill,omitempty"`
|
||||
Elems []interface{}
|
||||
Xfrm AXfrm
|
||||
PrstGeom APrstGeom
|
||||
SolidFill *ASolidFill
|
||||
BlipFill *ABlipFill
|
||||
NoFill *struct{} `xml:"a:noFill,omitempty"`
|
||||
Line *ALine
|
||||
|
||||
EffectList struct{} `xml:"a:effectLst"`
|
||||
ExtList struct{} `xml:"a:extLst"`
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
@@ -129,6 +262,20 @@ func (w *WPSSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
}
|
||||
case "prstGeom":
|
||||
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":
|
||||
w.NoFill = &struct{}{}
|
||||
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") {
|
||||
return err
|
||||
}
|
||||
w.Elems = append(w.Elems, &ln)
|
||||
w.Line = &ln
|
||||
default:
|
||||
err = d.Skip() // skip unsupported tags
|
||||
if err != nil {
|
||||
@@ -150,14 +297,137 @@ func (w *WPSSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
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.
|
||||
type ALine struct {
|
||||
XMLName xml.Name `xml:"a:ln,omitempty"`
|
||||
W int64 `xml:"w,attr"`
|
||||
W int64 `xml:"w,attr,omitempty"`
|
||||
Cap string `xml:"cap,attr,omitempty"`
|
||||
Compound string `xml:"cmpd,attr,omitempty"`
|
||||
Align string `xml:"algn,attr,omitempty"`
|
||||
|
||||
NoFill *struct{} `xml:"a:noFill,omitempty"`
|
||||
SolidFill *ASolidFill
|
||||
PrstDash *APrstDash
|
||||
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 {
|
||||
switch tt.Name.Local {
|
||||
case "noFill":
|
||||
l.NoFill = &struct{}{}
|
||||
case "solidFill":
|
||||
l.SolidFill = new(ASolidFill)
|
||||
err = d.DecodeElement(l.SolidFill, &tt)
|
||||
@@ -351,7 +623,156 @@ func (r *ATailEnd) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
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.
|
||||
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
|
||||
|
||||
import (
|
||||
@@ -13,8 +33,8 @@ func TestShapeStructure(t *testing.T) {
|
||||
// add new paragraph
|
||||
para1 := w.AddParagraph()
|
||||
// add text
|
||||
para1.AddText("test shape")
|
||||
para1.AddShape(808355, 238760, "AutoShape", "auto", "straightConnector1", []interface{}{
|
||||
para1.AddText("test anchor shape")
|
||||
para1.AddAnchorShape(808355, 238760, "AutoShape", "auto", "straightConnector1",
|
||||
&ALine{
|
||||
W: 9525,
|
||||
SolidFill: &ASolidFill{SrgbClr: &ASrgbClr{Val: "000000"}},
|
||||
@@ -22,7 +42,19 @@ func TestShapeStructure(t *testing.T) {
|
||||
HeadEnd: &AHeadEnd{},
|
||||
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")
|
||||
if err != nil {
|
||||
|
||||
@@ -51,11 +51,11 @@ func (t *WTable) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
switch tt.Name.Local {
|
||||
case "tr":
|
||||
var value WTableRow
|
||||
value.file = t.file
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
value.file = t.file
|
||||
t.TableRows = append(t.TableRows, &value)
|
||||
case "tblPr":
|
||||
t.TableProperties = new(WTableProperties)
|
||||
@@ -421,11 +421,11 @@ func (w *WTableRow) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
}
|
||||
case "tc":
|
||||
var value WTableCell
|
||||
value.file = w.file
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
value.file = w.file
|
||||
w.TableCells = append(w.TableCells, &value)
|
||||
default:
|
||||
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.
|
||||
type WTableRowHeight struct {
|
||||
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"`
|
||||
}
|
||||
|
||||
@@ -565,9 +565,9 @@ type WTableCellProperties struct {
|
||||
TableCellWidth *WTableCellWidth
|
||||
VMerge *WvMerge
|
||||
GridSpan *WGridSpan
|
||||
VAlign *WVerticalAlignment
|
||||
TableBorders *WTableBorders `xml:"w:tcBorders"`
|
||||
Shade *Shade
|
||||
VAlign *WVerticalAlignment
|
||||
}
|
||||
|
||||
// UnmarshalXML ...
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
<Default Extension="xml" ContentType="application/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/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/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+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