Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,8 @@ const importHeadersFooters = (docx, converter, editor) => {
filename: currentFileName,
});

if (!converter.headerIds.ids) converter.headerIds.ids = [];
converter.headerIds.ids.push(rId);
converter.headers[rId] = { type: 'doc', content: [...schema] };
converter.headerIds[sectionType] = rId;
});
Expand All @@ -470,6 +472,8 @@ const importHeadersFooters = (docx, converter, editor) => {
filename: currentFileName,
});

if (!converter.footerIds.ids) converter.footerIds.ids = [];
converter.footerIds.ids.push(rId);
converter.footers[rId] = { type: 'doc', content: [...schema] };
converter.footerIds[sectionType] = rId;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ export const handleParagraphNode = (params) => {

schemaNode.attrs.marksAttrs = marks;
}


let styleId;
if (styleTag) {
schemaNode.attrs['styleId'] = styleTag.attributes['w:val'];
styleId = styleTag.attributes['w:val'];
schemaNode.attrs['styleId'] = styleId;
}

if (docx) {
const indent = getParagraphIndent(node, docx, schemaNode.attrs['styleId']);
const indent = getParagraphIndent(node, docx, styleId);

if (!schemaNode.attrs.indent) {
schemaNode.attrs.indent = {};
Expand All @@ -86,10 +88,10 @@ export const handleParagraphNode = (params) => {
if (indent.firstLine || indent.firstLine === 0) {
schemaNode.attrs.indent.firstLine = indent.firstLine;
}
if (indent.hanging) {
if (indent.hanging || indent.hanging === 0) {
schemaNode.attrs.indent.hanging = indent.hanging;
}
if (indent.textIndent) {
if (indent.textIndent || indent.textIndent === 0) {
schemaNode.attrs.textIndent = `${indent.textIndent}in`;
}
}
Expand All @@ -111,10 +113,10 @@ export const handleParagraphNode = (params) => {

if (docx) {
const defaultStyleId = node.attributes?.['w:rsidRDefault'];
schemaNode.attrs['spacing'] = getParagraphSpacing(node, docx, schemaNode.attrs['styleId'], schemaNode.attrs.marksAttrs);
schemaNode.attrs['spacing'] = getParagraphSpacing(node, docx, styleId, schemaNode.attrs.marksAttrs);
schemaNode.attrs['rsidRDefault'] = defaultStyleId;
}

if (framePr && framePr.attributes['w:dropCap']) {
schemaNode.attrs.dropcap = {
type: framePr.attributes['w:dropCap'],
Expand All @@ -135,6 +137,14 @@ export const handleParagraphNode = (params) => {
};
}

// Pass through this paragraph's sectPr, if any
const sectPr = pPr?.elements?.find((el) => el.name === 'w:sectPr');
if (sectPr) {
if (!schemaNode.attrs.paragraphProperties) schemaNode.attrs.paragraphProperties = {};
schemaNode.attrs.paragraphProperties.sectPr = sectPr;
schemaNode.attrs.pageBreakSource = 'sectPr';
};

return { nodes: schemaNode ? [schemaNode] : [], consumed: 1 };
};

Expand Down Expand Up @@ -252,16 +262,20 @@ const getDefaultParagraphStyle = (docx, styleId = '') => {
// Styles based on styleId
let pPrStyleIdSpacingTag = {};
let pPrStyleIdIndentTag = {};
let pPrStyleJc = {};
if (styleId) {
const stylesById = styles.elements[0].elements?.find((el) => el.name === 'w:style' && el.attributes['w:styleId'] === styleId);
const pPrById = stylesById?.elements?.find((el) => el.name === 'w:pPr');

pPrStyleIdSpacingTag = pPrById?.elements?.find((el) => el.name === 'w:spacing') || {};
pPrStyleIdIndentTag = pPrById?.elements?.find((el) => el.name === 'w:ind') || {};
pPrStyleJc = pPrById?.elements?.find((el) => el.name === 'w:jc') || {};
}

const { attributes: pPrDefaultSpacingAttr } = pPrDefaultSpacingTag;
const { attributes: pPrNormalSpacingAttr } = pPrNormalSpacingTag;
const { attributes: pPrByIdSpacingAttr } = pPrStyleIdSpacingTag;
const { attributes: pPrByIdJcAttr } = pPrStyleJc;

const { attributes: pPrDefaultIndentAttr } = pPrDefaultIndentTag;
const { attributes: pPrNormalIndentAttr } = pPrNormalIndentTag;
Expand All @@ -270,6 +284,7 @@ const getDefaultParagraphStyle = (docx, styleId = '') => {
return {
spacing: pPrByIdSpacingAttr || pPrDefaultSpacingAttr || pPrNormalSpacingAttr,
indent: pPrByIdIndentAttr || pPrDefaultIndentAttr || pPrNormalIndentAttr,
justify: pPrByIdJcAttr,
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import { parseProperties } from './importerHelpers.js';
import { twipsToPixels } from '../../helpers.js';

/**
* @type {import("docxImporter").NodeHandler}
*/
const handleTabNode = (params) => {
const { nodes } = params;
const { nodes, docx, parentStyleId } = params;
if (nodes.length === 0 || nodes[0].name !== 'w:tab') {
return { nodes: [], consumed: 0 };
}
const node = nodes[0];

const styles = docx['word/styles.xml'];
let stylePos;
if (styles && styles.elements?.length) {
const style = styles.elements[0]?.elements?.find((s) => s.attributes?.['w:styleId'] === parentStyleId);
const pPr = style?.elements?.find((s) => s.name === 'w:pPr');
const tabsDef = pPr?.elements?.find((s) => s.name === 'w:tabs');
const firstTab = tabsDef?.elements?.find((s) => s.name === 'w:tab');
stylePos = twipsToPixels(firstTab?.attributes?.['w:pos']);
}

const { attributes = {} } = node;
const processedNode = {
type: 'tab',
Expand Down
13 changes: 13 additions & 0 deletions packages/super-editor/src/extensions/line-break/line-break.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ export const HardBreak = Node.create({
}
},

addAttributes() {
return {
pageBreakSource: {
rendered: false,
default: null,
},
pageBreakType: {
default: null,
rendered: false,
}
}
},

parseDOM() {
return [{ tag: 'span' }];
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export const initPaginationData = async (editor) => {
if (!editor.converter) return;

const sectionData = { headers: {}, footers: {} };
const headerIds = editor.converter.headerIds;
const footerIds = editor.converter.footerIds;
const headerIds = editor.converter.headerIds.ids;
const footerIds = editor.converter.footerIds.ids;

for (let key in headerIds) {
const sectionId = headerIds[key];
Expand Down
42 changes: 38 additions & 4 deletions packages/super-editor/src/extensions/pagination/pagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,26 @@ export const Pagination = Extension.create({
* @param {Editor} editor
* @returns {String|null} The header or footer ID
*/
const getHeaderFooterId = (currentPageNumber, sectionType, editor) => {
const getHeaderFooterId = (currentPageNumber, sectionType, editor, node = null) => {
const { alternateHeaders } = editor.converter.pageStyles;
const sectionIds = editor.converter[sectionType];

if (node && node.attrs?.paragraphProperties?.sectPr) {
const sectPr = node.attrs?.paragraphProperties?.sectPr;

if (currentPageNumber === 1) {
if (sectionType === 'headerIds') {
const sectionData = sectPr?.elements?.find((el) => el.name === 'w:headerReference' && el.attributes?.['w:type'] === 'first');
const newId = sectionData?.attributes?.['r:id'];
return newId;
} else if (sectionType === 'footerIds') {
const sectionData = sectPr?.elements?.find((el) => el.name === 'w:footerReference' && el.attributes?.['w:type'] === 'first');
const newId = sectionData?.attributes?.['r:id'];
return newId;
}
}
}

if (sectionIds?.titlePg && !sectionIds.first && currentPageNumber === 1) return null;

const even = sectionIds.even;
Expand All @@ -179,9 +195,11 @@ const getHeaderFooterId = (currentPageNumber, sectionType, editor) => {
if (sectionIds?.titlePg && first && currentPageNumber === 1) return first;

let sectionId = sectionIds.default;
if (currentPageNumber === 1) sectionId = first || defaultHeader;

if (alternateHeaders) {
if (currentPageNumber === 1) sectionId = first;
else if (currentPageNumber % 2 === 0) sectionId = even || defaultHeader;
if (currentPageNumber % 2 === 0) sectionId = even || defaultHeader;
else sectionId = odd || defaultHeader;
}

Expand Down Expand Up @@ -319,7 +337,22 @@ function generateInternalPageBreaks(doc, view, editor, sectionData) {
if (!coords) return;

let shouldAddPageBreak = coords.bottom > pageHeightThreshold;
const isHardBreakNode = currentNode.type.name === 'hardBreak';
let isHardBreakNode = currentNode.type.name === 'hardBreak';

const paragraphSectPrBreak = currentNode.attrs?.pageBreakSource;
if (paragraphSectPrBreak === 'sectPr') {
const nextNode = doc.nodeAt(currentPos + currentNode.nodeSize);
const nextNodeSectPr = nextNode?.attrs?.pageBreakSource === 'sectPr';
if (!nextNodeSectPr) isHardBreakNode = true;

if (currentPageNumber === 1) {
const headerId = getHeaderFooterId(currentPageNumber, 'headerIds', editor, currentNode);
decorations.pop(); // Remove the first header and replace with sectPr header
const newFirstHeader = createHeader(pageMargins, pageSize, sectionData, headerId);
const pageBreak = createPageBreak({ editor, header: newFirstHeader, isFirstHeader: true });
decorations.push(Decoration.widget(0, pageBreak, { key: 'stable-key' }));
};
};

if (currentNode.type.name === 'paragraph' && currentNode.attrs.styleId) {
const linkedStyles = LinkedStylesPluginKey.getState(editor.state)?.styles;
Expand Down Expand Up @@ -359,9 +392,10 @@ function generateInternalPageBreaks(doc, view, editor, sectionData) {
};

// Update the header and footer based on the current page number
const footerId = getHeaderFooterId(currentPageNumber, 'footerIds', editor, currentNode);

currentPageNumber++;
const headerId = getHeaderFooterId(currentPageNumber, 'headerIds', editor);
const footerId = getHeaderFooterId(currentPageNumber, 'footerIds', editor);
header = createHeader(pageMargins, pageSize, sectionData, headerId);
footer = createFooter(pageMargins, pageSize, sectionData, footerId, currentPageNumber - 1);

Expand Down
15 changes: 15 additions & 0 deletions packages/super-editor/src/extensions/paragraph/paragraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@ export const Paragraph = Node.create({
keepNext: { rendered: false },
paragraphProperties: { rendered: false },
dropcap: { rendered: false },
pageBreakSource: { rendered: false },
justify: {
renderDOM: ({ justify }) => {
const { val: jc } = justify || {};
if (!jc) return {};

let style = '';
if (jc === 'left') style += 'text-align: left;';
else if (jc === 'right') style += 'text-align: right;';
else if (jc === 'center') style += 'text-align: center;';
else if (jc === 'both') style += 'text-align: justify;';

return { style };
},
}
};
},

Expand Down
2 changes: 1 addition & 1 deletion packages/super-editor/src/extensions/tab/tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const TabNode = Node.create({
tabSize: {
renderDOM: ({ tabSize }) => {
if (!tabSize) return {};
const style = `width: ${tabSize}px;`;
const style = `width: ${tabSize}px; min-width: ${tabSize}px;`;
return { style };
},
},
Expand Down
Loading