@a3s-lab/office 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +98 -24
  2. package/dist/0~2582.js +485 -0
  3. package/dist/0~4595.js +14 -7
  4. package/dist/0~4750.js +939 -0
  5. package/dist/{0~work-document-paragraph-formatting.js → 0~5861.js} +174 -3
  6. package/dist/0~7048.js +8 -6
  7. package/dist/0~9512.js +7 -4
  8. package/dist/0~document-editor.js +3147 -531
  9. package/dist/0~markdown-editor.js +26 -1
  10. package/dist/0~presentation-editor.js +68 -12
  11. package/dist/0~spreadsheet-editor.js +37 -17
  12. package/dist/0~work-document-extensions.js +588 -13
  13. package/dist/0~work-document-model-codec.js +1 -1
  14. package/dist/0~work-docx-bibliography.js +1 -1
  15. package/dist/0~work-docx-export.js +116 -55
  16. package/dist/0~work-docx-import.js +690 -99
  17. package/dist/0~work-office-diagnostics.js +2 -2
  18. package/dist/{4704.js → 2881.js} +162 -71
  19. package/dist/4104.js +2 -62
  20. package/dist/internal/features/work/editors/document-comment-window.d.ts +37 -0
  21. package/dist/internal/features/work/editors/document-navigation-panel.d.ts +3 -1
  22. package/dist/internal/features/work/editors/document-navigation-window.d.ts +64 -0
  23. package/dist/internal/features/work/editors/document-outline-navigation.d.ts +11 -0
  24. package/dist/internal/features/work/editors/document-page-navigation.d.ts +11 -1
  25. package/dist/internal/features/work/editors/document-page-thumbnail.d.ts +31 -0
  26. package/dist/internal/features/work/editors/document-picture-properties-dialog-model.d.ts +28 -0
  27. package/dist/internal/features/work/editors/document-picture-properties-dialog.d.ts +4 -0
  28. package/dist/internal/features/work/editors/document-search-navigation.d.ts +12 -0
  29. package/dist/internal/features/work/editors/document-table-margins-popover.d.ts +4 -0
  30. package/dist/internal/features/work/editors/document-table-properties-dialog-model.d.ts +51 -0
  31. package/dist/internal/features/work/editors/document-table-properties-dialog-sections.d.ts +19 -0
  32. package/dist/internal/features/work/editors/document-table-properties-dialog.d.ts +8 -0
  33. package/dist/internal/features/work/editors/office-task-pane.d.ts +1 -1
  34. package/dist/internal/features/work/editors/presentation-chart-panel.d.ts +2 -1
  35. package/dist/internal/features/work/editors/presentation-comments-panel.d.ts +2 -1
  36. package/dist/internal/features/work/editors/spreadsheet-workbook-panel.d.ts +2 -1
  37. package/dist/internal/features/work/editors/use-document-pagination.d.ts +6 -0
  38. package/dist/internal/features/work/editors/use-presentation-review-commands.d.ts +1 -1
  39. package/dist/internal/features/work/work-document-image-layout.d.ts +11 -0
  40. package/dist/internal/features/work/work-document-page-capture.d.ts +15 -0
  41. package/dist/internal/features/work/work-document-paragraph-formatting.d.ts +4 -0
  42. package/dist/internal/features/work/work-document-section.d.ts +3 -1
  43. package/dist/internal/features/work/work-document-table-borders.d.ts +20 -0
  44. package/dist/internal/features/work/work-document-table-cell-formatting.d.ts +8 -5
  45. package/dist/internal/features/work/work-document-table-geometry.d.ts +41 -0
  46. package/dist/internal/features/work/work-document-table-property-changes.d.ts +25 -0
  47. package/dist/internal/features/work/work-document-table-sizing.d.ts +15 -2
  48. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +11 -0
  49. package/dist/internal/features/work/work-docx-document-layout.d.ts +2 -0
  50. package/dist/internal/features/work/work-docx-paragraph-alignment-import.d.ts +2 -1
  51. package/dist/internal/features/work/work-docx-paragraph-direction-import.d.ts +2 -1
  52. package/dist/internal/features/work/work-docx-paragraph-indent-import.d.ts +2 -1
  53. package/dist/internal/features/work/work-docx-paragraph-pagination-import.d.ts +2 -1
  54. package/dist/internal/features/work/work-docx-paragraph-spacing-import.d.ts +3 -2
  55. package/dist/internal/features/work/work-docx-paragraph-styles.d.ts +2 -2
  56. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +8 -1
  57. package/dist/internal/features/work/work-docx-tab-stop-import.d.ts +2 -1
  58. package/dist/internal/features/work/work-docx-table-cell-export.d.ts +1 -1
  59. package/dist/internal/features/work/work-docx-table-cell-import.d.ts +14 -4
  60. package/dist/internal/features/work/work-docx-table-sizing-export.d.ts +1 -1
  61. package/dist/internal/features/work/work-docx-table-sizing-import.d.ts +4 -3
  62. package/dist/internal/features/work/work-docx-table-styles.d.ts +22 -0
  63. package/dist/internal/features/work/work-types.d.ts +6 -0
  64. package/dist/office-kernel.wasm +0 -0
  65. package/dist/styles.css +1288 -233
  66. package/docs/{browser-editor-architecture.md → latest/en/browser-editor-architecture.md} +144 -35
  67. package/package.json +9 -5
  68. package/dist/0~6552.js +0 -787
  69. package/dist/0~8155.js +0 -299
@@ -1,9 +1,9 @@
1
1
  import jszip from "jszip";
2
2
  import { contentTypeForPart, directChildren, bytesToDataUrl, OoxmlPackage, firstDescendant, descendants, directChild, childPath, attribute } from "./8715.js";
3
3
  import { docxCaptionSequenceKind, docxFieldOccurrences, docxCaptionBookmark, docxFieldResultText, docxCaptionReferenceTarget } from "./0~152.js";
4
- import { documentContentLayoutProperties, documentPageChromeLegacyFields, normalizeDocumentFieldsHtml, documentInitialSectionLayout, documentSectionDomAttributes, documentCaptionLabel, normalizeDocumentPageChrome, normalizeDocumentCitationsHtml, normalizeDocumentColumns, normalizeDocumentCaptionsHtml, normalizeDocumentNotesHtml, documentCitationTagsFromInstruction, docxDocumentFieldKind, createDocumentNoteElement } from "./4704.js";
5
- import { normalizeDocumentImageAlignment, serializeDocumentTabStops, normalizeDocumentImageLayoutOptions, normalizeDocumentTabStops } from "./0~8155.js";
6
- import { normalizeDocumentParagraphIndent } from "./0~work-document-paragraph-formatting.js";
4
+ import { documentContentLayoutProperties, documentPageChromeLegacyFields, normalizeDocumentFieldsHtml, documentInitialSectionLayout, documentSectionDomAttributes, documentCaptionLabel, normalizeDocumentPageChrome, normalizeDocumentCitationsHtml, normalizeDocumentColumns, normalizeDocumentCaptionsHtml, normalizeDocumentNotesHtml, documentCitationTagsFromInstruction, docxDocumentFieldKind, createDocumentNoteElement } from "./2881.js";
5
+ import { renderDocumentTableBorders, renderDocumentTableCellMarginOverrides, normalizeDocumentImageAlignment, documentTableBordersFromElement, normalizeDocumentImageLayoutOptions, normalizeDocumentTabStops, DEFAULT_DOCUMENT_TABLE_GEOMETRY, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, serializeDocumentTabStops, applyDocumentTableGeometryToElement } from "./0~4750.js";
6
+ import { normalizeDocumentParagraphIndent, documentAutoLineHeight, documentWordLineHeightFactor, renderDocumentAutoLineHeight } from "./0~5861.js";
7
7
  import { readDocxBibliography } from "./0~work-docx-bibliography.js";
8
8
  import { importDocxPageColor } from "./0~work-docx-page-color.js";
9
9
  const WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
@@ -1332,21 +1332,23 @@ function createDocxParagraphStyleResolver(stylesDocument) {
1332
1332
  function resolveDocxParagraphStyleResolver(source) {
1333
1333
  return source && 'styles' in source ? source : createDocxParagraphStyleResolver(source);
1334
1334
  }
1335
- function docxParagraphPropertySources(directProperties, resolver) {
1335
+ function docxParagraphPropertySources(directProperties, resolver, contextualProperties = []) {
1336
1336
  const sources = [];
1337
1337
  if (resolver.defaultProperties) sources.push(resolver.defaultProperties);
1338
1338
  const styleReference = directProperties ? directChild(directProperties, 'pStyle') : void 0;
1339
1339
  const styleId = (styleReference ? wordAttribute(styleReference, 'val')?.trim() : void 0) || resolver.defaultStyleId;
1340
1340
  if (styleId) sources.push(...stylePropertySources(resolver.styles, styleId, 'paragraphProperties'));
1341
+ sources.push(...contextualProperties);
1341
1342
  if (directProperties) sources.push(directProperties);
1342
1343
  return sources;
1343
1344
  }
1344
- function docxRunPropertySources(paragraphProperties, runProperties, resolver) {
1345
+ function docxRunPropertySources(paragraphProperties, runProperties, resolver, contextualProperties = []) {
1345
1346
  const sources = [];
1346
1347
  if (resolver.defaultRunProperties) sources.push(resolver.defaultRunProperties);
1347
1348
  const paragraphStyleReference = paragraphProperties ? directChild(paragraphProperties, 'pStyle') : void 0;
1348
1349
  const paragraphStyleId = (paragraphStyleReference ? wordAttribute(paragraphStyleReference, 'val')?.trim() : void 0) || resolver.defaultStyleId;
1349
1350
  if (paragraphStyleId) sources.push(...stylePropertySources(resolver.styles, paragraphStyleId, 'runProperties'));
1351
+ sources.push(...contextualProperties);
1350
1352
  const paragraphRunProperties = paragraphProperties ? directChild(paragraphProperties, 'rPr') : void 0;
1351
1353
  if (paragraphRunProperties) sources.push(paragraphRunProperties);
1352
1354
  const characterStyleReference = runProperties ? directChild(runProperties, 'rStyle') : void 0;
@@ -1379,15 +1381,266 @@ function onOffAttribute(element, name) {
1379
1381
  function wordAttribute(element, name) {
1380
1382
  return attribute(element, name) ?? attribute(element, `w:${name}`);
1381
1383
  }
1384
+ const work_docx_table_styles_MAX_STYLE_INHERITANCE_DEPTH = 64;
1385
+ const DEFAULT_TABLE_LOOK = {
1386
+ firstRow: true,
1387
+ lastRow: false,
1388
+ firstColumn: true,
1389
+ lastColumn: false,
1390
+ noHorizontalBand: false,
1391
+ noVerticalBand: true
1392
+ };
1393
+ const TABLE_LOOK_BITS = {
1394
+ firstRow: 0x0020,
1395
+ lastRow: 0x0040,
1396
+ firstColumn: 0x0080,
1397
+ lastColumn: 0x0100,
1398
+ noHorizontalBand: 0x0200,
1399
+ noVerticalBand: 0x0400
1400
+ };
1401
+ function createDocxTableStyleResolver(stylesDocument) {
1402
+ if (!stylesDocument) return {
1403
+ tableStyles: new Map()
1404
+ };
1405
+ const tableStyles = new Map();
1406
+ let defaultStyleId;
1407
+ for (const style of descendants(stylesDocument, 'style')){
1408
+ if ('table' !== work_docx_table_styles_wordAttribute(style, 'type')) continue;
1409
+ const styleId = work_docx_table_styles_wordAttribute(style, 'styleId')?.trim();
1410
+ if (!styleId) continue;
1411
+ const basedOn = directChild(style, 'basedOn');
1412
+ const conditional = new Map();
1413
+ for (const conditionalStyle of directChildren(style, 'tblStylePr')){
1414
+ const type = work_docx_table_styles_wordAttribute(conditionalStyle, 'type')?.trim();
1415
+ if (type) conditional.set(type, styleLayer(conditionalStyle));
1416
+ }
1417
+ tableStyles.set(styleId, {
1418
+ ...styleLayer(style),
1419
+ basedOn: basedOn ? work_docx_table_styles_wordAttribute(basedOn, 'val')?.trim() || void 0 : void 0,
1420
+ conditional
1421
+ });
1422
+ if (!defaultStyleId && work_docx_table_styles_onOffAttribute(style, 'default')) defaultStyleId = styleId;
1423
+ }
1424
+ return {
1425
+ defaultStyleId,
1426
+ tableStyles
1427
+ };
1428
+ }
1429
+ function resolveDocxTableStyleResolver(source) {
1430
+ return source && 'tableStyles' in source ? source : createDocxTableStyleResolver(source);
1431
+ }
1432
+ function docxTablePropertySources(table, resolver) {
1433
+ const directTableProperties = directChild(table, 'tblPr');
1434
+ const styleReference = directTableProperties ? directChild(directTableProperties, 'tblStyle') : void 0;
1435
+ const styleId = (styleReference ? work_docx_table_styles_wordAttribute(styleReference, 'val')?.trim() : void 0) || resolver.defaultStyleId;
1436
+ const sources = styleId ? tableStyleChain(resolver.tableStyles, styleId).map(({ tableProperties })=>tableProperties).filter((properties)=>Boolean(properties)) : [];
1437
+ if (directTableProperties) sources.push(directTableProperties);
1438
+ return sources;
1439
+ }
1440
+ function docxTableCellStyleLayers(cell, resolver) {
1441
+ const table = work_docx_table_styles_closestAncestor(cell, 'tbl');
1442
+ if (!table) return [];
1443
+ const directTableProperties = directChild(table, 'tblPr');
1444
+ const styleReference = directTableProperties ? directChild(directTableProperties, 'tblStyle') : void 0;
1445
+ const styleId = (styleReference ? work_docx_table_styles_wordAttribute(styleReference, 'val')?.trim() : void 0) || resolver.defaultStyleId;
1446
+ if (!styleId) return [];
1447
+ const styles = tableStyleChain(resolver.tableStyles, styleId);
1448
+ if (!styles.length) return [];
1449
+ const unconditionalLayers = styles.map(styleLayerFromStyle);
1450
+ const propertySources = unconditionalLayers.map(({ tableProperties })=>tableProperties).filter((properties)=>Boolean(properties));
1451
+ if (directTableProperties) propertySources.push(directTableProperties);
1452
+ const position = tableCellPosition(table, cell);
1453
+ if (!position) return unconditionalLayers;
1454
+ const look = resolveTableLook(propertySources);
1455
+ const rowBandSize = resolveBandSize(propertySources, 'tblStyleRowBandSize');
1456
+ const columnBandSize = resolveBandSize(propertySources, 'tblStyleColBandSize');
1457
+ const layers = [
1458
+ ...unconditionalLayers
1459
+ ];
1460
+ for (const condition of applicableConditions(position, look, rowBandSize, columnBandSize))for (const style of styles){
1461
+ const layer = style.conditional.get(condition);
1462
+ if (layer) layers.push(layer);
1463
+ }
1464
+ return layers;
1465
+ }
1466
+ function docxTableRunPropertySources(element, resolver) {
1467
+ const cell = work_docx_table_styles_closestAncestor(element, 'tc');
1468
+ if (!cell) return [];
1469
+ const sources = [];
1470
+ for (const layer of docxTableCellStyleLayers(cell, resolver)){
1471
+ const paragraphRunProperties = layer.paragraphProperties ? directChild(layer.paragraphProperties, 'rPr') : void 0;
1472
+ if (paragraphRunProperties) sources.push(paragraphRunProperties);
1473
+ if (layer.runProperties) sources.push(layer.runProperties);
1474
+ }
1475
+ return sources;
1476
+ }
1477
+ function docxTableParagraphPropertySources(element, resolver) {
1478
+ const cell = work_docx_table_styles_closestAncestor(element, 'tc');
1479
+ if (!cell) return [];
1480
+ return docxTableCellStyleLayers(cell, resolver).map(({ paragraphProperties })=>paragraphProperties).filter((properties)=>Boolean(properties));
1481
+ }
1482
+ function styleLayer(parent) {
1483
+ return {
1484
+ tableProperties: directChild(parent, 'tblPr'),
1485
+ cellProperties: directChild(parent, 'tcPr'),
1486
+ paragraphProperties: directChild(parent, 'pPr'),
1487
+ runProperties: directChild(parent, 'rPr')
1488
+ };
1489
+ }
1490
+ function styleLayerFromStyle(style) {
1491
+ return {
1492
+ tableProperties: style.tableProperties,
1493
+ cellProperties: style.cellProperties,
1494
+ paragraphProperties: style.paragraphProperties,
1495
+ runProperties: style.runProperties
1496
+ };
1497
+ }
1498
+ function tableStyleChain(styles, styleId) {
1499
+ const inherited = [];
1500
+ const visited = new Set();
1501
+ let currentStyleId = styleId;
1502
+ let depth = 0;
1503
+ while(currentStyleId && depth < work_docx_table_styles_MAX_STYLE_INHERITANCE_DEPTH && !visited.has(currentStyleId)){
1504
+ depth += 1;
1505
+ visited.add(currentStyleId);
1506
+ const style = styles.get(currentStyleId);
1507
+ if (!style) break;
1508
+ inherited.push(style);
1509
+ currentStyleId = style.basedOn;
1510
+ }
1511
+ return inherited.reverse();
1512
+ }
1513
+ function applicableConditions(position, look, rowBandSize, columnBandSize) {
1514
+ const conditions = [
1515
+ 'wholeTable'
1516
+ ];
1517
+ const isFirstRow = 0 === position.rowIndex;
1518
+ const isLastRow = position.rowIndex === position.rowCount - 1;
1519
+ const isFirstColumn = 0 === position.columnStart;
1520
+ const isLastColumn = position.columnEnd === position.columnCount - 1;
1521
+ if (!look.noVerticalBand) {
1522
+ const offset = look.firstColumn ? 1 : 0;
1523
+ const bandIndex = position.columnStart - offset;
1524
+ if (bandIndex >= 0) conditions.push(Math.floor(bandIndex / columnBandSize) % 2 === 0 ? 'band1Vert' : 'band2Vert');
1525
+ }
1526
+ if (!look.noHorizontalBand) {
1527
+ const offset = look.firstRow ? 1 : 0;
1528
+ const bandIndex = position.rowIndex - offset;
1529
+ if (bandIndex >= 0) conditions.push(Math.floor(bandIndex / rowBandSize) % 2 === 0 ? 'band1Horz' : 'band2Horz');
1530
+ }
1531
+ if (look.firstColumn && isFirstColumn) conditions.push('firstCol');
1532
+ if (look.lastColumn && isLastColumn) conditions.push('lastCol');
1533
+ if (look.firstRow && isFirstRow) conditions.push('firstRow');
1534
+ if (look.lastRow && isLastRow) conditions.push('lastRow');
1535
+ if (look.firstRow && isFirstRow && look.firstColumn && isFirstColumn) conditions.push('nwCell');
1536
+ if (look.firstRow && isFirstRow && look.lastColumn && isLastColumn) conditions.push('neCell');
1537
+ if (look.lastRow && isLastRow && look.firstColumn && isFirstColumn) conditions.push('swCell');
1538
+ if (look.lastRow && isLastRow && look.lastColumn && isLastColumn) conditions.push('seCell');
1539
+ return conditions;
1540
+ }
1541
+ function resolveTableLook(propertySources) {
1542
+ const look = {
1543
+ ...DEFAULT_TABLE_LOOK
1544
+ };
1545
+ for (const properties of propertySources){
1546
+ const element = directChild(properties, 'tblLook');
1547
+ if (!element) continue;
1548
+ const encoded = work_docx_table_styles_wordAttribute(element, 'val')?.trim();
1549
+ if (encoded && /^[0-9a-f]{1,4}$/i.test(encoded)) {
1550
+ const value = Number.parseInt(encoded, 16);
1551
+ look.firstRow = Boolean(value & TABLE_LOOK_BITS.firstRow);
1552
+ look.lastRow = Boolean(value & TABLE_LOOK_BITS.lastRow);
1553
+ look.firstColumn = Boolean(value & TABLE_LOOK_BITS.firstColumn);
1554
+ look.lastColumn = Boolean(value & TABLE_LOOK_BITS.lastColumn);
1555
+ look.noHorizontalBand = Boolean(value & TABLE_LOOK_BITS.noHorizontalBand);
1556
+ look.noVerticalBand = Boolean(value & TABLE_LOOK_BITS.noVerticalBand);
1557
+ }
1558
+ assignLookFlag(look, 'firstRow', element, 'firstRow');
1559
+ assignLookFlag(look, 'lastRow', element, 'lastRow');
1560
+ assignLookFlag(look, 'firstColumn', element, 'firstColumn');
1561
+ assignLookFlag(look, 'lastColumn', element, 'lastColumn');
1562
+ assignLookFlag(look, 'noHorizontalBand', element, 'noHBand');
1563
+ assignLookFlag(look, 'noVerticalBand', element, 'noVBand');
1564
+ }
1565
+ return look;
1566
+ }
1567
+ function assignLookFlag(look, key, element, attributeName) {
1568
+ const value = onOffValue(work_docx_table_styles_wordAttribute(element, attributeName));
1569
+ if (void 0 !== value) look[key] = value;
1570
+ }
1571
+ function resolveBandSize(propertySources, propertyName) {
1572
+ let size = 1;
1573
+ for (const properties of propertySources){
1574
+ const element = directChild(properties, propertyName);
1575
+ const value = Number(element ? work_docx_table_styles_wordAttribute(element, 'val') : void 0);
1576
+ if (Number.isInteger(value) && value > 0 && value <= 64) size = value;
1577
+ }
1578
+ return size;
1579
+ }
1580
+ function tableCellPosition(table, targetCell) {
1581
+ const rows = descendants(table, 'tr').filter((row)=>work_docx_table_styles_closestAncestor(row, 'tbl') === table);
1582
+ const targetRow = work_docx_table_styles_closestAncestor(targetCell, 'tr');
1583
+ if (!targetRow) return null;
1584
+ const rowIndex = rows.indexOf(targetRow);
1585
+ if (rowIndex < 0) return null;
1586
+ const cells = rowCells(targetRow);
1587
+ const cellIndex = cells.indexOf(targetCell);
1588
+ if (cellIndex < 0) return null;
1589
+ const columnStart = rowGridOffset(targetRow, 'gridBefore') + cells.slice(0, cellIndex).reduce((total, cell)=>total + cellGridSpan(cell), 0);
1590
+ const columnEnd = columnStart + cellGridSpan(targetCell) - 1;
1591
+ const columnCount = Math.max(1, ...rows.map((row)=>rowGridOffset(row, 'gridBefore') + rowCells(row).reduce((total, cell)=>total + cellGridSpan(cell), 0) + rowGridOffset(row, 'gridAfter')));
1592
+ return {
1593
+ rowIndex,
1594
+ rowCount: rows.length,
1595
+ columnStart,
1596
+ columnEnd,
1597
+ columnCount
1598
+ };
1599
+ }
1600
+ function rowCells(row) {
1601
+ return descendants(row, 'tc').filter((cell)=>work_docx_table_styles_closestAncestor(cell, 'tr') === row);
1602
+ }
1603
+ function cellGridSpan(cell) {
1604
+ const properties = directChild(cell, 'tcPr');
1605
+ const gridSpan = properties ? directChild(properties, 'gridSpan') : void 0;
1606
+ const value = Number(gridSpan ? work_docx_table_styles_wordAttribute(gridSpan, 'val') : void 0);
1607
+ return Number.isInteger(value) && value > 0 && value <= 256 ? value : 1;
1608
+ }
1609
+ function rowGridOffset(row, propertyName) {
1610
+ const properties = directChild(row, 'trPr');
1611
+ const element = properties ? directChild(properties, propertyName) : void 0;
1612
+ const value = Number(element ? work_docx_table_styles_wordAttribute(element, 'val') : void 0);
1613
+ return Number.isInteger(value) && value > 0 && value <= 256 ? value : 0;
1614
+ }
1615
+ function work_docx_table_styles_closestAncestor(element, localName) {
1616
+ let current = element;
1617
+ while(current){
1618
+ if (current.localName === localName) return current;
1619
+ current = current.parentElement;
1620
+ }
1621
+ return null;
1622
+ }
1623
+ function work_docx_table_styles_onOffAttribute(element, name) {
1624
+ return onOffValue(work_docx_table_styles_wordAttribute(element, name)) ?? false;
1625
+ }
1626
+ function onOffValue(value) {
1627
+ if (null == value) return;
1628
+ const normalized = value.trim().toLowerCase();
1629
+ return '0' !== normalized && 'false' !== normalized && 'off' !== normalized;
1630
+ }
1631
+ function work_docx_table_styles_wordAttribute(element, name) {
1632
+ return attribute(element, name) ?? attribute(element, `w:${name}`);
1633
+ }
1382
1634
  const work_docx_paragraph_direction_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
1383
1635
  const work_docx_paragraph_direction_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
1384
1636
  const PARAGRAPH_DIRECTION_MARKER_PATTERN = /__A3S_WORK_PARAGRAPH_DIRECTION_\d+__/g;
1385
- function markDocxParagraphDirections(document, styleSource) {
1637
+ function markDocxParagraphDirections(document, styleSource, tableStyleSource) {
1386
1638
  const paragraphs = [];
1387
1639
  const styles = resolveDocxParagraphStyleResolver(styleSource);
1640
+ const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
1388
1641
  for (const paragraph of descendants(document, 'p')){
1389
1642
  let properties = directChild(paragraph, 'pPr');
1390
- const sources = docxParagraphPropertySources(properties, styles);
1643
+ const sources = docxParagraphPropertySources(properties, styles, docxTableParagraphPropertySources(paragraph, tableStyles));
1391
1644
  const direction = paragraphDirection(sources);
1392
1645
  if (!direction) continue;
1393
1646
  properties ??= insertParagraphProperties(document, paragraph);
@@ -1425,11 +1678,11 @@ function paragraphDirection(propertySources) {
1425
1678
  let direction = null;
1426
1679
  for (const properties of propertySources){
1427
1680
  const bidi = directChild(properties, 'bidi');
1428
- if (bidi) direction = onOffValue(bidi) ? 'rtl' : 'ltr';
1681
+ if (bidi) direction = work_docx_paragraph_direction_import_onOffValue(bidi) ? 'rtl' : 'ltr';
1429
1682
  }
1430
1683
  return direction;
1431
1684
  }
1432
- function onOffValue(element) {
1685
+ function work_docx_paragraph_direction_import_onOffValue(element) {
1433
1686
  const value = (attribute(element, 'val') ?? attribute(element, 'w:val'))?.trim().toLowerCase();
1434
1687
  return '0' !== value && 'false' !== value && 'off' !== value;
1435
1688
  }
@@ -1461,12 +1714,13 @@ function work_docx_paragraph_direction_import_textNodes(root) {
1461
1714
  const work_docx_paragraph_alignment_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
1462
1715
  const work_docx_paragraph_alignment_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
1463
1716
  const PARAGRAPH_ALIGNMENT_MARKER_PATTERN = /__A3S_WORK_PARAGRAPH_ALIGNMENT_\d+__/g;
1464
- function markDocxParagraphAlignments(document, styleSource) {
1717
+ function markDocxParagraphAlignments(document, styleSource, tableStyleSource) {
1465
1718
  const paragraphs = [];
1466
1719
  const styles = resolveDocxParagraphStyleResolver(styleSource);
1720
+ const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
1467
1721
  for (const paragraph of descendants(document, 'p')){
1468
1722
  let properties = directChild(paragraph, 'pPr');
1469
- const sources = docxParagraphPropertySources(properties, styles);
1723
+ const sources = docxParagraphPropertySources(properties, styles, docxTableParagraphPropertySources(paragraph, tableStyles));
1470
1724
  const alignment = paragraphAlignment(sources);
1471
1725
  if (!alignment) continue;
1472
1726
  properties ??= work_docx_paragraph_alignment_import_insertParagraphProperties(document, paragraph);
@@ -1591,12 +1845,13 @@ const work_docx_paragraph_indent_import_WORD_NAMESPACE = 'http://schemas.openxml
1591
1845
  const work_docx_paragraph_indent_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
1592
1846
  const TWIPS_PER_CSS_PIXEL = 15;
1593
1847
  const PARAGRAPH_INDENT_MARKER_PATTERN = /__A3S_WORK_PARAGRAPH_INDENT_\d+__/g;
1594
- function markDocxParagraphIndents(document, styleSource) {
1848
+ function markDocxParagraphIndents(document, styleSource, tableStyleSource) {
1595
1849
  const paragraphs = [];
1596
1850
  const styles = resolveDocxParagraphStyleResolver(styleSource);
1851
+ const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
1597
1852
  for (const paragraph of descendants(document, 'p')){
1598
1853
  let properties = directChild(paragraph, 'pPr');
1599
- const sources = docxParagraphPropertySources(properties, styles);
1854
+ const sources = docxParagraphPropertySources(properties, styles, docxTableParagraphPropertySources(paragraph, tableStyles));
1600
1855
  if (sources.some((source)=>directChild(source, 'numPr'))) continue;
1601
1856
  const indent = paragraphIndent(sources);
1602
1857
  if (!indent.left && !indent.right && !indent.firstLine) continue;
@@ -1709,13 +1964,14 @@ function work_docx_paragraph_indent_import_textNodes(root) {
1709
1964
  const work_docx_paragraph_pagination_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
1710
1965
  const work_docx_paragraph_pagination_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
1711
1966
  const PARAGRAPH_PAGINATION_MARKER_PATTERN = /__A3S_WORK_PARAGRAPH_PAGINATION_\d+__/g;
1712
- function markDocxParagraphPagination(document, styleSource) {
1967
+ function markDocxParagraphPagination(document, styleSource, tableStyleSource) {
1713
1968
  const paragraphs = [];
1714
1969
  const styles = resolveDocxParagraphStyleResolver(styleSource);
1970
+ const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
1715
1971
  for (const paragraph of descendants(document, 'p')){
1716
1972
  let properties = directChild(paragraph, 'pPr');
1717
1973
  if (properties && directChild(properties, 'numPr')) continue;
1718
- const pagination = paragraphPagination(docxParagraphPropertySources(properties, styles));
1974
+ const pagination = paragraphPagination(docxParagraphPropertySources(properties, styles, docxTableParagraphPropertySources(paragraph, tableStyles)));
1719
1975
  if (!Object.keys(pagination).length) continue;
1720
1976
  properties ??= work_docx_paragraph_pagination_import_insertParagraphProperties(document, paragraph);
1721
1977
  const marker = `__A3S_WORK_PARAGRAPH_PAGINATION_${paragraphs.length + 1}__`;
@@ -1803,12 +2059,13 @@ function work_docx_paragraph_pagination_import_textNodes(root) {
1803
2059
  const work_docx_paragraph_spacing_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
1804
2060
  const work_docx_paragraph_spacing_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
1805
2061
  const PARAGRAPH_SPACING_MARKER_PATTERN = /__A3S_WORK_PARAGRAPH_SPACING_\d+__/g;
1806
- function markDocxParagraphSpacing(document, styleSource) {
2062
+ function markDocxParagraphSpacing(document, styleSource, tableStyleSource) {
1807
2063
  const paragraphs = [];
1808
2064
  const styles = resolveDocxParagraphStyleResolver(styleSource);
2065
+ const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
1809
2066
  for (const paragraph of descendants(document, 'p')){
1810
2067
  let properties = directChild(paragraph, 'pPr');
1811
- const sources = docxParagraphPropertySources(properties, styles);
2068
+ const sources = docxParagraphPropertySources(properties, styles, docxTableParagraphPropertySources(paragraph, tableStyles));
1812
2069
  if (sources.some((source)=>directChild(source, 'numPr'))) continue;
1813
2070
  const spacing = paragraphSpacing(sources);
1814
2071
  if (!Object.keys(spacing).length) continue;
@@ -1885,6 +2142,14 @@ function applyParagraphSpacing(element, spacing) {
1885
2142
  }
1886
2143
  if (spacing.lineHeight) element.style.lineHeight = spacing.lineHeight;
1887
2144
  if (spacing.lineRule) element.dataset.officeLineRule = spacing.lineRule;
2145
+ if ('auto' === spacing.lineRule) {
2146
+ const autoLineHeight = documentAutoLineHeight(spacing.lineHeight);
2147
+ for (const [name, value] of Object.entries(renderDocumentAutoLineHeight(spacing.lineHeight, autoLineHeight)))if ('style' === name) for (const declaration of value.split(';')){
2148
+ const separator = declaration.indexOf(':');
2149
+ if (!(separator < 0)) element.style.setProperty(declaration.slice(0, separator).trim(), declaration.slice(separator + 1).trim());
2150
+ }
2151
+ else element.setAttribute(name, value);
2152
+ }
1888
2153
  }
1889
2154
  function work_docx_paragraph_spacing_import_insertParagraphMarker(document, paragraph, properties, marker) {
1890
2155
  const run = document.createElementNS(work_docx_paragraph_spacing_import_WORD_NAMESPACE, 'w:r');
@@ -2020,10 +2285,11 @@ function isDocxThemeResolver(source) {
2020
2285
  const work_docx_run_formatting_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
2021
2286
  const work_docx_run_formatting_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
2022
2287
  const RUN_FORMATTING_MARKER_PATTERN = /__A3S_WORK_RUN_(?:START|END)_\d+__/g;
2023
- function markDocxRunFormatting(document, styleSource, themeSource) {
2288
+ function markDocxRunFormatting(document, styleSource, themeSource, tableStyleSource) {
2024
2289
  const runs = [];
2025
2290
  const styles = resolveDocxParagraphStyleResolver(styleSource);
2026
2291
  const theme = resolveDocxThemeResolver(themeSource);
2292
+ const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
2027
2293
  for (const run of descendants(document, 'r')){
2028
2294
  const runText = directRunText(run);
2029
2295
  if (!runText || runText.includes('__A3S_')) continue;
@@ -2031,7 +2297,7 @@ function markDocxRunFormatting(document, styleSource, themeSource) {
2031
2297
  if (!paragraph) continue;
2032
2298
  const paragraphProperties = directChild(paragraph, 'pPr');
2033
2299
  const runProperties = directChild(run, 'rPr');
2034
- const formatting = resolvedRunFormatting(docxRunPropertySources(paragraphProperties, runProperties, styles), theme);
2300
+ const formatting = resolvedRunFormatting(docxRunPropertySources(paragraphProperties, runProperties, styles, docxTableRunPropertySources(run, tableStyles)), theme);
2035
2301
  if (!Object.keys(formatting).length) continue;
2036
2302
  const index = runs.length + 1;
2037
2303
  const startMarker = `__A3S_WORK_RUN_START_${index}__`;
@@ -2050,8 +2316,9 @@ function markDocxRunFormatting(document, styleSource, themeSource) {
2050
2316
  function applyImportedDocxRunFormattingMarkers(document, markers) {
2051
2317
  const replacements = new Map();
2052
2318
  for (const marker of markers.runs){
2053
- replacements.set(marker.startMarker, formattingSpanStart(document, marker.formatting));
2054
- replacements.set(marker.endMarker, '</span>');
2319
+ const markup = formattingMarkup(document, marker.formatting);
2320
+ replacements.set(marker.startMarker, markup.start);
2321
+ replacements.set(marker.endMarker, markup.end);
2055
2322
  }
2056
2323
  document.body.innerHTML = document.body.innerHTML.replace(RUN_FORMATTING_MARKER_PATTERN, (marker)=>replacements.get(marker) ?? '');
2057
2324
  }
@@ -2063,7 +2330,18 @@ function resolvedRunFormatting(propertySources, theme) {
2063
2330
  let fontSize;
2064
2331
  let color;
2065
2332
  let backgroundColor;
2333
+ let bold;
2334
+ let italic;
2335
+ let underline;
2336
+ let strike;
2337
+ let snapToGrid;
2066
2338
  for (const properties of propertySources){
2339
+ bold = overriddenBoolean(bold, onOffProperty(properties, 'b'));
2340
+ italic = overriddenBoolean(italic, onOffProperty(properties, 'i'));
2341
+ underline = overriddenBoolean(underline, underlineProperty(properties));
2342
+ strike = overriddenBoolean(strike, onOffProperty(properties, 'strike'));
2343
+ strike = overriddenBoolean(strike, onOffProperty(properties, 'dstrike'));
2344
+ snapToGrid = overriddenBoolean(snapToGrid, onOffProperty(properties, 'snapToGrid'));
2067
2345
  const runFonts = directChild(properties, 'rFonts');
2068
2346
  if (runFonts) {
2069
2347
  assignFont(fonts, 'ascii', resolvedFont(runFonts, 'ascii', 'asciiTheme', theme));
@@ -2094,19 +2372,42 @@ function resolvedRunFormatting(propertySources, theme) {
2094
2372
  else if (fill && /^[0-9a-f]{6}$/i.test(fill)) backgroundColor = `#${fill.toLowerCase()}`;
2095
2373
  }
2096
2374
  }
2097
- const fontFamily = uniqueFonts([
2375
+ let fontFamily = uniqueFonts([
2098
2376
  fonts.eastAsia,
2099
2377
  fonts.hAnsi,
2100
2378
  fonts.ascii,
2101
2379
  fonts.complex
2102
2380
  ]);
2381
+ if (!fontFamily) fontFamily = uniqueFonts([
2382
+ docxThemeFont(theme, 'minorEastAsia'),
2383
+ docxThemeFont(theme, 'minorHAnsi'),
2384
+ docxThemeFont(theme, 'minorAscii'),
2385
+ docxThemeFont(theme, 'minorBidi')
2386
+ ]);
2387
+ const hasRunPropertySource = propertySources.length > 0;
2103
2388
  return {
2389
+ ...void 0 !== bold || hasRunPropertySource ? {
2390
+ bold: bold ?? false
2391
+ } : {},
2392
+ ...void 0 !== italic || hasRunPropertySource ? {
2393
+ italic: italic ?? false
2394
+ } : {},
2395
+ ...void 0 !== underline || hasRunPropertySource ? {
2396
+ underline: underline ?? false
2397
+ } : {},
2398
+ ...void 0 !== strike || hasRunPropertySource ? {
2399
+ strike: strike ?? false
2400
+ } : {},
2104
2401
  ...fontFamily ? {
2105
- fontFamily
2402
+ fontFamily,
2403
+ wordLineHeightFactor: documentWordLineHeightFactor(fontFamily)
2106
2404
  } : {},
2107
2405
  ...void 0 !== fontSize ? {
2108
2406
  fontSize
2109
2407
  } : {},
2408
+ ...void 0 !== snapToGrid ? {
2409
+ wordSnapToGrid: snapToGrid
2410
+ } : {},
2110
2411
  ...color ? {
2111
2412
  color
2112
2413
  } : {},
@@ -2127,14 +2428,57 @@ function work_docx_run_formatting_import_markerText(document, marker) {
2127
2428
  text.textContent = marker;
2128
2429
  return text;
2129
2430
  }
2130
- function formattingSpanStart(document, formatting) {
2431
+ function formattingMarkup(document, formatting) {
2131
2432
  const span = document.createElement('span');
2433
+ if (false === formatting.bold) span.style.fontWeight = 'normal';
2434
+ if (false === formatting.italic) span.style.fontStyle = 'normal';
2435
+ if ((false === formatting.underline || false === formatting.strike) && !formatting.underline && !formatting.strike) span.style.textDecorationLine = 'none';
2132
2436
  if (formatting.fontFamily) span.style.fontFamily = formatting.fontFamily;
2437
+ if (void 0 !== formatting.wordLineHeightFactor) {
2438
+ const factor = formatLineHeightFactor(formatting.wordLineHeightFactor);
2439
+ span.dataset.officeWordLineHeightFactor = factor;
2440
+ span.style.setProperty('--work-document-word-line-height-factor', factor);
2441
+ }
2442
+ if (void 0 !== formatting.wordSnapToGrid) span.dataset.officeWordSnapToGrid = String(formatting.wordSnapToGrid);
2133
2443
  if (void 0 !== formatting.fontSize) span.style.fontSize = `${work_docx_run_formatting_import_formatNumber(formatting.fontSize)}pt`;
2134
2444
  if (formatting.color) span.style.color = formatting.color;
2135
2445
  if (formatting.backgroundColor) span.style.backgroundColor = formatting.backgroundColor;
2136
2446
  const html = span.outerHTML;
2137
- return html.slice(0, html.indexOf('>') + 1);
2447
+ const tags = [
2448
+ ...formatting.bold ? [
2449
+ 'strong'
2450
+ ] : [],
2451
+ ...formatting.italic ? [
2452
+ 'em'
2453
+ ] : [],
2454
+ ...formatting.underline ? [
2455
+ 'u'
2456
+ ] : [],
2457
+ ...formatting.strike ? [
2458
+ 's'
2459
+ ] : []
2460
+ ];
2461
+ return {
2462
+ start: `${html.slice(0, html.indexOf('>') + 1)}${tags.map((tag)=>`<${tag}>`).join('')}`,
2463
+ end: `${[
2464
+ ...tags
2465
+ ].reverse().map((tag)=>`</${tag}>`).join('')}</span>`
2466
+ };
2467
+ }
2468
+ function overriddenBoolean(current, next) {
2469
+ return void 0 === next ? current : next;
2470
+ }
2471
+ function onOffProperty(properties, propertyName) {
2472
+ const element = directChild(properties, propertyName);
2473
+ if (!element) return;
2474
+ const value = work_docx_run_formatting_import_wordAttribute(element, 'val')?.trim().toLowerCase();
2475
+ return '0' !== value && 'false' !== value && 'off' !== value;
2476
+ }
2477
+ function underlineProperty(properties) {
2478
+ const element = directChild(properties, 'u');
2479
+ if (!element) return;
2480
+ const value = work_docx_run_formatting_import_wordAttribute(element, 'val')?.trim().toLowerCase();
2481
+ return '0' !== value && 'false' !== value && 'off' !== value && 'none' !== value;
2138
2482
  }
2139
2483
  function directRunText(run) {
2140
2484
  return Array.from(run.children).filter((child)=>'t' === child.localName || 'delText' === child.localName).map((child)=>child.textContent ?? '').join('');
@@ -2200,18 +2544,22 @@ function wordHighlightColor(value) {
2200
2544
  function work_docx_run_formatting_import_formatNumber(value) {
2201
2545
  return Number(value.toFixed(2)).toString();
2202
2546
  }
2547
+ function formatLineHeightFactor(value) {
2548
+ return Number(value.toFixed(4)).toString();
2549
+ }
2203
2550
  const work_docx_tab_stop_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
2204
2551
  const work_docx_tab_stop_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
2205
2552
  const work_docx_tab_stop_import_TWIPS_PER_CSS_PIXEL = 15;
2206
2553
  const PARAGRAPH_TAB_STOP_MARKER_PATTERN = /__A3S_WORK_PARAGRAPH_TAB_STOPS_\d+__/g;
2207
2554
  const INLINE_TAB_MARKER_PATTERN = /__A3S_WORK_INLINE_TAB_\d+__/g;
2208
- function markDocxParagraphTabStops(document, styleSource) {
2555
+ function markDocxParagraphTabStops(document, styleSource, tableStyleSource) {
2209
2556
  const paragraphs = [];
2210
2557
  const inlineTabs = [];
2211
2558
  const styles = resolveDocxParagraphStyleResolver(styleSource);
2559
+ const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
2212
2560
  for (const paragraph of descendants(document, 'p')){
2213
2561
  let properties = directChild(paragraph, 'pPr');
2214
- const tabStops = resolvedParagraphTabStops(docxParagraphPropertySources(properties, styles));
2562
+ const tabStops = resolvedParagraphTabStops(docxParagraphPropertySources(properties, styles, docxTableParagraphPropertySources(paragraph, tableStyles)));
2215
2563
  if (tabStops.length) {
2216
2564
  properties ??= work_docx_tab_stop_import_insertParagraphProperties(document, paragraph);
2217
2565
  const marker = `__A3S_WORK_PARAGRAPH_TAB_STOPS_${paragraphs.length + 1}__`;
@@ -2357,20 +2705,42 @@ function work_docx_tab_stop_import_textNodes(root) {
2357
2705
  while(walker.nextNode())nodes.push(walker.currentNode);
2358
2706
  return nodes;
2359
2707
  }
2708
+ const TABLE_BORDER_EDGES = [
2709
+ 'top',
2710
+ 'right',
2711
+ 'bottom',
2712
+ 'left'
2713
+ ];
2360
2714
  const work_docx_table_cell_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
2361
2715
  const work_docx_table_cell_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
2362
2716
  const TABLE_CELL_MARKER_PATTERN = /__A3S_WORK_TABLE_CELL_\d+__/g;
2363
- function markDocxTableCells(document) {
2717
+ const PIXELS_PER_TWIP = 96 / 1440;
2718
+ function markDocxTableCells(document, themeSource, tableStyleSource) {
2364
2719
  const cells = [];
2720
+ const theme = resolveDocxThemeResolver(themeSource);
2721
+ const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
2365
2722
  for (const cell of descendants(document, 'tc')){
2366
2723
  const properties = directChild(cell, 'tcPr');
2367
- const shading = properties ? directChild(properties, 'shd') : void 0;
2368
- const verticalAlignment = properties ? directChild(properties, 'vAlign') : void 0;
2369
- const directBorders = properties ? uniformBorders(directChild(properties, 'tcBorders')) : null;
2370
- const border = directBorders ?? uniformTableBorders(cell);
2371
- const backgroundColor = ooxmlColor(attribute(shading ?? cell, 'fill'));
2372
- const verticalAlign = tableVerticalAlign(attribute(verticalAlignment ?? cell, 'val'));
2373
- if (!backgroundColor && !verticalAlign && !border) continue;
2724
+ const table = work_docx_table_cell_import_closestAncestor(cell, 'tbl');
2725
+ const directTableProperties = table ? directChild(table, 'tblPr') : void 0;
2726
+ const layers = [
2727
+ ...docxTableCellStyleLayers(cell, tableStyles),
2728
+ ...directTableProperties ? [
2729
+ {
2730
+ tableProperties: directTableProperties
2731
+ }
2732
+ ] : [],
2733
+ ...properties ? [
2734
+ {
2735
+ cellProperties: properties
2736
+ }
2737
+ ] : []
2738
+ ];
2739
+ const borders = importedTableCellBorders(cell, layers, theme);
2740
+ const backgroundColor = importedTableCellBackgroundColor(layers, theme);
2741
+ const verticalAlign = importedTableCellVerticalAlign(layers);
2742
+ const margins = importedTableCellMargins(layers);
2743
+ if (!backgroundColor && !verticalAlign && !borders && !margins) continue;
2374
2744
  const paragraph = firstTableCellParagraph(document, cell);
2375
2745
  if (!paragraph) continue;
2376
2746
  const marker = `__A3S_WORK_TABLE_CELL_${cells.length + 1}__`;
@@ -2383,10 +2753,11 @@ function markDocxTableCells(document) {
2383
2753
  ...verticalAlign ? {
2384
2754
  verticalAlign
2385
2755
  } : {},
2386
- ...border ? {
2387
- borderColor: border.color,
2388
- borderStyle: border.style,
2389
- borderWidth: border.width
2756
+ ...borders ? {
2757
+ borders
2758
+ } : {},
2759
+ ...margins ? {
2760
+ margins
2390
2761
  } : {}
2391
2762
  });
2392
2763
  }
@@ -2422,44 +2793,130 @@ function applyCellFormat(cell, format) {
2422
2793
  cell.dataset.officeCellVerticalAlign = format.verticalAlign;
2423
2794
  cell.style.verticalAlign = format.verticalAlign;
2424
2795
  }
2425
- if (format.borderColor && format.borderStyle && void 0 !== format.borderWidth) {
2426
- cell.dataset.officeCellBorderColor = format.borderColor;
2427
- cell.dataset.officeCellBorderStyle = format.borderStyle;
2428
- cell.dataset.officeCellBorderWidth = String(format.borderWidth);
2429
- cell.style.border = 'none' === format.borderStyle || 0 === format.borderWidth ? '0px none transparent' : `${format.borderWidth}px ${format.borderStyle} ${format.borderColor}`;
2796
+ if (format.borders) {
2797
+ const borders = documentTableBordersFromElement(cell, {
2798
+ color: '#cfd5df',
2799
+ style: 'solid',
2800
+ width: 1
2801
+ });
2802
+ for (const edge of TABLE_BORDER_EDGES){
2803
+ const border = format.borders[edge];
2804
+ if (border) borders[edge] = {
2805
+ ...border
2806
+ };
2807
+ }
2808
+ const rendered = renderDocumentTableBorders(borders);
2809
+ for (const [name, value] of Object.entries(rendered))if ('style' !== name) cell.setAttribute(name, value);
2810
+ cell.style.cssText = `${cell.style.cssText}; ${rendered.style}`;
2811
+ }
2812
+ if (format.margins) {
2813
+ const rendered = renderDocumentTableCellMarginOverrides(format.margins);
2814
+ for (const [name, value] of Object.entries(rendered))if ('style' !== name) cell.setAttribute(name, value);
2815
+ if (rendered.style) cell.style.cssText = `${cell.style.cssText}; ${rendered.style}`;
2816
+ }
2817
+ }
2818
+ function importedTableCellMargins(layers) {
2819
+ const margins = {};
2820
+ for (const layer of layers){
2821
+ const marginElement = layer.cellProperties ? directChild(layer.cellProperties, 'tcMar') : void 0;
2822
+ if (!marginElement) continue;
2823
+ const children = new Map(directChildren(marginElement).map((margin)=>[
2824
+ margin.localName,
2825
+ margin
2826
+ ]));
2827
+ assignCellMargin(margins, 'top', children.get('top'));
2828
+ assignCellMargin(margins, 'right', children.get('right') ?? children.get('end'));
2829
+ assignCellMargin(margins, 'bottom', children.get('bottom'));
2830
+ assignCellMargin(margins, 'left', children.get('left') ?? children.get('start'));
2831
+ }
2832
+ return Object.keys(margins).length ? margins : null;
2833
+ }
2834
+ function assignCellMargin(target, side, element) {
2835
+ if (!element) return;
2836
+ const type = attribute(element, 'type');
2837
+ if (type && 'dxa' !== type) return;
2838
+ const twips = Number(attribute(element, 'w'));
2839
+ if (!Number.isFinite(twips) || twips < 0) return;
2840
+ target[side] = Math.round(twips * PIXELS_PER_TWIP * 100) / 100;
2841
+ }
2842
+ function importedTableCellBorders(cell, layers, theme) {
2843
+ const borders = {};
2844
+ for (const layer of layers){
2845
+ if (layer.tableProperties) mergeBorders(borders, tableBordersForCell(cell, layer.tableProperties, theme));
2846
+ if (layer.cellProperties) mergeBorders(borders, borderEdges(directChild(layer.cellProperties, 'tcBorders'), theme));
2430
2847
  }
2848
+ return Object.keys(borders).length ? borders : null;
2431
2849
  }
2432
- function uniformTableBorders(cell) {
2850
+ function tableBordersForCell(cell, properties, theme) {
2433
2851
  const table = work_docx_table_cell_import_closestAncestor(cell, 'tbl');
2434
- const properties = table ? directChild(table, 'tblPr') : void 0;
2435
- return properties ? uniformBorders(directChild(properties, 'tblBorders'), true) : null;
2436
- }
2437
- function uniformBorders(borders, includeInside = false) {
2438
- if (!borders) return null;
2439
- const edgeNames = includeInside ? [
2440
- 'top',
2441
- 'right',
2442
- 'bottom',
2443
- 'left',
2444
- 'insideH',
2445
- 'insideV'
2446
- ] : [
2447
- 'top',
2448
- 'right',
2449
- 'bottom',
2450
- 'left'
2451
- ];
2452
- const edgeElements = new Map(directChildren(borders).map((edge)=>[
2852
+ const borders = borderElementMap(directChild(properties, 'tblBorders'));
2853
+ if (!table || !borders.size) return {};
2854
+ const row = work_docx_table_cell_import_closestAncestor(cell, 'tr');
2855
+ if (!row) return {};
2856
+ const rows = descendants(table, 'tr').filter((candidate)=>work_docx_table_cell_import_closestAncestor(candidate, 'tbl') === table);
2857
+ const cells = descendants(row, 'tc').filter((candidate)=>work_docx_table_cell_import_closestAncestor(candidate, 'tr') === row);
2858
+ const rowIndex = rows.indexOf(row);
2859
+ const cellIndex = cells.indexOf(cell);
2860
+ if (rowIndex < 0 || cellIndex < 0) return {};
2861
+ return compactBorders({
2862
+ top: parseBorder(borders.get(0 === rowIndex ? 'top' : 'insideH'), theme),
2863
+ right: parseBorder(borderElement(borders, cellIndex === cells.length - 1 ? [
2864
+ 'right',
2865
+ 'end'
2866
+ ] : [
2867
+ 'insideV'
2868
+ ]), theme),
2869
+ bottom: parseBorder(borders.get(rowIndex === rows.length - 1 ? 'bottom' : 'insideH'), theme),
2870
+ left: parseBorder(borderElement(borders, 0 === cellIndex ? [
2871
+ 'left',
2872
+ 'start'
2873
+ ] : [
2874
+ 'insideV'
2875
+ ]), theme)
2876
+ });
2877
+ }
2878
+ function mergeBorders(target, source) {
2879
+ for (const edge of TABLE_BORDER_EDGES){
2880
+ const border = source[edge];
2881
+ if (border) target[edge] = border;
2882
+ }
2883
+ }
2884
+ function borderEdges(borders, theme) {
2885
+ const edges = borderElementMap(borders);
2886
+ return compactBorders({
2887
+ top: parseBorder(edges.get('top'), theme),
2888
+ right: parseBorder(borderElement(edges, [
2889
+ 'right',
2890
+ 'end'
2891
+ ]), theme),
2892
+ bottom: parseBorder(edges.get('bottom'), theme),
2893
+ left: parseBorder(borderElement(edges, [
2894
+ 'left',
2895
+ 'start'
2896
+ ]), theme)
2897
+ });
2898
+ }
2899
+ function borderElementMap(borders) {
2900
+ return new Map(borders ? directChildren(borders).map((edge)=>[
2453
2901
  edge.localName,
2454
2902
  edge
2455
- ]));
2456
- const formats = edgeNames.map((name)=>parseBorder(edgeElements.get(name)));
2457
- if (formats.some((format)=>!format)) return null;
2458
- const first = formats[0];
2459
- if (!first) return null;
2460
- return formats.every((format)=>format?.color === first.color && format.style === first.style && format.width === first.width) ? first : null;
2903
+ ]) : []);
2461
2904
  }
2462
- function parseBorder(edge) {
2905
+ function borderElement(borders, names) {
2906
+ for (const name of names){
2907
+ const edge = borders.get(name);
2908
+ if (edge) return edge;
2909
+ }
2910
+ }
2911
+ function compactBorders(borders) {
2912
+ const result = {};
2913
+ for (const edge of TABLE_BORDER_EDGES){
2914
+ const border = borders[edge];
2915
+ if (border) result[edge] = border;
2916
+ }
2917
+ return result;
2918
+ }
2919
+ function parseBorder(edge, theme) {
2463
2920
  if (!edge) return null;
2464
2921
  const style = tableBorderStyle(attribute(edge, 'val'));
2465
2922
  if (!style) return null;
@@ -2468,7 +2925,8 @@ function parseBorder(edge) {
2468
2925
  style,
2469
2926
  width: 0
2470
2927
  };
2471
- const color = ooxmlColor(attribute(edge, 'color')) ?? '#000000';
2928
+ const themed = docxThemeColor(theme, attribute(edge, 'themeColor'), attribute(edge, 'themeTint'), attribute(edge, 'themeShade'));
2929
+ const color = themed ? `#${themed}` : ooxmlColor(attribute(edge, 'color')) ?? '#000000';
2472
2930
  const size = Number(attribute(edge, 'sz'));
2473
2931
  const width = Number.isFinite(size) && size > 0 ? size / 6 : 1;
2474
2932
  return {
@@ -2477,6 +2935,30 @@ function parseBorder(edge) {
2477
2935
  width: Math.max(0.5, Math.min(6, Math.round(2 * width) / 2))
2478
2936
  };
2479
2937
  }
2938
+ function importedTableCellBackgroundColor(layers, theme) {
2939
+ let color = null;
2940
+ for (const layer of layers){
2941
+ const tableShading = layer.tableProperties ? directChild(layer.tableProperties, 'shd') : void 0;
2942
+ const cellShading = layer.cellProperties ? directChild(layer.cellProperties, 'shd') : void 0;
2943
+ if (tableShading) color = tableCellBackgroundColor(tableShading, theme);
2944
+ if (cellShading) color = tableCellBackgroundColor(cellShading, theme);
2945
+ }
2946
+ return color;
2947
+ }
2948
+ function tableCellBackgroundColor(shading, theme) {
2949
+ const themed = docxThemeColor(theme, attribute(shading, 'themeFill'), attribute(shading, 'themeFillTint'), attribute(shading, 'themeFillShade'));
2950
+ return themed ? `#${themed}` : ooxmlColor(attribute(shading, 'fill'));
2951
+ }
2952
+ function importedTableCellVerticalAlign(layers) {
2953
+ let alignment = null;
2954
+ for (const layer of layers){
2955
+ const element = layer.cellProperties ? directChild(layer.cellProperties, 'vAlign') : void 0;
2956
+ if (!element) continue;
2957
+ const value = tableVerticalAlign(attribute(element, 'val'));
2958
+ if (value) alignment = value;
2959
+ }
2960
+ return alignment;
2961
+ }
2480
2962
  function tableBorderStyle(value) {
2481
2963
  const normalized = value?.trim();
2482
2964
  if (!normalized) return null;
@@ -2532,7 +3014,7 @@ function work_docx_table_cell_import_textNodes(root) {
2532
3014
  const work_docx_table_row_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
2533
3015
  const work_docx_table_row_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
2534
3016
  const TABLE_ROW_MARKER_PATTERN = /__A3S_WORK_TABLE_ROW_\d+__/g;
2535
- const PIXELS_PER_TWIP = 96 / 1440;
3017
+ const work_docx_table_row_import_PIXELS_PER_TWIP = 96 / 1440;
2536
3018
  function markDocxTableRows(document) {
2537
3019
  const rows = [];
2538
3020
  for (const row of descendants(document, 'tr')){
@@ -2625,7 +3107,7 @@ function tableRowHeightRule(value) {
2625
3107
  }
2626
3108
  function work_docx_table_row_import_twipsToPixels(value) {
2627
3109
  if (!Number.isFinite(value) || value <= 0) return null;
2628
- return Math.round(value * PIXELS_PER_TWIP * 100) / 100;
3110
+ return Math.round(value * work_docx_table_row_import_PIXELS_PER_TWIP * 100) / 100;
2629
3111
  }
2630
3112
  function work_docx_table_row_import_closestAncestor(element, localName) {
2631
3113
  let current = element;
@@ -2647,21 +3129,19 @@ const work_docx_table_sizing_import_WORD_NAMESPACE = 'http://schemas.openxmlform
2647
3129
  const work_docx_table_sizing_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
2648
3130
  const TABLE_SIZING_MARKER_PATTERN = /__A3S_WORK_TABLE_SIZING_\d+__/g;
2649
3131
  const work_docx_table_sizing_import_PIXELS_PER_TWIP = 96 / 1440;
2650
- function markDocxTableSizing(document) {
3132
+ function markDocxTableSizing(document, tableStyleSource) {
2651
3133
  const tables = [];
3134
+ const tableStyles = resolveDocxTableStyleResolver(tableStyleSource);
2652
3135
  for (const table of descendants(document, 'tbl')){
2653
3136
  const paragraph = firstTableParagraph(document, table);
2654
3137
  if (!paragraph) continue;
2655
- const properties = directChild(table, 'tblPr');
2656
- const layout = properties ? directChild(properties, 'tblLayout') : void 0;
2657
- const preferredWidth = properties ? directChild(properties, 'tblW') : void 0;
2658
3138
  const grid = directChild(table, 'tblGrid');
2659
- const columnWidths = grid ? directChildren(grid, 'gridCol').map((column)=>work_docx_table_sizing_import_twipsToPixels(Number(attribute(column, 'w')))).filter((width)=>null !== width) : [];
3139
+ const columnWidths = grid ? directChildren(grid, 'gridCol').map((column)=>work_docx_table_sizing_import_twipsToPixels(Number(attribute(column, 'w')), false)).filter((width)=>null !== width) : [];
2660
3140
  const marker = `__A3S_WORK_TABLE_SIZING_${tables.length + 1}__`;
2661
3141
  insertMarker(document, paragraph, marker);
2662
3142
  tables.push({
2663
3143
  marker,
2664
- layoutMode: importedTableLayoutMode(layout, preferredWidth),
3144
+ geometry: importedTableGeometry(docxTablePropertySources(table, tableStyles)),
2665
3145
  columnWidths
2666
3146
  });
2667
3147
  }
@@ -2680,8 +3160,9 @@ function applyImportedDocxTableSizingMarkers(document, markers) {
2680
3160
  node.data = node.data.replace(TABLE_SIZING_MARKER_PATTERN, (marker)=>{
2681
3161
  const sizing = tableByMarker.get(marker);
2682
3162
  if (table instanceof HTMLTableElement && sizing) {
2683
- table.dataset.officeTableLayout = sizing.layoutMode;
2684
- if ('fixed' === sizing.layoutMode && sizing.columnWidths.length) applyColumnWidths(table, sizing.columnWidths);
3163
+ table.dataset.officeTableImported = 'true';
3164
+ applyDocumentTableGeometryToElement(table, sizing.geometry);
3165
+ if (sizing.columnWidths.length) applyColumnWidths(table, sizing.columnWidths);
2685
3166
  }
2686
3167
  return '';
2687
3168
  });
@@ -2691,12 +3172,104 @@ function applyImportedDocxTableSizingMarkers(document, markers) {
2691
3172
  function hasImportedDocxTableSizingMarkers(markers) {
2692
3173
  return markers.tables.length > 0;
2693
3174
  }
2694
- function importedTableLayoutMode(layout, preferredWidth) {
2695
- const layoutType = layout ? attribute(layout, 'type') : null;
2696
- const widthType = preferredWidth ? attribute(preferredWidth, 'type') : null;
2697
- if ('autofit' === layoutType || 'auto' === widthType) return 'contents';
2698
- if ('pct' === widthType) return 'window';
2699
- return 'fixed';
3175
+ function importedTableGeometry(propertySources) {
3176
+ let layout = DEFAULT_DOCUMENT_TABLE_GEOMETRY.layout;
3177
+ let width = {
3178
+ type: 'auto',
3179
+ value: null
3180
+ };
3181
+ let alignment = DEFAULT_DOCUMENT_TABLE_GEOMETRY.alignment;
3182
+ let indent = DEFAULT_DOCUMENT_TABLE_GEOMETRY.indent;
3183
+ let cellMargins = {
3184
+ ...DEFAULT_DOCUMENT_TABLE_CELL_MARGINS
3185
+ };
3186
+ for (const properties of propertySources){
3187
+ const layoutElement = directChild(properties, 'tblLayout');
3188
+ const layoutValue = layoutElement ? importedTableLayout(attribute(layoutElement, 'type')) : null;
3189
+ if (layoutValue) layout = layoutValue;
3190
+ const widthElement = directChild(properties, 'tblW');
3191
+ const widthValue = widthElement ? importedTablePreferredWidth(widthElement) : null;
3192
+ if (widthValue) width = widthValue;
3193
+ const alignmentElement = directChild(properties, 'jc');
3194
+ const alignmentValue = alignmentElement ? importedTableAlignment(attribute(alignmentElement, 'val')) : null;
3195
+ if (alignmentValue) alignment = alignmentValue;
3196
+ const indentElement = directChild(properties, 'tblInd');
3197
+ const indentValue = indentElement ? tableWidthPixels(indentElement, true) : null;
3198
+ if (null !== indentValue) indent = indentValue;
3199
+ const marginElement = directChild(properties, 'tblCellMar');
3200
+ if (marginElement) cellMargins = {
3201
+ ...cellMargins,
3202
+ ...importedCellMargins(marginElement)
3203
+ };
3204
+ }
3205
+ return {
3206
+ layout,
3207
+ width,
3208
+ alignment,
3209
+ indent,
3210
+ cellMargins
3211
+ };
3212
+ }
3213
+ function importedTableLayout(value) {
3214
+ if ('fixed' === value) return 'fixed';
3215
+ return 'autofit' === value ? 'autofit' : null;
3216
+ }
3217
+ function importedTablePreferredWidth(width) {
3218
+ const type = attribute(width, 'type');
3219
+ if ('auto' === type || 'nil' === type) return {
3220
+ type: 'auto',
3221
+ value: null
3222
+ };
3223
+ if ('pct' === type) {
3224
+ const value = percentageValue(attribute(width, 'w'));
3225
+ return null === value ? null : {
3226
+ type: 'percent',
3227
+ value
3228
+ };
3229
+ }
3230
+ if ('dxa' === type) {
3231
+ const value = tableWidthPixels(width, false);
3232
+ return null === value ? null : {
3233
+ type: 'pixels',
3234
+ value
3235
+ };
3236
+ }
3237
+ return null;
3238
+ }
3239
+ function importedTableAlignment(value) {
3240
+ if ('center' === value) return 'center';
3241
+ if ('right' === value || 'end' === value) return 'right';
3242
+ if ('left' === value || 'start' === value) return 'left';
3243
+ return null;
3244
+ }
3245
+ function importedCellMargins(margins) {
3246
+ const children = new Map(directChildren(margins).map((margin)=>[
3247
+ margin.localName,
3248
+ margin
3249
+ ]));
3250
+ const result = {};
3251
+ assignMargin(result, 'top', children.get('top'));
3252
+ assignMargin(result, 'right', children.get('right') ?? children.get('end'));
3253
+ assignMargin(result, 'bottom', children.get('bottom'));
3254
+ assignMargin(result, 'left', children.get('left') ?? children.get('start'));
3255
+ return result;
3256
+ }
3257
+ function assignMargin(target, side, element) {
3258
+ if (!element) return;
3259
+ const value = tableWidthPixels(element, true);
3260
+ if (null !== value) target[side] = value;
3261
+ }
3262
+ function tableWidthPixels(element, allowZero) {
3263
+ const type = attribute(element, 'type');
3264
+ if (type && 'dxa' !== type) return null;
3265
+ return work_docx_table_sizing_import_twipsToPixels(Number(attribute(element, 'w')), allowZero);
3266
+ }
3267
+ function percentageValue(value) {
3268
+ const normalized = value?.trim();
3269
+ if (!normalized) return null;
3270
+ const percentage = normalized.endsWith('%') ? Number(normalized.slice(0, -1)) : Number(normalized) / 50;
3271
+ if (!Number.isFinite(percentage) || percentage <= 0) return null;
3272
+ return Math.round(100 * percentage) / 100;
2700
3273
  }
2701
3274
  function applyColumnWidths(table, columnWidths) {
2702
3275
  const occupiedUntilRow = [];
@@ -2729,8 +3302,8 @@ function insertMarker(document, paragraph, marker) {
2729
3302
  const properties = directChild(paragraph, 'pPr');
2730
3303
  paragraph.insertBefore(run, properties?.nextSibling ?? paragraph.firstChild);
2731
3304
  }
2732
- function work_docx_table_sizing_import_twipsToPixels(value) {
2733
- if (!Number.isFinite(value) || value <= 0) return null;
3305
+ function work_docx_table_sizing_import_twipsToPixels(value, allowZero) {
3306
+ if (!Number.isFinite(value) || value < 0 || !allowZero && 0 === value) return null;
2734
3307
  return Math.round(value * work_docx_table_sizing_import_PIXELS_PER_TWIP * 100) / 100;
2735
3308
  }
2736
3309
  function work_docx_table_sizing_import_closestAncestor(element, localName) {
@@ -2838,18 +3411,19 @@ async function prepareDocxImport(buffer) {
2838
3411
  const imageLayoutMarkers = markDocxImageLayouts(document);
2839
3412
  const paragraphStylesDocument = archive.has('word/styles.xml') ? await archive.xml('word/styles.xml') : null;
2840
3413
  const paragraphStyles = createDocxParagraphStyleResolver(paragraphStylesDocument);
2841
- const paragraphDirectionMarkers = markDocxParagraphDirections(document, paragraphStyles);
2842
- const paragraphAlignmentMarkers = markDocxParagraphAlignments(document, paragraphStyles);
2843
- const paragraphIndentMarkers = markDocxParagraphIndents(document, paragraphStyles);
2844
- const paragraphSpacingMarkers = markDocxParagraphSpacing(document, paragraphStyles);
2845
- const paragraphPaginationMarkers = markDocxParagraphPagination(document, paragraphStyles);
3414
+ const tableStyles = createDocxTableStyleResolver(paragraphStylesDocument);
3415
+ const paragraphDirectionMarkers = markDocxParagraphDirections(document, paragraphStyles, tableStyles);
3416
+ const paragraphAlignmentMarkers = markDocxParagraphAlignments(document, paragraphStyles, tableStyles);
3417
+ const paragraphIndentMarkers = markDocxParagraphIndents(document, paragraphStyles, tableStyles);
3418
+ const paragraphSpacingMarkers = markDocxParagraphSpacing(document, paragraphStyles, tableStyles);
3419
+ const paragraphPaginationMarkers = markDocxParagraphPagination(document, paragraphStyles, tableStyles);
2846
3420
  const themePath = archive.paths('word/theme/').find((path)=>/\/theme\d*\.xml$/i.test(path));
2847
3421
  const themeDocument = themePath ? await archive.xml(themePath) : null;
2848
- const runFormattingMarkers = markDocxRunFormatting(document, paragraphStyles, themeDocument);
2849
- const tabStopMarkers = markDocxParagraphTabStops(document, paragraphStyles);
2850
- const tableCellMarkers = markDocxTableCells(document);
3422
+ const runFormattingMarkers = markDocxRunFormatting(document, paragraphStyles, themeDocument, tableStyles);
3423
+ const tabStopMarkers = markDocxParagraphTabStops(document, paragraphStyles, tableStyles);
3424
+ const tableCellMarkers = markDocxTableCells(document, themeDocument, tableStyles);
2851
3425
  const tableRowMarkers = markDocxTableRows(document);
2852
- const tableSizingMarkers = markDocxTableSizing(document);
3426
+ const tableSizingMarkers = markDocxTableSizing(document, tableStyles);
2853
3427
  const settings = archive.has('word/settings.xml') ? await archive.xml('word/settings.xml') : null;
2854
3428
  const trackChanges = Boolean(settings && firstDescendant(settings, 'trackRevisions')) || changeMarkers.changes.length > 0;
2855
3429
  const sectionElements = effectiveSectionProperties(document);
@@ -3021,6 +3595,7 @@ async function parseSectionLayout(section, archive, relationships, previous, odd
3021
3595
  const size = pageSize ? Math.abs(shortEdge - 12240) < Math.abs(shortEdge - 11906) ? 'letter' : 'a4' : previous.pageSize;
3022
3596
  const marginsElement = firstDescendant(section, 'pgMar');
3023
3597
  const columnsElement = firstDescendant(section, 'cols');
3598
+ const documentGridElement = directChild(section, 'docGrid');
3024
3599
  const pageChrome = await importSectionPageChrome(section, archive, relationships, previous, oddEvenPageChrome);
3025
3600
  const pageNumberStart = work_docx_import_numberAttribute(firstDescendant(section, 'pgNumType'), 'start');
3026
3601
  return {
@@ -3032,11 +3607,27 @@ async function parseSectionLayout(section, archive, relationships, previous, odd
3032
3607
  columns: columnsElement ? importDocxColumns(columnsElement, previous.columns) : {
3033
3608
  ...previous.columns
3034
3609
  },
3610
+ ...documentGridElement ? {
3611
+ documentGrid: parseDocumentGrid(documentGridElement)
3612
+ } : previous.documentGrid ? {
3613
+ documentGrid: {
3614
+ ...previous.documentGrid
3615
+ }
3616
+ } : {},
3035
3617
  breakAfter: parseSectionBreak(firstDescendant(section, 'type')),
3036
3618
  ...pageChrome,
3037
3619
  pageNumberStart: pageNumberStart > 0 ? pageNumberStart : void 0
3038
3620
  };
3039
3621
  }
3622
+ function parseDocumentGrid(element) {
3623
+ const sourceType = attribute(element, 'type');
3624
+ const type = 'lines' === sourceType || 'linesAndChars' === sourceType || 'snapToChars' === sourceType ? sourceType : 'default';
3625
+ const sourceLinePitch = work_docx_import_numberAttribute(element, 'linePitch');
3626
+ return {
3627
+ type,
3628
+ linePitch: sourceLinePitch > 0 ? Number((sourceLinePitch / 20).toFixed(2)) : 18
3629
+ };
3630
+ }
3040
3631
  function addSectionMarkers(document, sectionElements) {
3041
3632
  for(let index = 0; index < sectionElements.length - 1; index += 1){
3042
3633
  const paragraph = work_docx_import_closestAncestor(sectionElements[index], 'p');