Documentation
¶
Overview ¶
Package ooxml provides the preservation-first representation used by the renderer. It deliberately models XML rather than a subset of WordprocessingML.
Index ¶
- Constants
- Variables
- func AdaptOfficeRelationshipType(relationshipType, namespace string) string
- func AdaptOfficeRelationshipsNamespace(nodes []*Node, namespace string)
- func AdaptWordprocessingNamespace(nodes []*Node, namespace string)
- func CanonicalPartName(name string) string
- func DeclareUsedNamespaces(nodes []*Node)
- func IsOfficeRelationshipsNamespace(namespace string) bool
- func IsSemanticNonTextParagraphContent(node *Node) bool
- func IsWordprocessingMLNamespace(namespace string) bool
- func Marshal(root *Node) ([]byte, error)
- func NormalizeRevisions(root *Node) bool
- func PreflightPackageWithLimits(data []byte, limits PackageLimits) error
- func RejectDigitalSignaturesWithLimits(data []byte, limits PackageLimits) error
- func SemanticEqual(left, right *Node) bool
- func StoryRelationshipsNamespace(root *Node) string
- func ValidatePackage(data []byte) error
- func ValidatePackageWithLimits(data []byte, limits PackageLimits) error
- func WordprocessingNamespace(root *Node) string
- type Attribute
- type DigitalSignatureError
- type Name
- type Node
- type NodeIndex
- type NodeKind
- type NodeLocation
- type Package
- func (p *Package) AddBinaryPart(name string, content []byte) (*Part, error)
- func (p *Package) AddXMLPart(name string, tree *Node) (*Part, error)
- func (p *Package) CloneForRender(mutableParts map[string]bool) (*Package, map[string]*NodeIndex)
- func (p *Package) DeepClone() *Package
- func (p *Package) DeepCloneWithIndexes() (*Package, map[string]*NodeIndex)
- func (p *Package) EffectiveContentType(partName string) (string, error)
- func (p *Package) EnsureContentType(partName, contentType string) error
- func (p *Package) EnsureContentTypeDefault(partName string) error
- func (p *Package) EnsureContentTypeOverride(partName, contentType string) error
- func (p *Package) Marshal() ([]byte, error)
- func (p *Package) Part(name string) (*Part, bool)
- func (p *Package) Relationships(sourcePart string) (*RelationshipSet, error)
- func (p *Package) ReplacePart(name string, content []byte) (*Part, error)
- func (p *Package) StoryPartNames() []string
- type PackageLimits
- type PackageValidationError
- type Paragraph
- type Part
- type RelationshipSet
- type Story
- type TemplateSpan
- type TextPosition
- type TextReference
- type UniqueIDAllocator
- func (a *UniqueIDAllocator) AdoptOneToOneStructuralRange(nodes []*Node) error
- func (a *UniqueIDAllocator) AdoptStructuralRange(nodes []*Node) error
- func (a *UniqueIDAllocator) CloneStructuralRange(nodes []*Node) ([]*Node, error)
- func (a *UniqueIDAllocator) CloneStructuralRangeWithIndex(nodes []*Node) ([]*Node, *NodeIndex, error)
- func (a *UniqueIDAllocator) ReserveNodeIDFloor(floor uint64)
- type ValidationIssue
- type XMLPathStep
Constants ¶
const ( WordDrawingNamespace = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" DrawingNamespace = "http://schemas.openxmlformats.org/drawingml/2006/main" PictureNamespace = "http://schemas.openxmlformats.org/drawingml/2006/picture" Word2010Namespace = "http://schemas.microsoft.com/office/word/2010/wordml" Word2010DrawingNamespace = "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" )
const ( // The defaults are deliberately conservative for server-side template // processing. Callers which intentionally handle larger packages can use // OpenPackageWithLimits with application-specific values. DefaultMaxPackageEntries = 4096 DefaultMaxXMLPartBytes = 64 << 20 DefaultMaxMaterializedPartBytes = 256 << 20 DefaultMaxMaterializedTotalBytes = 512 << 20 DefaultMaxPackageOutputBytes = 512 << 20 DefaultMaxXMLNodes = 1_000_000 DefaultMaxXMLAttributes = 2_000_000 DefaultMaxXMLTextBytes = 128 << 20 DefaultMaxXMLDepth = 1024 )
const ( XMLNamespace = "http://www.w3.org/XML/1998/namespace" XMLNSNamespace = "http://www.w3.org/2000/xmlns/" WordNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" // StrictWordNamespace is the ISO/IEC 29500 Strict WordprocessingML // namespace. V2 treats Strict and Transitional Word nodes equivalently for // semantic matching while retaining their original namespace declarations. StrictWordNamespace = "http://purl.oclc.org/ooxml/wordprocessingml/main" )
const ( PackageRelationshipsNamespace = "http://schemas.openxmlformats.org/package/2006/relationships" HyperlinkRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" )
const ContentTypesNamespace = "http://schemas.openxmlformats.org/package/2006/content-types"
const OfficeRelationshipsNamespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
const StrictOfficeRelationshipsNamespace = "http://purl.oclc.org/ooxml/officeDocument/relationships"
Variables ¶
var ErrDigitalSignatureUnsupported = errors.New("OPC digital signatures are not supported")
ErrDigitalSignatureUnsupported reports an OPC package carrying digital signature metadata. go-stencil deliberately fails closed because rendering can invalidate package signatures and it does not perform cryptographic signature verification.
var ErrNotZIPPackage = errors.New("not a ZIP package")
ErrNotZIPPackage reports that input contains no ZIP container signature or end-of-central-directory record. Other errors from PreflightPackageWithLimits describe a ZIP-shaped package that is invalid or exceeds configured limits.
Functions ¶
func AdaptOfficeRelationshipType ¶
AdaptOfficeRelationshipType aligns an office-document relationship type URI with a destination Strict/Transitional relationship namespace.
func AdaptOfficeRelationshipsNamespace ¶
AdaptOfficeRelationshipsNamespace aligns detached relationship-bearing attributes with the concrete Strict/Transitional profile of a story.
func AdaptWordprocessingNamespace ¶
AdaptWordprocessingNamespace makes detached nodes conform to the concrete Strict/Transitional profile of their destination story. Lexical prefixes are retained; explicit namespace declarations are updated with the nodes.
func CanonicalPartName ¶
CanonicalPartName returns the comparison key used by OPC package lookups. OPC part names are ASCII-case-insensitive; the fixed [Content_Types].xml package item remains case-sensitive because it is not an ordinary part.
func DeclareUsedNamespaces ¶
func DeclareUsedNamespaces(nodes []*Node)
DeclareUsedNamespaces makes each top-level element self-contained after it is detached from its original XML document and inserted into another part.
func IsOfficeRelationshipsNamespace ¶
IsOfficeRelationshipsNamespace reports whether namespace is either the Transitional or Strict office-document relationships namespace.
func IsSemanticNonTextParagraphContent ¶
IsSemanticNonTextParagraphContent reports whether an element carries paragraph content that is not represented by a visible w:t node. Besides reference/range markers, this covers the complete semantic EG_RunInnerContent family. Property and wrapper elements deliberately do not qualify on their own; their descendants are inspected independently.
func IsWordprocessingMLNamespace ¶
IsWordprocessingMLNamespace reports whether namespace is either the Transitional or Strict WordprocessingML namespace.
func Marshal ¶
Marshal serializes the stored lexical names and attribute order. It does not pretty-print because whitespace is meaningful in Word text nodes.
func NormalizeRevisions ¶
NormalizeRevisions accepts tracked revisions in-place. Insertions and move-to ranges are promoted, deletions and move-from ranges are removed, and property change histories are discarded. The function reports whether it changed the tree.
func PreflightPackageWithLimits ¶
func PreflightPackageWithLimits(data []byte, limits PackageLimits) error
PreflightPackageWithLimits validates the ZIP directory and cheap OPC metadata before callers enter archive/zip or decompress any part. It is intended for lazy package detection paths which must retain deferred XML parsing while still enforcing entry, output and declared XML-size limits.
func RejectDigitalSignaturesWithLimits ¶
func RejectDigitalSignaturesWithLimits(data []byte, limits PackageLimits) error
RejectDigitalSignaturesWithLimits inspects only package names, content-type metadata, and relationship metadata. It does not validate a signature and never removes signature artifacts.
func SemanticEqual ¶
SemanticEqual compares parsed XML by expanded names and content. Namespace declaration spelling, prefixes and attribute order do not affect XML semantics and are therefore ignored.
func StoryRelationshipsNamespace ¶
StoryRelationshipsNamespace returns the concrete office-document relationships namespace declared by a story, if present.
func ValidatePackage ¶
ValidatePackage verifies OPC and WordprocessingML invariants that are not covered by XML well-formedness alone. It is intended for tests, diagnostics and explicit acceptance checks rather than the render hot path.
func ValidatePackageWithLimits ¶
func ValidatePackageWithLimits(data []byte, limits PackageLimits) error
ValidatePackageWithLimits validates a package using the same resource limit model as OpenPackageWithLimits.
func WordprocessingNamespace ¶
WordprocessingNamespace returns the concrete WordprocessingML namespace used by root. This deliberately preserves whether the destination story is Strict or Transitional.
Types ¶
type Attribute ¶
Attribute is an ordered XML attribute. Namespace declarations are kept as normal attributes with IsNamespaceDeclaration set.
type DigitalSignatureError ¶
DigitalSignatureError identifies the package metadata which caused a fail-closed digital-signature rejection.
func (*DigitalSignatureError) Error ¶
func (e *DigitalSignatureError) Error() string
func (*DigitalSignatureError) Unwrap ¶
func (e *DigitalSignatureError) Unwrap() error
type Name ¶
Name stores both the lexical prefix and the resolved namespace name. Prefix is retained for round-tripping; NamespaceURI is used for matching.
type Node ¶
type Node struct {
Kind NodeKind
ID uint64
Name Name
Attributes []Attribute
Children []*Node
Data string
Target string
}
Node is a lossless, ordered XML node for the information relevant to OOXML. IDs are stable across DeepClone so compiled render plans never depend on Go pointers.
func CloneDetachedStructuralRange ¶
CloneDetachedStructuralRange validates and deep-clones complete sibling nodes without assigning destination-local identifiers. The returned nodes are detached and owned by the caller. AdoptStructuralRange must be called exactly once after any render-time transformations and before insertion into a destination part.
func Parse ¶
Parse reads XML through RawToken so lexical prefixes and ordered attributes are retained. Names are additionally resolved against a namespace stack.
func ParseFragment ¶
ParseFragment parses a well-formed OOXML fragment using the standard Word namespaces. Prefixes outside this set must be declared by the fragment.
func (*Node) DeepCloneWithIndex ¶
DeepCloneWithIndex creates an independent tree and builds a render-local node/parent index in the same traversal. The index points only into the cloned tree.
type NodeIndex ¶
type NodeIndex struct {
// contains filtered or unexported fields
}
NodeIndex provides constant-time stable-ID and parent lookups for one tree. It is intentionally render-local: callers must rebuild it after structural mutations that add or remove nodes.
func NewNodeIndex ¶
NewNodeIndex indexes root and all descendants in document order.
type NodeLocation ¶
type NodeLocation struct {
NodeID uint64
Path []XMLPathStep
}
NodeLocation locates a node in the immutable story tree.
type Package ¶
type Package struct {
Parts []*Part
// contains filtered or unexported fields
}
Package is an ordered OPC package. It does not expose a map as the primary representation because ZIP entry order is preservation-sensitive.
func OpenPackage ¶
OpenPackage opens a DOCX using conservative server-safe limits.
func OpenPackageWithLimits ¶
func OpenPackageWithLimits(data []byte, limits PackageLimits) (*Package, error)
OpenPackageWithLimits parses supported story parts eagerly. Other entries retain their exact compressed stream and are decompressed only when their content is requested. The package keeps references into data; callers must not modify it afterwards.
func (*Package) AddBinaryPart ¶
AddBinaryPart appends generated non-XML content to the package.
func (*Package) AddXMLPart ¶
AddXMLPart appends a newly generated XML part. OPC relationship parts do not need a content-type override when the package has the standard rels default.
func (*Package) CloneForRender ¶
CloneForRender copies package/part metadata but deep-clones only the named mutable trees. Trees not listed in mutableParts remain shared and must be treated as immutable by the caller. The returned indexes point into cloned mutable trees only.
func (*Package) DeepClone ¶
DeepClone creates a render-local package. Immutable original and compressed bytes are shared; mutable trees and headers are copied.
func (*Package) DeepCloneWithIndexes ¶
DeepCloneWithIndexes creates a render-local package and an ID/parent index for every cloned XML tree. Clean non-tree parts are shared as immutable data.
func (*Package) EffectiveContentType ¶
EffectiveContentType returns the content type declared for partName, preferring an exact Override over the extension Default.
func (*Package) EnsureContentType ¶
EnsureContentType preserves an explicit content type while retaining the compact conventional Default entry when the extension has that exact type.
func (*Package) EnsureContentTypeDefault ¶
EnsureContentTypeDefault adds a Default entry for a generated part's extension when it is not already declared.
func (*Package) EnsureContentTypeOverride ¶
EnsureContentTypeOverride adds an Override entry for a generated OOXML part unless the part is already declared.
func (*Package) Marshal ¶
Marshal writes the entries in their original order. Clean entries reuse the original compressed stream through CreateRaw. Dirty entries are compressed up front so their local headers contain CRC and sizes; Office rejects stored entries that rely on streaming ZIP data descriptors.
func (*Package) Part ¶
Part returns a package entry by its ASCII-case-insensitive OPC name. The fixed [Content_Types].xml package item remains case-sensitive.
func (*Package) Relationships ¶
func (p *Package) Relationships(sourcePart string) (*RelationshipSet, error)
Relationships opens or creates the part-local relationship set.
func (*Package) ReplacePart ¶
ReplacePart stores generated bytes for an existing part or appends a new part. It is intended for non-story resource XML and binary package parts.
func (*Package) StoryPartNames ¶
StoryPartNames returns the main document and every header/footer story in a stable order. Relationship-discovered names are included even when they do not use Word's conventional headerN.xml/footerN.xml naming scheme.
type PackageLimits ¶
type PackageLimits struct {
MaxEntries int
MaxXMLPartBytes uint64
MaxMaterializedPartBytes uint64
MaxMaterializedTotalBytes uint64
MaxOutputBytes uint64
MaxXMLNodes uint64
MaxXMLAttributes uint64
MaxXMLTextBytes uint64
MaxXMLDepth uint64
}
PackageLimits bounds work which requires decompression. Clean entries that are only copied through do not count towards the materialized-byte limits.
type PackageValidationError ¶
type PackageValidationError struct {
Issues []ValidationIssue
Cause error
}
PackageValidationError contains every detected integrity violation.
func (*PackageValidationError) Error ¶
func (e *PackageValidationError) Error() string
func (*PackageValidationError) Unwrap ¶
func (e *PackageValidationError) Unwrap() error
type Paragraph ¶
type Paragraph struct {
NodeID uint64
Path []XMLPathStep
Text []TextReference
}
Paragraph is one independently compilable text scope. Nested paragraphs, for example inside a textbox, are indexed separately.
func IndexParagraphCompact ¶
IndexParagraphCompact indexes one WordprocessingML paragraph without traversing or wrapping its containing story. Nested paragraphs, such as those in textboxes, remain independent text scopes and are not included.
func (Paragraph) CompileTemplateSpans ¶
func (p Paragraph) CompileTemplateSpans() []TemplateSpan
CompileTemplateSpans finds template ranges across any number of visible w:t nodes. Positions are retained in node-local rune offsets for precise edits.
type Part ¶
type Part struct {
Name string
Header zip.FileHeader
Original []byte
Tree *Node
Dirty bool
Replacement []byte
// contains filtered or unexported fields
}
Part is one ordered OPC ZIP entry. Original is populated for eagerly parsed story parts; other clean content is available through ReadOnlyBytes or Bytes. Original, lazy backing and rawCompressed are immutable; Tree is populated only for supported story parts.
func (*Part) MarkDirty ¶
func (p *Part) MarkDirty()
MarkDirty records that Tree rather than Original must be serialized.
func (*Part) ReadOnlyBytes ¶
ReadOnlyBytes returns the current uncompressed part content without copying immutable binary storage. Callers must not modify the returned slice.
type RelationshipSet ¶
type RelationshipSet struct {
SourcePart string
Part *Part
// contains filtered or unexported fields
}
RelationshipSet mutates only the .rels part belonging to SourcePart.
func (*RelationshipSet) Add ¶
func (r *RelationshipSet) Add(relationshipType, target, targetMode string) string
Add appends a relationship with a collision-free part-local rId.
func (*RelationshipSet) AddHyperlink ¶
func (r *RelationshipSet) AddHyperlink(target string) string
AddHyperlink adds an external hyperlink relationship.
func (*RelationshipSet) Ensure ¶
func (r *RelationshipSet) Ensure(relationshipType, target, targetMode string) string
Ensure returns an existing matching relationship ID or appends one.
type Story ¶
type Story struct {
PartName string
RootID uint64
Paragraphs []Paragraph
Locations map[uint64]NodeLocation
// contains filtered or unexported fields
}
Story indexes visible WordprocessingML text while retaining stable Node IDs.
func IndexStory ¶
IndexStory builds the common document/header/footer story index. It traverses unknown wrappers, hyperlinks, content controls and textbox content naturally.
func IndexStoryCompact ¶
IndexStoryCompact indexes the text scopes needed by the renderer without materializing diagnostic XML paths or a location map for every node. Use IndexStory when callers need source locations for validation or diagnostics.
func (*Story) HasSemanticNonTextContent ¶
HasSemanticNonTextContent reports whether the paragraph carries fields, references, ranges, drawings, or other semantic content not represented by visible w:t nodes. The sparse set is populated only during story indexing.
type TemplateSpan ¶
type TemplateSpan struct {
Raw string
Start TextPosition
End TextPosition
GlobalStart int
GlobalEnd int
StartPath []XMLPathStep
RunIndex int
Malformed bool
}
TemplateSpan is a raw {{...}} range compiled from a paragraph's visible text. End is exclusive. Malformed spans extend to the end of the paragraph.
type TextPosition ¶
TextPosition addresses a rune boundary within one visible text node.
type TextReference ¶
type TextReference struct {
TextElementID uint64
TextNodeID uint64
RunIndex int
Text string
Path []XMLPathStep
}
TextReference identifies visible content from one w:t element.
type UniqueIDAllocator ¶
type UniqueIDAllocator struct {
// contains filtered or unexported fields
}
UniqueIDAllocator owns the part-local identifiers assigned to structural clones. It is render-local and therefore requires no synchronization.
func NewUniqueIDAllocator ¶
func NewUniqueIDAllocator(root *Node) *UniqueIDAllocator
NewUniqueIDAllocator scans the complete part before any clones are added.
func (*UniqueIDAllocator) AdoptOneToOneStructuralRange ¶
func (a *UniqueIDAllocator) AdoptOneToOneStructuralRange(nodes []*Node) error
AdoptOneToOneStructuralRange assigns destination-local identifiers to a structural range produced by splitting an existing range in place. Unlike AdoptStructuralRange, it accepts comment, permission, and custom XML range markers because the caller is transferring every split segment exactly once rather than duplicating arbitrary content. Range identifiers are therefore intentionally preserved. Only internal node IDs and duplicated paragraph or drawing hex IDs are made destination-local; paired bookmark IDs/names and field references must remain unchanged when their other endpoint lives outside the paragraph being split.
func (*UniqueIDAllocator) AdoptStructuralRange ¶
func (a *UniqueIDAllocator) AdoptStructuralRange(nodes []*Node) error
AdoptStructuralRange assigns destination-local IDs to detached nodes and remaps identifiers in place. The caller transfers ownership of nodes; they must not be shared with a prepared tree or another render. Compared with CloneStructuralRange this avoids a redundant deep clone for freshly parsed HTML/XML and already render-local DOCX fragment nodes.
func (*UniqueIDAllocator) CloneStructuralRange ¶
func (a *UniqueIDAllocator) CloneStructuralRange(nodes []*Node) ([]*Node, error)
CloneStructuralRange clones complete sibling nodes, assigns fresh internal IDs and remaps OOXML identifiers that must be unique within a part.
func (*UniqueIDAllocator) CloneStructuralRangeWithIndex ¶
func (a *UniqueIDAllocator) CloneStructuralRangeWithIndex(nodes []*Node) ([]*Node, *NodeIndex, error)
CloneStructuralRangeWithIndex clones a sibling range and returns an index that resolves both the source IDs used by compiled render plans and the new IDs assigned to the clones. This lets loop bodies reuse their prepared plans without reparsing the cloned XML on every iteration.
func (*UniqueIDAllocator) ReserveNodeIDFloor ¶
func (a *UniqueIDAllocator) ReserveNodeIDFloor(floor uint64)
ReserveNodeIDFloor prevents subsequently cloned internal nodes from using IDs at or below floor. This is useful when a prepared-tree index is available but the live render tree may have already removed its highest-ID nodes before the allocator is first needed. It deliberately affects only internal Node IDs; OOXML-visible identifiers are still derived from the live tree scan.
type ValidationIssue ¶
ValidationIssue describes one package-integrity violation that can make Word reject or repair a generated document.
type XMLPathStep ¶
XMLPathStep is a stable, namespace-aware structural location.