Skip to content

Commit

Permalink
Merge pull request #34 from gomutex/comments-update
Browse files Browse the repository at this point in the history
doc update and moved API funcs of Run to docx
  • Loading branch information
gomutex authored Jun 28, 2024
2 parents 9a0aaf6 + ecd8b34 commit 57dfdbe
Show file tree
Hide file tree
Showing 18 changed files with 421 additions and 248 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import (

func main() {
// Open an existing DOCX document
// docx, err := godocx.OpenDocument("./testdata/test.docx")
// document, err := godocx.OpenDocument("./testdata/test.docx")

// Create New Document
document, err := godocx.NewDocument()
Expand Down
4 changes: 4 additions & 0 deletions dml/dmlct/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Package dmlct provides complex types related to DrawingML (Drawing Markup Language),
// which is part of the Office Open XML (OOXML) standard. DrawingML is used to represent
// graphics and drawings in WordprocessingML, SpreadsheetML, and PresentationML documents.
package dmlct
4 changes: 4 additions & 0 deletions dml/dmlst/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Package dml provides simple types used in DrawingML (Drawing Markup Language),
// part of the Office Open XML (OOXML) standard for representing graphical elements
// in documents.
package dmlst
4 changes: 4 additions & 0 deletions dml/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Package dml provides functionality for working with DrawingML (Drawing Markup Language)
// which is part of the Office Open XML (OOXML) standard. DrawingML is used to represent
// graphics and drawings in WordprocessingML, SpreadsheetML, and PresentationML documents.
package dml
16 changes: 8 additions & 8 deletions docx/body.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

// This element specifies the contents of the body of the document – the main document editing surface.
type Body struct {
Root *RootDoc
root *RootDoc
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main body"`
Children []DocumentChild
SectPr *ctypes.SectionProp
Expand All @@ -23,7 +23,7 @@ type DocumentChild struct {
// Use this function to initialize a new Body before adding content to it.
func NewBody(root *RootDoc) *Body {
return &Body{
Root: root,
root: root,
}
}

Expand All @@ -40,13 +40,13 @@ func (b Body) MarshalXML(e *xml.Encoder, start xml.StartElement) (err error) {
if b.Children != nil {
for _, child := range b.Children {
if child.Para != nil {
if err = child.Para.CT.MarshalXML(e, xml.StartElement{}); err != nil {
if err = child.Para.ct.MarshalXML(e, xml.StartElement{}); err != nil {
return err
}
}

if child.Table != nil {
if err = child.Table.CT.MarshalXML(e, xml.StartElement{}); err != nil {
if err = child.Table.ct.MarshalXML(e, xml.StartElement{}); err != nil {
return err
}
}
Expand Down Expand Up @@ -76,14 +76,14 @@ func (body *Body) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err erro
case xml.StartElement:
switch elem.Name.Local {
case "p":
para := NewParagraph(body.Root)
if err := d.DecodeElement(&para.CT, &elem); err != nil {
para := newParagraph(body.root)
if err := d.DecodeElement(&para.ct, &elem); err != nil {
return err
}
body.Children = append(body.Children, DocumentChild{Para: para})
case "tbl":
tbl := NewTable(body.Root)
if err := d.DecodeElement(&tbl.CT, &elem); err != nil {
tbl := NewTable(body.root)
if err := d.DecodeElement(&tbl.ct, &elem); err != nil {
return err
}
body.Children = append(body.Children, DocumentChild{Table: tbl})
Expand Down
2 changes: 0 additions & 2 deletions docx/core.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// Package oxml provides utilities for working with Office Open XML (OOXML) documents,
// including functions related to encoding and decoding XML elements.
package docx

import (
Expand Down
11 changes: 11 additions & 0 deletions docx/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Package docx provides a comprehensive set of functions and structures
// for manipulating DOCX documents. It allows for the creation, modification,
// and retrieval of document elements such as paragraphs, styles, and images.
// The package is designed to be accessed through the RootDoc element or
// instances of inner elements, providing a flexible and intuitive API for
// working with Office Open XML (OOXML) documents.
//
// // The RootDoc structure is initialized from the main godocx package,
// which provides methods for creating a new document from a default template or
// opening an existing document.
package docx
10 changes: 9 additions & 1 deletion docx/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,15 @@ func (d *Document) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement) (e

}

// Return newly Paragraph object containing only a page break.
// AddPageBreak adds a page break to the document by inserting a paragraph containing only a page break.
//
// Returns:
// - *Paragraph: A pointer to the newly created Paragraph object containing the page break.
//
// Example:
//
// document := godocx.NewDocument()
// para := document.AddPageBreak()
func (rd *RootDoc) AddPageBreak() *Paragraph {
p := rd.AddEmptyParagraph()
p.AddRun().AddBreak(internal.ToPtr(stypes.BreakTypePage))
Expand Down
6 changes: 3 additions & 3 deletions docx/heading.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ func (rd *RootDoc) AddHeading(text string, level uint) (*Paragraph, error) {
return nil, errors.New("Heading level not supported")
}

p := NewParagraph(rd)
p.CT.Property = ctypes.DefaultParaProperty()
p := newParagraph(rd)
p.ct.Property = ctypes.DefaultParaProperty()

style := "Title"
if level != 0 {
style = fmt.Sprintf("Heading%d", level)
}

p.CT.Property.Style = ctypes.NewParagraphStyle(style)
p.ct.Property.Style = ctypes.NewParagraphStyle(style)

bodyElem := DocumentChild{
Para: p,
Expand Down
21 changes: 21 additions & 0 deletions docx/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ import (
"github.com/gomutex/godocx/common/constants"
)

// addLinkRelation adds a hyperlink relationship to the document's relationships collection.
//
// Parameters:
// - link: A string representing the target URL or location of the hyperlink.
//
// Returns:
// - string: The ID ("rId" + relation ID) of the added relationship.
//
// This function generates a new relationship ID, creates a Relationship object with the specified link as the target,
// and appends it to the document's relationships collection (DocRels.Relationships). It returns the generated ID of the relationship.
func (doc *Document) addLinkRelation(link string) string {

rID := doc.IncRelationID()
Expand All @@ -22,6 +32,17 @@ func (doc *Document) addLinkRelation(link string) string {
return "rId" + strconv.Itoa(rID)
}

// addRelation adds a generic relationship to the document's relationships collection.
//
// Parameters:
// - relType: A string representing the type of relationship (e.g., constants.SourceRelationshipImage).
// - fileName: A string representing the target file name or location related to the relationship.
//
// Returns:
// - string: The ID ("rId" + relation ID) of the added relationship.
//
// This function generates a new relationship ID, creates a Relationship object with the specified type and target,
// and appends it to the document's relationships collection (DocRels.Relationships). It returns the generated ID of the relationship.
func (doc *Document) addRelation(relType string, fileName string) string {
rID := doc.IncRelationID()
rel := &Relationship{
Expand Down
130 changes: 72 additions & 58 deletions docx/paragraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,22 @@ import (
"github.com/gomutex/godocx/wml/stypes"
)

// Paragraph represents a paragraph in a DOCX document.
type Paragraph struct {
// Reverse inheriting the Rootdoc into Paragrah to access other elements
Root *RootDoc

// Paragraph Complex Type
CT ctypes.Paragraph
root *RootDoc // root is a reference to the root document.
ct ctypes.Paragraph // ct holds the underlying Paragraph Complex Type.
}

func NewParagraph(root *RootDoc) *Paragraph {
// newParagraph creates and initializes a new Paragraph instance.
func newParagraph(root *RootDoc) *Paragraph {
return &Paragraph{
Root: root,
root: root,
}
}

func NewParagraphChild() *ctypes.ParagraphChild {
return &ctypes.ParagraphChild{}
}

func DefaultParagraphChild() *ctypes.ParagraphChild {
return &ctypes.ParagraphChild{}
// GetCT returns a pointer to the underlying Paragraph Complex Type.
func (p *Paragraph) GetCT() *ctypes.Paragraph {
return &p.ct
}

// AddParagraph adds a new paragraph with the specified text to the document.
Expand All @@ -43,7 +39,7 @@ func DefaultParagraphChild() *ctypes.ParagraphChild {
// Returns:
// - p: The created Paragraph instance.
func (rd *RootDoc) AddParagraph(text string) *Paragraph {
p := NewParagraph(rd)
p := newParagraph(rd)
p.AddText(text)
bodyElem := DocumentChild{
Para: p,
Expand All @@ -58,59 +54,62 @@ func (rd *RootDoc) AddParagraph(text string) *Paragraph {
// Parameters:
// - value: A string representing the style value. It can be any valid style defined in the WordprocessingML specification.
//
// Returns:
// - *Paragraph: A pointer to the modified Paragraph instance with the updated style.
//
// Example:
//
// p1 := docx.AddParagraph("Example para")
// p1 := document.AddParagraph("Example para")
// paragraph.Style("List Number")
func (p *Paragraph) Style(value string) {
if p.CT.Property == nil {
p.CT.Property = ctypes.DefaultParaProperty()
if p.ct.Property == nil {
p.ct.Property = ctypes.DefaultParaProperty()
}
p.CT.Property.Style = ctypes.NewParagraphStyle(value)
p.ct.Property.Style = ctypes.NewParagraphStyle(value)
}

// Justification sets the paragraph justification type.
//
// Parameters:
// - value: A string representing the justification value. It can be one of the following:
// - "left" for left justification
// - "center" for center justification
// - "right" for right justification
// - "both" for justification with equal spacing on both sides
// - "distribute": Paragraph characters are distributed to fill the entire width of paragraph
// - value: A value of type stypes.Justification representing the justification type.
// It can be one of the Justification type values defined in the stypes package.
//
// Returns:
// - *Paragraph: A pointer to the modified Paragraph instance with the updated justification.

func (p *Paragraph) Justification(value string) error {
if p.CT.Property == nil {
p.CT.Property = ctypes.DefaultParaProperty()
}

val, err := stypes.JustificationFromStr(value)
if err != nil {
return err
// Example:
//
// p1 := document.AddParagraph("Example justified para")
// p1.Justification(stypes.JustificationCenter) // Center justification
func (p *Paragraph) Justification(value stypes.Justification) {
if p.ct.Property == nil {
p.ct.Property = ctypes.DefaultParaProperty()
}

p.CT.Property.Justification = ctypes.NewGenSingleStrVal(val)

return nil
p.ct.Property.Justification = ctypes.NewGenSingleStrVal(value)
}

// Numbering sets the paragraph numbering properties.
//
// This function assigns a numbering definition ID and a level to the paragraph,
// which affects how numbering is displayed in the document.
//
// Parameters:
// - id: An integer representing the numbering definition ID.
// - level: An integer representing the level within the numbering definition.
//
// Example:
//
// p1 := document.AddParagraph("Example numbered para")
// p1.Numbering(1, 0)
//
// In this example, the paragraph p1 is assigned the numbering properties
// defined by numbering definition ID 1 and level 0.
func (p Paragraph) Numbering(id int, level int) {

if p.CT.Property == nil {
p.CT.Property = ctypes.DefaultParaProperty()
if p.ct.Property == nil {
p.ct.Property = ctypes.DefaultParaProperty()
}

if p.CT.Property.NumProp == nil {
p.CT.Property.NumProp = &ctypes.NumProp{}
if p.ct.Property.NumProp == nil {
p.ct.Property.NumProp = &ctypes.NumProp{}
}
p.CT.Property.NumProp.NumID = ctypes.NewDecimalNum(id)
p.CT.Property.NumProp.ILvl = ctypes.NewDecimalNum(level)
p.ct.Property.NumProp.NumID = ctypes.NewDecimalNum(id)
p.ct.Property.NumProp.ILvl = ctypes.NewDecimalNum(level)
}

// Appends a new text to the Paragraph.
Expand All @@ -124,7 +123,7 @@ func (p Paragraph) Numbering(id int, level int) {
//
// Returns:
// - *Run: The newly created Run instance added to the Paragraph.
func (p *Paragraph) AddText(text string) *ctypes.Run {
func (p *Paragraph) AddText(text string) *Run {
t := ctypes.TextFromString(text)

runChildren := []ctypes.RunChild{}
Expand All @@ -135,9 +134,9 @@ func (p *Paragraph) AddText(text string) *ctypes.Run {
Children: runChildren,
}

p.CT.Children = append(p.CT.Children, ctypes.ParagraphChild{Run: run})
p.ct.Children = append(p.ct.Children, ctypes.ParagraphChild{Run: run})

return run
return newRun(p.root, run)
}

// AddEmptyParagraph adds a new empty paragraph to the document.
Expand All @@ -146,7 +145,7 @@ func (p *Paragraph) AddText(text string) *ctypes.Run {
// Returns:
// - p: The created Paragraph instance.
func (rd *RootDoc) AddEmptyParagraph() *Paragraph {
p := NewParagraph(rd)
p := newParagraph(rd)

bodyElem := DocumentChild{
Para: p,
Expand All @@ -156,13 +155,13 @@ func (rd *RootDoc) AddEmptyParagraph() *Paragraph {
return p
}

func (p *Paragraph) AddRun() *ctypes.Run {
func (p *Paragraph) AddRun() *Run {

run := &ctypes.Run{}

p.CT.Children = append(p.CT.Children, ctypes.ParagraphChild{Run: run})
p.ct.Children = append(p.ct.Children, ctypes.ParagraphChild{Run: run})

return run
return newRun(p.root, run)
}

// func (p *Paragraph) AddLink(text string, link string) *Hyperlink {
Expand Down Expand Up @@ -195,7 +194,17 @@ func (p *Paragraph) AddRun() *ctypes.Run {
// return hyperLink
// }

func (p *Paragraph) AddDrawing(rID string, imgCount uint, width units.Inch, height units.Inch) *dml.Inline {
// AddDrawing adds a new drawing (image) to the Paragraph.
//
// Parameters:
// - rID: The relationship ID of the image in the document.
// - imgCount: The count of images in the document.
// - width: The width of the image in inches.
// - height: The height of the image in inches.
//
// Returns:
// - *dml.Inline: The created Inline instance representing the added drawing.
func (p *Paragraph) addDrawing(rID string, imgCount uint, width units.Inch, height units.Inch) *dml.Inline {
eWidth := width.ToEmu()
eHeight := height.ToEmu()

Expand All @@ -221,17 +230,22 @@ func (p *Paragraph) AddDrawing(rID string, imgCount uint, width units.Inch, heig
Children: runChildren,
}

p.CT.Children = append(p.CT.Children, ctypes.ParagraphChild{Run: run})
p.ct.Children = append(p.ct.Children, ctypes.ParagraphChild{Run: run})

return &inline
}

// GetStyle retrieves the style information applied to the Paragraph.
//
// Returns:
// - *ctypes.Style: The style information of the Paragraph.
// - error: An error if the style information is not found.
func (p *Paragraph) GetStyle() (*ctypes.Style, error) {
if p.CT.Property == nil || p.CT.Property.Style == nil {
if p.ct.Property == nil || p.ct.Property.Style == nil {
return nil, errors.New("No property for the style")
}

style := p.Root.GetStyleByID(p.CT.Property.Style.Val, stypes.StyleTypeParagraph)
style := p.root.GetStyleByID(p.ct.Property.Style.Val, stypes.StyleTypeParagraph)
if style == nil {
return nil, errors.New("No style found for the paragraph")
}
Expand Down
Loading

0 comments on commit 57dfdbe

Please sign in to comment.