终审编委信息
This commit is contained in:
@@ -186,28 +186,105 @@ function applyTableCaptionCenterParagraphPr(pInner) {
|
||||
return '<w:pPr><w:jc w:val="center"/></w:pPr>' + pInner;
|
||||
}
|
||||
|
||||
/** 从 tbl 前向前收集紧邻的 w:p(避免全文正则灾难性回溯) */
|
||||
function collectParagraphBlocksImmediatelyBefore(xml, tblIdx, minIndex) {
|
||||
const blocks = [];
|
||||
let end = tblIdx;
|
||||
|
||||
while (end > minIndex && blocks.length < 8) {
|
||||
let ws = end;
|
||||
while (ws > minIndex && /\s/.test(xml.charAt(ws - 1))) {
|
||||
ws -= 1;
|
||||
}
|
||||
if (ws <= minIndex) {
|
||||
break;
|
||||
}
|
||||
const closeIdx = xml.lastIndexOf('</w:p>', ws - 1);
|
||||
if (closeIdx < minIndex) {
|
||||
break;
|
||||
}
|
||||
const openIdx = xml.lastIndexOf('<w:p', closeIdx);
|
||||
if (openIdx < minIndex) {
|
||||
break;
|
||||
}
|
||||
const raw = xml.slice(openIdx, ws);
|
||||
if (!/<\/w:p>\s*$/i.test(raw)) {
|
||||
break;
|
||||
}
|
||||
blocks.unshift({
|
||||
start: openIdx,
|
||||
raw: raw,
|
||||
inner: raw.replace(/^<w:p\b[^>]*>/i, '').replace(/<\/w:p>\s*$/i, '')
|
||||
});
|
||||
end = openIdx;
|
||||
}
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
function isHomePageMetadataTableBlock(block) {
|
||||
const text = String(block || '');
|
||||
return /Author/i.test(text) && /contributions/i.test(text) && /Abstract/i.test(text);
|
||||
}
|
||||
|
||||
/** 正文表格标题(Table N…)紧挨 w:tbl 前的段落强制居中,不含首页元数据表格 */
|
||||
export function patchBodyTableCaptionCenterToXml(xml) {
|
||||
return xml.replace(/((?:<w:p\b[^>]*>[\s\S]*?<\/w:p>\s*)+)(\s*<w:tbl\b)/gi, function (match, paragraphGroup, tblOpen) {
|
||||
const blocks = paragraphGroup.match(/<w:p\b[^>]*>[\s\S]*?<\/w:p>/gi) || [];
|
||||
if (!blocks.length) {
|
||||
return match;
|
||||
if (!xml || xml.indexOf('<w:tbl') < 0) {
|
||||
return xml;
|
||||
}
|
||||
|
||||
const parts = [];
|
||||
let cursor = 0;
|
||||
const tblToken = '<w:tbl';
|
||||
const closeTag = '</w:tbl>';
|
||||
|
||||
while (cursor < xml.length) {
|
||||
const tblIdx = xml.indexOf(tblToken, cursor);
|
||||
if (tblIdx < 0) {
|
||||
parts.push(xml.slice(cursor));
|
||||
break;
|
||||
}
|
||||
|
||||
const firstText = extractTableCaptionParagraphPlainText(
|
||||
blocks[0].replace(/^<w:p\b[^>]*>/, '').replace(/<\/w:p>$/, '')
|
||||
);
|
||||
if (!isBodyTableCaptionPlainText(firstText)) {
|
||||
return match;
|
||||
const tblEnd = xml.indexOf(closeTag, tblIdx);
|
||||
if (tblEnd < 0) {
|
||||
parts.push(xml.slice(cursor));
|
||||
break;
|
||||
}
|
||||
|
||||
const centered = blocks.map(function (block) {
|
||||
return block.replace(/(<w:p\b[^>]*>)([\s\S]*?)(<\/w:p>)/, function (_full, open, inner, close) {
|
||||
return open + applyTableCaptionCenterParagraphPr(inner) + close;
|
||||
const tblEndExclusive = tblEnd + closeTag.length;
|
||||
const tblBlock = xml.slice(tblIdx, tblEndExclusive);
|
||||
|
||||
if (isHomePageMetadataTableBlock(tblBlock)) {
|
||||
parts.push(xml.slice(cursor, tblEndExclusive));
|
||||
cursor = tblEndExclusive;
|
||||
continue;
|
||||
}
|
||||
|
||||
const blocks = collectParagraphBlocksImmediatelyBefore(xml, tblIdx, cursor);
|
||||
const isCaption =
|
||||
blocks.length &&
|
||||
isBodyTableCaptionPlainText(extractTableCaptionParagraphPlainText(blocks[0].inner));
|
||||
|
||||
if (isCaption) {
|
||||
parts.push(xml.slice(cursor, blocks[0].start));
|
||||
blocks.forEach(function (entry) {
|
||||
parts.push(
|
||||
entry.raw.replace(/(<w:p\b[^>]*>)([\s\S]*?)(<\/w:p>)/i, function (_full, open, inner, close) {
|
||||
return open + applyTableCaptionCenterParagraphPr(inner) + close;
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
return centered.join('') + tblOpen;
|
||||
});
|
||||
const afterBlocks = blocks[blocks.length - 1].start + blocks[blocks.length - 1].raw.length;
|
||||
parts.push(xml.slice(afterBlocks, tblIdx));
|
||||
} else {
|
||||
parts.push(xml.slice(cursor, tblIdx));
|
||||
}
|
||||
|
||||
parts.push(tblBlock);
|
||||
cursor = tblEndExclusive;
|
||||
}
|
||||
|
||||
return parts.join('');
|
||||
}
|
||||
|
||||
/** 导出后处理:除首页表格外,正文表格标题居中 */
|
||||
@@ -248,11 +325,17 @@ function ensureFigureTitleTrailingPeriod(text) {
|
||||
return trimmed + '.';
|
||||
}
|
||||
|
||||
function createFigureTitleParagraph(children) {
|
||||
return createWordParagraph(children, { alignment: AlignmentType.JUSTIFIED });
|
||||
function createFigureTitleParagraph(children, alignment) {
|
||||
return createWordParagraph(children, { alignment: alignment || AlignmentType.CENTER });
|
||||
}
|
||||
|
||||
function appendFigureTitleParagraphs(children, titleHtml) {
|
||||
function hasFigureAnnotation(noteHtml) {
|
||||
return !!htmlToPlainText(String(noteHtml || '')).trim();
|
||||
}
|
||||
|
||||
function appendFigureTitleParagraphs(children, titleHtml, options) {
|
||||
const opts = options || {};
|
||||
const alignment = hasFigureAnnotation(opts.note) ? AlignmentType.JUSTIFIED : AlignmentType.CENTER;
|
||||
const segments = splitHtmlSegments(titleHtml)
|
||||
.map(function (segment) {
|
||||
return htmlToPlainText(segment).trim();
|
||||
@@ -266,16 +349,19 @@ function appendFigureTitleParagraphs(children, titleHtml) {
|
||||
const text =
|
||||
index === segments.length - 1 ? ensureFigureTitleTrailingPeriod(segment) : segment;
|
||||
children.push(
|
||||
createFigureTitleParagraph([
|
||||
new TextRun({
|
||||
text: text,
|
||||
bold: true,
|
||||
color: TITLE_COLOR,
|
||||
font: FONT_NAME,
|
||||
size: TITLE_FONT_SIZE,
|
||||
kern: FONT_KERN_MIN_1PT
|
||||
})
|
||||
])
|
||||
createFigureTitleParagraph(
|
||||
[
|
||||
new TextRun({
|
||||
text: text,
|
||||
bold: true,
|
||||
color: TITLE_COLOR,
|
||||
font: FONT_NAME,
|
||||
size: TITLE_FONT_SIZE,
|
||||
kern: FONT_KERN_MIN_1PT
|
||||
})
|
||||
],
|
||||
alignment
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -771,6 +857,28 @@ function buildTableWordChildren(processedItem, options) {
|
||||
return children;
|
||||
}
|
||||
|
||||
/** 稿件导出:标题 + 表格 + 表注均为单栏(分节符在标题前 / 表前,双栏恢复在表注后 / 表后) */
|
||||
export function buildTableWordManuscriptParts(processedItem, options) {
|
||||
const blockChildren = buildTableWordChildren(processedItem, options);
|
||||
const tableIndex = blockChildren.findIndex(function (child) {
|
||||
return child instanceof Table;
|
||||
});
|
||||
|
||||
if (tableIndex < 0) {
|
||||
return {
|
||||
titleChildren: blockChildren,
|
||||
tableChildren: [],
|
||||
noteChildren: []
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
titleChildren: blockChildren.slice(0, tableIndex),
|
||||
tableChildren: blockChildren.slice(tableIndex, tableIndex + 1),
|
||||
noteChildren: blockChildren.slice(tableIndex + 1)
|
||||
};
|
||||
}
|
||||
|
||||
export function buildTableWordDocument(processedItem) {
|
||||
return createWordDocument(buildTableWordChildren(processedItem));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user