Files
tougao_web/scripts/inspect-word-figures.mjs
2026-07-31 15:07:12 +08:00

83 lines
2.5 KiB
JavaScript

import FS from 'fs';
import path from 'path';
import JSZip from 'jszip';
const file = path.join(
'C:/Users/Administrator/Desktop/IN2026A0418001_final_20260713 1.docx'
);
const buf = FS.readFileSync(file);
const zip = await JSZip.loadAsync(buf);
const xml = await zip.file('word/document.xml').async('string');
const drawings = (xml.match(/<w:drawing/g) || []).length;
const blips = (xml.match(/a:blip/g) || []).length;
console.log('drawings', drawings, 'blips', blips);
const colors = {};
for (const m of xml.matchAll(/w:color\s+w:val="([^"]+)"/g)) {
colors[m[1]] = (colors[m[1]] || 0) + 1;
}
console.log(
'colors top',
Object.entries(colors)
.sort((a, b) => b[1] - a[1])
.slice(0, 20)
);
// Extract paragraphs containing "Figure" with nearby text
const paras = xml.split(/<\/w:p>/);
let figParaCount = 0;
for (let i = 0; i < paras.length; i++) {
const p = paras[i];
const texts = [...p.matchAll(/<w:t(?:\s[^>]*)?>([\s\S]*?)<\/w:t>/g)].map((x) => x[1]);
const plain = texts.join('').replace(/&amp;/g, '&').trim();
if (!/^Figure\s+\d+/i.test(plain) && !/^Fig\.?\s*\d+/i.test(plain)) continue;
figParaCount += 1;
const hasDrawing = /<w:drawing/.test(p);
const colorVals = [...p.matchAll(/w:color\s+w:val="([^"]+)"/g)].map((x) => x[1]);
// next non-empty para
let nextPlain = '';
for (let j = i + 1; j < Math.min(i + 5, paras.length); j++) {
const nt = [...paras[j].matchAll(/<w:t(?:\s[^>]*)?>([\s\S]*?)<\/w:t>/g)]
.map((x) => x[1])
.join('')
.replace(/&amp;/g, '&')
.trim();
if (nt) {
nextPlain = nt.slice(0, 220);
break;
}
}
// prev: look back for drawing-only paragraphs
let prevHasDrawing = false;
for (let j = i - 1; j >= Math.max(0, i - 6); j--) {
if (/<w:drawing/.test(paras[j])) {
prevHasDrawing = true;
break;
}
const pt = [...paras[j].matchAll(/<w:t(?:\s[^>]*)?>([\s\S]*?)<\/w:t>/g)]
.map((x) => x[1])
.join('')
.trim();
if (pt && !/^[AB]$/.test(pt)) break;
}
console.log('---');
console.log('caption:', plain.slice(0, 160));
console.log('colors:', [...new Set(colorVals)]);
console.log('sameParaDrawing:', hasDrawing, 'prevHasDrawing:', prevHasDrawing);
console.log('next:', nextPlain);
}
console.log('figParaCount', figParaCount);
// Check standalone A/B label paragraphs near figures
let abCount = 0;
for (const p of paras) {
const plain = [...p.matchAll(/<w:t(?:\s[^>]*)?>([\s\S]*?)<\/w:t>/g)]
.map((x) => x[1])
.join('')
.trim();
if (/^[AB]$/.test(plain)) abCount += 1;
}
console.log('standalone A/B paras', abCount);