专刊
This commit is contained in:
82
scripts/inspect-word-figures.mjs
Normal file
82
scripts/inspect-word-figures.mjs
Normal file
@@ -0,0 +1,82 @@
|
||||
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(/&/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(/&/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);
|
||||
Reference in New Issue
Block a user