@@ -10,6 +10,17 @@ import { evaluateXPathToMap } from '../utilities/xquery.ts';
1010 * https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_rPr_topic_ID0EIEKM.html
1111 */
1212export type SectionProperties = {
13+ /**
14+ * The column layout for a particular section of the document
15+ */
16+ columns ?: {
17+ numberOfColumns : null | number ;
18+ equalWidth : null | boolean ;
19+ separator : null | boolean ;
20+ columnSpacing ?: null | Length ;
21+ columns ?: { columnSize : Length , columnSpacing : Length | null } [ ]
22+ } ;
23+
1324 /**
1425 * A reference to the header portion on every page in this section.
1526 */
@@ -54,41 +65,70 @@ export type SectionProperties = {
5465export function sectionPropertiesFromNode ( node ?: Node | null ) : SectionProperties {
5566 if ( ! node ) {
5667 return { } ;
57- }
68+ } ;
5869 const data = evaluateXPathToMap < SectionProperties > (
59- `map {
60- "headers": map {
61- "first": ./${ QNS . w } headerReference[@${ QNS . w } type = 'first']/@${ QNS . r } id/string(),
62- "even": ./${ QNS . w } headerReference[@${ QNS . w } type = 'even']/@${ QNS . r } id/string(),
63- "odd": ./${ QNS . w } headerReference[@${ QNS . w } type = 'default']/@${ QNS . r } id/string()
64- },
65- "footers": map {
66- "first": ./${ QNS . w } footerReference[@${ QNS . w } type = 'first']/@${ QNS . r } id/string(),
67- "even": ./${ QNS . w } footerReference[@${ QNS . w } type = 'even']/@${ QNS . r } id/string(),
68- "odd": ./${ QNS . w } footerReference[@${ QNS . w } type = 'default']/@${ QNS . r } id/string()
69- },
70- "pageWidth": docxml:length(${ QNS . w } pgSz/@${ QNS . w } w, 'twip'),
71- "pageHeight": docxml:length(${ QNS . w } pgSz/@${ QNS . w } h, 'twip'),
72- "pageOrientation": ./${ QNS . w } pgSz/@${ QNS . w } orient/string(),
73- "pageMargin": map {
74- "top": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } top, 'twip'),
75- "right": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } right, 'twip'),
76- "bottom": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } bottom, 'twip'),
77- "left": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } left, 'twip'),
78- "header": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } header, 'twip'),
79- "footer": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } footer, 'twip'),
80- "gutter": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } gutter, 'twip')
81- },
82- "isTitlePage": exists(./${ QNS . w } titlePg) and (not(./${ QNS . w } titlePg/@${ QNS . w } val) or docxml:st-on-off(./${ QNS . w } titlePg/@${ QNS . w } val))
83- }` ,
70+ `let $propsMap := map {
71+ "headers": map {
72+ "first": ./${ QNS . w } headerReference[@${ QNS . w } type = 'first']/@${ QNS . r } id/string(),
73+ "even": ./${ QNS . w } headerReference[@${ QNS . w } type = 'even']/@${ QNS . r } id/string(),
74+ "odd": ./${ QNS . w } headerReference[@${ QNS . w } type = 'default']/@${ QNS . r } id/string()
75+ },
76+ "footers": map {
77+ "first": ./${ QNS . w } footerReference[@${ QNS . w } type = 'first']/@${ QNS . r } id/string(),
78+ "even": ./${ QNS . w } footerReference[@${ QNS . w } type = 'even']/@${ QNS . r } id/string(),
79+ "odd": ./${ QNS . w } footerReference[@${ QNS . w } type = 'default']/@${ QNS . r } id/string()
80+ },
81+ "columns": map {
82+ "numberOfColumns": ./${ QNS . w } cols/@${ QNS . w } num/number(),
83+ "separator": docxml:st-on-off(./${ QNS . w } cols/@${ QNS . w } sep),
84+ "equalWidth": docxml:st-on-off(./${ QNS . w } cols/@${ QNS . w } equalWidth)
85+ },
86+ "pageWidth": docxml:length(${ QNS . w } pgSz/@${ QNS . w } w, 'twip'),
87+ "pageHeight": docxml:length(${ QNS . w } pgSz/@${ QNS . w } h, 'twip'),
88+ "pageOrientation": ./${ QNS . w } pgSz/@${ QNS . w } orient/string(),
89+ "pageMargin": map {
90+ "top": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } top, 'twip'),
91+ "right": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } right, 'twip'),
92+ "bottom": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } bottom, 'twip'),
93+ "left": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } left, 'twip'),
94+ "header": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } header, 'twip'),
95+ "footer": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } footer, 'twip'),
96+ "gutter": docxml:length(./${ QNS . w } pgMar/@${ QNS . w } gutter, 'twip')
97+ },
98+ "isTitlePage": exists(./${ QNS . w } titlePg) and (not(./${ QNS . w } titlePg/@${ QNS . w } val) or docxml:st-on-off(./${ QNS . w } titlePg/@${ QNS . w } val))
99+ }
100+ let $colSpacing := if (exists(./${ QNS . w } cols/@${ QNS . w } space)) then (docxml:length(./${ QNS . w } cols/@${ QNS . w } space, 'twip')) else ()
101+ let $cols := ./${ QNS . w } cols/${ QNS . w } col
102+ let $colMap :=
103+ if (exists($cols))
104+ then (
105+ for-each(
106+ $cols,
107+ function($c) {
108+ map {
109+ "columnsSize": docxml:length($c/@${ QNS . w } w, 'twip'),
110+ "columnSpacing": docxml:length($c/@${ QNS . w } space, 'twip')
111+ }
112+ }
113+ )
114+ )
115+ else()
116+
117+ return (
118+ if (exists($colSpacing))
119+ then (
120+ map:put($propsMap('columns'), 'columnSpacing', $colSpacing)
121+ )
122+ else(),
123+ map:put($propsMap('columns'), 'columns', $colMap)
124+ )` ,
84125 node ,
85126 ) ;
86-
87127 return data ;
88128}
89129
90130export function sectionPropertiesToNode ( data : SectionProperties = { } ) : Node {
91- return create (
131+ const query = create (
92132 `element ${ QNS . w } sectPr {
93133 if (exists($headers('first'))) then element ${ QNS . w } headerReference {
94134 attribute ${ QNS . r } id { $headers('first') },
@@ -114,6 +154,24 @@ export function sectionPropertiesToNode(data: SectionProperties = {}): Node {
114154 attribute ${ QNS . r } id { $footers('odd') },
115155 attribute ${ QNS . w } type { 'default' }
116156 } else (),
157+ if (exists($columns)) then element ${ QNS . w } cols {
158+ attribute ${ QNS . w } sep { $columns('separator') },
159+ attribute ${ QNS . w } equalWidth { $columns('equalWidth') },
160+ attribute ${ QNS . w } num { $columns('numberOfColumns') },
161+ if (exists($columns('columnSpacing')))
162+ then (
163+ attribute ${ QNS . w } columnSpacing { $columns('columnSpacing')}
164+ )
165+ else (),
166+ if (exists($columns('columns')))
167+ then (
168+ element columns {
169+ attribute ${ QNS . w } w { round($columns('columns')('columnSize')('twip')) },
170+ attribute ${ QNS . w } space { round($columns('columns')('columnSpacing')('twip')) }
171+ }
172+ )
173+ else()
174+ } else (),
117175 if (exists($pageWidth) or exists($pageHeight) or $pageOrientation) then element ${ QNS . w } pgSz {
118176 if (exists($pageWidth)) then attribute ${ QNS . w } w {
119177 round($pageWidth('twip'))
@@ -157,11 +215,19 @@ export function sectionPropertiesToNode(data: SectionProperties = {}): Node {
157215 typeof data . footers === 'string'
158216 ? { first : data . footers , even : data . footers , odd : data . footers }
159217 : data . footers || { } ,
218+ columns : {
219+ numberOfColumns : data . columns ?. numberOfColumns ,
220+ separator : data . columns ?. separator ,
221+ equalWidth : data . columns ?. equalWidth ,
222+ columnSpacing : data . columns ?. columnSpacing ,
223+ columns : data . columns ?. columns ,
224+ } ,
160225 pageWidth : data . pageWidth || null ,
161226 pageHeight : data . pageHeight || null ,
162227 pageMargin : data . pageMargin || null ,
163228 pageOrientation : data . pageOrientation || null ,
164229 isTitlePage : data . isTitlePage || null ,
165230 } ,
166231 ) ;
232+ return query ;
167233}
0 commit comments