fix: import of columns
This commit is contained in:
1 parent
e6fbf9703c
commit
15f7e50976
5 files changed
+80
-12
No files matched your search
@@ -916,7 +916,7 @@ function pushColumnRuns(inner: Node[], cols: { count: number; gapCm: number }, o
|
||||
if (COLUMNS_ALLOWED.has(block.type)) {
|
||||
run.push(block);
|
||||
} else {
|
||||
ctx.warnings.add('Tables, text boxes and nested sections inside a multi-column section were moved out of the columns');
|
||||
ctx.warnings.add('Tables and text boxes inside a multi-column layout were moved out of the columns');
|
||||
flush();
|
||||
out.push(block);
|
||||
}
|
||||
|
||||
+16
-5
@@ -286,9 +286,18 @@ export function importOdt(bytes: Uint8Array): OdtImportResult {
|
||||
if (!body) throw new Error('Not a text document (no office:text body).');
|
||||
|
||||
const ctx: Ctx = { resolver, warnings, files, imageCache: new Map(), pendingBlocks: [] };
|
||||
const blocks = convertBlocks(Array.from(body.children), ctx, 'body');
|
||||
let blocks = convertBlocks(Array.from(body.children), ctx, 'body');
|
||||
if (blocks.length === 0) blocks.push({ type: 'paragraph' });
|
||||
|
||||
// Whole-document columns declared on the page layout (Word-style) instead of a
|
||||
// text:section: wrap the body's wrappable runs the way a section would be.
|
||||
const pageCols = resolver.pageColumns();
|
||||
if (pageCols) {
|
||||
const wrapped: Node[] = [];
|
||||
pushColumnRuns(blocks, pageCols, wrapped, ctx);
|
||||
blocks = wrapped;
|
||||
}
|
||||
|
||||
const hf = resolver.masterPageHF();
|
||||
if (hf.hasVariants) {
|
||||
warnings.add('Per-page header/footer variants (first/even pages) are not supported — the default one was used');
|
||||
@@ -372,9 +381,9 @@ function parseXml(xml: string): Document {
|
||||
// Block types a columns section (columns.ts) can contain.
|
||||
const COLUMNS_ALLOWED = new Set(['paragraph', 'heading', 'bulletList', 'orderedList']);
|
||||
|
||||
// Wrap a multi-column <text:section>'s converted blocks into columns nodes: maximal
|
||||
// runs of allowed types become one node each; anything else (tables, text boxes,
|
||||
// nested sections) is emitted between the runs at top level with a warning.
|
||||
// Wrap a multi-column region's converted blocks into columns nodes: maximal runs of
|
||||
// allowed types become one node each; anything else is emitted between the runs at
|
||||
// top level — with a warning, except columns nodes (they keep their own layout).
|
||||
function pushColumnRuns(inner: Node[], cols: { count: number; gapCm: number }, out: Node[], ctx: Ctx): void {
|
||||
let count = cols.count;
|
||||
if (count > 3) {
|
||||
@@ -390,7 +399,9 @@ function pushColumnRuns(inner: Node[], cols: { count: number; gapCm: number }, o
|
||||
if (COLUMNS_ALLOWED.has(block.type)) {
|
||||
run.push(block);
|
||||
} else {
|
||||
ctx.warnings.add('Tables, text boxes and nested sections inside a multi-column section were moved out of the columns');
|
||||
if (block.type !== 'columns') {
|
||||
ctx.warnings.add('Tables and text boxes inside a multi-column layout were moved out of the columns');
|
||||
}
|
||||
flush();
|
||||
out.push(block);
|
||||
}
|
||||
|
||||
@@ -272,12 +272,23 @@ export class StyleResolver {
|
||||
}
|
||||
|
||||
// A section style's column layout: { count, gapCm } when it declares more than one
|
||||
// column, else null. The gap falls back to the per-column indent form (first
|
||||
// column's fo:end-indent + second's fo:start-indent) LibreOffice sometimes writes.
|
||||
// column, else null.
|
||||
sectionColumns(name: string | null): { count: number; gapCm: number } | null {
|
||||
const el = name ? this.sectionStyleEls.get(name) : null;
|
||||
if (!el) return null;
|
||||
const props = el.getElementsByTagNameNS(NS.style, 'section-properties')[0];
|
||||
const props = el?.getElementsByTagNameNS(NS.style, 'section-properties')[0];
|
||||
return this.columnsFrom(props ?? null);
|
||||
}
|
||||
|
||||
// Column layout of the master page's page layout — Word-produced files put
|
||||
// whole-document columns here instead of in a text:section.
|
||||
pageColumns(): { count: number; gapCm: number } | null {
|
||||
return this.columnsFrom(this.pageLayoutEl()?.getElementsByTagNameNS(NS.style, 'page-layout-properties')[0] ?? null);
|
||||
}
|
||||
|
||||
// <style:columns> under a properties element: { count, gapCm } when it declares more
|
||||
// than one column, else null. The gap falls back to LibreOffice's per-column indent
|
||||
// form (first column's fo:end-indent + second's fo:start-indent).
|
||||
private columnsFrom(props: Element | null): { count: number; gapCm: number } | null {
|
||||
const cols = props?.getElementsByTagNameNS(NS.style, 'columns')[0];
|
||||
if (!cols) return null;
|
||||
const count = parseInt(cols.getAttributeNS(NS.fo, 'column-count') ?? '', 10);
|
||||
|
||||
Reference in new issue
Block a user