Sign In

@file-viewer/doc

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@file-viewer/doc - npm Package Compare versions

Comparing version
2.2.5
to
2.2.6
+1
-0
dist/msdoc/constants.d.ts

@@ -5,2 +5,3 @@ export declare const DOC_CONTROL: {

picture: string;
textBoxPlaceholder: string;
fieldStart: string;

@@ -7,0 +8,0 @@ fieldSeparator: string;

@@ -5,2 +5,3 @@ export const DOC_CONTROL = {

picture: '\u0001',
textBoxPlaceholder: '\u0008',
fieldStart: '\u0013',

@@ -7,0 +8,0 @@ fieldSeparator: '\u0014',

@@ -126,4 +126,4 @@ import { parseCFB } from '../core/cfb.js';

case DOC_CONTROL.nonRequiredHyphen:
return '';
case DOC_CONTROL.annotationRef:
case DOC_CONTROL.textBoxPlaceholder:
return '';

@@ -134,2 +134,57 @@ default:

}
function normalizeParagraphText(text) {
return text.replaceAll(DOC_CONTROL.textBoxPlaceholder, '');
}
function getDocumentStoryRanges(fib, documentLength) {
const storyLengths = [
['main', fib.fibRgLw.ccpText],
['footnote', fib.fibRgLw.ccpFtn],
['header', fib.fibRgLw.ccpHdd],
['macro', fib.fibRgLw.ccpMcr],
['annotation', fib.fibRgLw.ccpAtn],
['endnote', fib.fibRgLw.ccpEdn],
['textbox', fib.fibRgLw.ccpTxbx],
['header-textbox', fib.fibRgLw.ccpHdrTxbx],
];
const hasDeclaredStories = storyLengths.some(([, length]) => length > 0);
if (!hasDeclaredStories)
return [{ kind: 'main', cpStart: 0, cpEnd: documentLength }];
const ranges = [];
let cp = 0;
for (const [kind, rawLength] of storyLengths) {
const length = Math.max(0, rawLength || 0);
const cpStart = Math.min(cp, documentLength);
cp += length;
const cpEnd = Math.min(cp, documentLength);
ranges.push({ kind, cpStart, cpEnd });
}
return ranges;
}
function buildStoryParagraphRanges(story, documentText, papxRuns) {
if (story.cpEnd <= story.cpStart)
return [];
const runs = papxRuns.filter((run) => run.cpStart < story.cpEnd && run.cpEnd > story.cpStart);
if (runs.length) {
return runs.map((run) => {
const cpStart = Math.max(story.cpStart, run.cpStart);
const cpEnd = Math.min(story.cpEnd, run.cpEnd);
return {
cpStart,
cpEnd,
terminator: documentText[cpEnd - 1] || '',
styleId: run.styleId,
properties: run.properties,
storyKind: story.kind,
};
}).filter((range) => range.cpEnd > range.cpStart);
}
return splitParagraphRanges(documentText.slice(story.cpStart, story.cpEnd)).map((range) => ({
...range,
cpStart: range.cpStart + story.cpStart,
cpEnd: range.cpEnd + story.cpStart,
styleId: 0,
properties: [],
storyKind: story.kind,
}));
}
function buildInlineNodes(segments, resolveAsset) {

@@ -212,3 +267,3 @@ const output = [];

}
function buildCharSegments(range, paragraphText, chpxRuns, styles, baseCharProps, resolveFont, cursorRef) {
function buildCharSegments(range, paragraphText, chpxRuns, styles, baseCharProps, resolveFont, cursorRef, forceReadableColors = false) {
const overlaps = getOverlappingRuns(chpxRuns, range.cpStart, range.cpEnd, cursorRef);

@@ -233,2 +288,4 @@ const boundaries = new Set([range.cpStart, range.cpEnd]);

const state = charPropsToState(finalProps);
if (forceReadableColors && state.colorIndex === 8)
state.colorIndex = 1;
const font = resolveFont(state.fontFamilyId);

@@ -252,2 +309,4 @@ if (font)

const state = charPropsToState(baseCharProps);
if (forceReadableColors && state.colorIndex === 8)
state.colorIndex = 1;
const font = resolveFont(state.fontFamilyId);

@@ -272,3 +331,3 @@ if (font)

const resolveFont = (fontId) => fonts.byIndex(fontId);
const segments = buildCharSegments(range, paragraphText, chpxRuns, styles, baseCharProps, resolveFont, chpxCursor);
const segments = buildCharSegments(range, paragraphText, chpxRuns, styles, baseCharProps, resolveFont, chpxCursor, range.storyKind === 'textbox' || range.storyKind === 'header-textbox');
const inlines = buildInlineNodes(segments, resolveAsset);

@@ -610,18 +669,20 @@ return {

const documentText = pieceTexts.join('');
const mainStoryEnd = fib.fibRgLw.ccpText > 0 ? fib.fibRgLw.ccpText : documentText.length;
const stories = getDocumentStoryRanges(fib, documentText.length);
const mainStory = stories.find((story) => story.kind === 'main') || { kind: 'main', cpStart: 0, cpEnd: documentText.length };
const supplementalTextStories = stories.filter((story) => ((story.kind === 'textbox' || story.kind === 'header-textbox')
&& normalizeParagraphText(documentText.slice(story.cpStart, story.cpEnd)).replace(/[\r\u0007]/g, '').trim().length > 0));
const styles = parseStyles(tableBytes, fib.fibRgFcLcb);
const fonts = parseFonts(tableBytes, fib.fibRgFcLcb);
const chpxRuns = readChpxRuns(wordBytes, tableBytes, fib, clx).filter((run) => run.cpStart < mainStoryEnd);
const relevantStoryEnd = Math.max(mainStory.cpEnd, ...supplementalTextStories.map((story) => story.cpEnd));
const chpxRuns = readChpxRuns(wordBytes, tableBytes, fib, clx)
.filter((run) => run.cpStart < relevantStoryEnd)
.map((run) => ({ ...run, cpEnd: Math.min(run.cpEnd, relevantStoryEnd) }));
const papxRuns = readPapxRuns(wordBytes, tableBytes, fib, clx, dataBytes)
.filter((run) => run.cpStart < mainStoryEnd)
.map((run) => ({ ...run, cpEnd: Math.min(run.cpEnd, mainStoryEnd) }));
const ranges = papxRuns.length
? papxRuns.map((run) => ({
cpStart: run.cpStart,
cpEnd: run.cpEnd,
terminator: documentText[run.cpEnd - 1] || '',
styleId: run.styleId,
properties: run.properties,
}))
: splitParagraphRanges(documentText.slice(0, mainStoryEnd)).map((range) => ({ ...range, styleId: 0, properties: [] }));
.filter((run) => run.cpStart < relevantStoryEnd)
.map((run) => ({ ...run, cpEnd: Math.min(run.cpEnd, relevantStoryEnd) }));
const ranges = [mainStory, ...supplementalTextStories]
.flatMap((story) => buildStoryParagraphRanges(story, documentText, papxRuns));
if (supplementalTextStories.length) {
pushWarning(warnings, 'Recovered text from a legacy Word text-box story; text-box positioning is unavailable, so the content was linearized after the main story.', { code: 'MSDOC_TEXTBOX_STORY_LINEARIZED', storyCount: supplementalTextStories.length });
}
const objectPool = extractObjectPool(cfb);

@@ -633,9 +694,13 @@ const assets = [];

const chpxCursor = { index: 0 };
const paragraphs = ranges.map((range) => {
const paragraphs = ranges.flatMap((range) => {
const rawParagraphText = getTextByCp(wordBytes, clx, pieceTexts, range.cpStart, range.cpEnd);
const terminator = range.terminator === DOC_CONTROL.paragraph || range.terminator === DOC_CONTROL.cellMark ? range.terminator : '';
const paragraphText = terminator && rawParagraphText.endsWith(terminator)
const rawContent = terminator && rawParagraphText.endsWith(terminator)
? rawParagraphText.slice(0, -1)
: rawParagraphText;
return buildParagraphModel({ ...range, terminator }, paragraphText, styles, fonts, chpxRuns, resolveAsset, chpxCursor);
const paragraphText = normalizeParagraphText(rawContent);
const isTextBoxStory = range.storyKind === 'textbox' || range.storyKind === 'header-textbox';
if ((rawContent.includes(DOC_CONTROL.textBoxPlaceholder) || isTextBoxStory) && !paragraphText.trim())
return [];
return [buildParagraphModel({ ...range, terminator }, paragraphText, styles, fonts, chpxRuns, resolveAsset, chpxCursor)];
});

@@ -642,0 +707,0 @@ normalizeRowEndOnlyTables(paragraphs);

+3
-2
{
"name": "@file-viewer/doc",
"version": "2.2.5",
"version": "2.2.6",
"private": false,

@@ -73,4 +73,5 @@ "type": "module",

"verify:github-34": "pnpm build && node scripts/verify-github-34.mjs",
"verify:github-87": "pnpm build && node scripts/verify-github-87.mjs"
"verify:github-87": "pnpm build && node scripts/verify-github-87.mjs",
"verify:github-171": "pnpm build && node scripts/verify-github-171.mjs"
}
}