diff --git a/Sources/SwiftDocX/Document/Document.swift b/Sources/SwiftDocX/Document/Document.swift index dd68095..b6c9fc6 100644 --- a/Sources/SwiftDocX/Document/Document.swift +++ b/Sources/SwiftDocX/Document/Document.swift @@ -72,6 +72,9 @@ public class Document { /// Document properties (metadata and accessibility) public var properties: DocumentProperties + /// Page size and margins + public var pageAttributes: PageAttributes + /// Document header (appears at top of pages) public var header: Header? @@ -84,6 +87,7 @@ public class Document { self.tables = [] self.elements = [] self.properties = DocumentProperties() + self.pageAttributes = PageAttributes() self.header = nil self.footer = nil } diff --git a/Sources/SwiftDocX/Document/DocumentWriter.swift b/Sources/SwiftDocX/Document/DocumentWriter.swift index 34520b8..1f27ad7 100644 --- a/Sources/SwiftDocX/Document/DocumentWriter.swift +++ b/Sources/SwiftDocX/Document/DocumentWriter.swift @@ -126,7 +126,7 @@ public class DocumentWriter { // Build document XML with header/footer references let documentXML = buildDocumentXMLWithHeaderFooter( - elements: document.elements, + document: document, headerRelId: headerRelId, footerRelId: footerRelId ) @@ -210,7 +210,7 @@ public class DocumentWriter { // MARK: - Private Helpers private func buildDocumentXMLWithHeaderFooter( - elements: [DocumentElement], + document: Document, headerRelId: String?, footerRelId: String? ) -> String { @@ -220,7 +220,7 @@ public class DocumentWriter { """ - for element in elements { + for element in document.elements { switch element { case .paragraph(let paragraph): xml += buildParagraphXML(paragraph) @@ -237,8 +237,11 @@ public class DocumentWriter { if let footerRelId = footerRelId { xml += "" } - xml += "" - xml += "" + + // Page size and margins + let margins = document.pageAttributes.margins + xml += "" + xml += "" xml += "" xml += """ diff --git a/Sources/SwiftDocX/Model/PageAttributes.swift b/Sources/SwiftDocX/Model/PageAttributes.swift new file mode 100644 index 0000000..edbd52d --- /dev/null +++ b/Sources/SwiftDocX/Model/PageAttributes.swift @@ -0,0 +1,56 @@ +import Foundation + + +/// Represents attributes of a page, including paper size and margins. +public struct PageAttributes: Equatable, Sendable { + /// The page width, in points. (72 pts per inch). Defaults to 8.5" (612 pts). + public var width: Double = 612.0 + + /// The page height, in points (72 pts per inch). Defaults to 11" (792 pts). + public var height: Double = 792.0 + + /// The margins of the page (top, bottom, left, right). + public var margins: Margins + + /// The margin for the page header, in points (1 inch = 72 points). Defaults to 36. + public var headerMargin: Double = 36.0 + + /// The margin for the page footer, in points (1 inch = 72 points). Defaults to 36. + public var footerMargin: Double = 36.0 + + /// Initializes a `PageAttributes` with the default 8.5 x 11" page size, 1" margins, and 0.5" margins for the header/footer. + public init(width: Double = 612.0, height: Double = 792.0, margins: Margins = .init(top: 72.0, bottom: 72.0, left: 72.0, right: 72.0), headerMargin: Double = 36.0, footerMargin: Double = 36.0) { + self.width = width + self.height = height + self.margins = margins + self.headerMargin = headerMargin + self.footerMargin = footerMargin + } +} + + +/// Represents the margins of an element such as a page or table cell. +public struct Margins: Equatable, Sendable { + /// The element's top margin, in points (1 inch = 72 points). Defaults to 0. + public var top: Double + + /// The element's bottom margin, in points (1 inch = 72 points). Defaults to 0. + public var bottom: Double + + /// The element's left margin, in points (1 inch = 72 points). Defaults to 0. + public var left: Double + + /// The element's right margin, in points (1 inch = 72 points). Defaults to 0. + public var right: Double + + /// Initializes a `Margins`. By default, all edges are set to 0 points. + public init(top: Double = 0, bottom: Double = 0, left: Double = 0, right: Double = 0) + { + self.top = top + self.bottom = bottom + self.left = left + self.right = right + } +} + + diff --git a/Sources/SwiftDocX/Model/Table.swift b/Sources/SwiftDocX/Model/Table.swift index 371e4a2..17c2892 100644 --- a/Sources/SwiftDocX/Model/Table.swift +++ b/Sources/SwiftDocX/Model/Table.swift @@ -81,6 +81,9 @@ public class TableCell { /// Cell width in points (nil for auto) public var width: Double? + /// The inset from the cell edges to the content of the cell. This value overrides the value of `Table.cellMargins` if both are set. + public var margins: Margins? + /// Background/shading color public var backgroundColor: Color? @@ -99,6 +102,7 @@ public class TableCell { public init() { self.paragraphs = [] self.width = nil + self.margins = nil self.backgroundColor = nil self.verticalAlignment = nil self.columnSpan = 1 @@ -178,6 +182,9 @@ public class Table { /// Table width in points (nil for auto) public var width: Double? + /// The margins (insets) to use for each cell in this `Table`. Can be overriden for a particular cell by setting `TableCell.margins`. + public var cellMargins: Margins? + /// Table alignment public var alignment: ParagraphAlignment? @@ -192,6 +199,7 @@ public class Table { self.borders = .single self.columnWidths = [] self.width = nil + self.cellMargins = nil self.alignment = nil self.accessibilityCaption = nil self.accessibilitySummary = nil diff --git a/Sources/SwiftDocX/XML/DocumentXMLBuilder.swift b/Sources/SwiftDocX/XML/DocumentXMLBuilder.swift index 42e11ca..c0995da 100644 --- a/Sources/SwiftDocX/XML/DocumentXMLBuilder.swift +++ b/Sources/SwiftDocX/XML/DocumentXMLBuilder.swift @@ -300,6 +300,16 @@ public class DocumentXMLBuilder { xml += "" } + // Table cell margins + if let margins = table.cellMargins { + xml += "" + xml += "" + xml += "" + xml += "" + xml += "" + xml += "" + } + // Accessibility: Caption (visible title) and Description (for screen readers) if let caption = table.accessibilityCaption { xml += "" @@ -413,6 +423,15 @@ public class DocumentXMLBuilder { xml += "" } + if let margins = cell.margins { + xml += "" + xml += "" + xml += "" + xml += "" + xml += "" + xml += "" + } + if cell.columnSpan > 1 { xml += "" }