添加期刊引用分析
This commit is contained in:
154
scripts/test-ref-comment-standalone.mjs
Normal file
154
scripts/test-ref-comment-standalone.mjs
Normal file
@@ -0,0 +1,154 @@
|
||||
import {
|
||||
Document,
|
||||
Paragraph,
|
||||
TextRun,
|
||||
CommentRangeStart,
|
||||
CommentRangeEnd,
|
||||
CommentReference,
|
||||
LevelFormat,
|
||||
LevelSuffix,
|
||||
AlignmentType,
|
||||
Packer
|
||||
} from 'docx';
|
||||
import JSZip from 'jszip';
|
||||
import fs from 'fs';
|
||||
|
||||
function htmlToPlainText(html) {
|
||||
return String(html || '')
|
||||
.replace(/ /g, ' ')
|
||||
.replace(/<br\s*\/?>/gi, ' ')
|
||||
.replace(/<[^>]*>/g, '')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function parseSingleAuthorName(nameStr) {
|
||||
const token = String(nameStr || '').trim();
|
||||
if (!token || /^et al\.?$/i.test(token)) return null;
|
||||
const parts = token.split(/\s+/).filter(Boolean);
|
||||
if (!parts.length) return null;
|
||||
if (parts.length === 1) return { first: '', last: parts[0] };
|
||||
return { first: parts.slice(0, -1).join(' '), last: parts[parts.length - 1] };
|
||||
}
|
||||
|
||||
function firstNameToAmaInitials(first) {
|
||||
return String(first || '')
|
||||
.split(/[\s-]+/)
|
||||
.filter(Boolean)
|
||||
.map((part) => part.charAt(0).toUpperCase())
|
||||
.join('');
|
||||
}
|
||||
|
||||
function formatOneAmaAuthor(nameStr) {
|
||||
const parsed = parseSingleAuthorName(nameStr);
|
||||
if (!parsed || !parsed.last) return '';
|
||||
const initials = firstNameToAmaInitials(parsed.first);
|
||||
return initials ? parsed.last + ' ' + initials : parsed.last;
|
||||
}
|
||||
|
||||
function splitAuthorList(authorText) {
|
||||
return String(authorText || '')
|
||||
.split(/\s*,\s*/)
|
||||
.map((part) => part.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function isAmaAbbreviatedAuthorList(authorText) {
|
||||
const authors = splitAuthorList(htmlToPlainText(authorText));
|
||||
if (!authors.length) return true;
|
||||
return authors.every((token) => {
|
||||
if (/^et al\.?$/i.test(token)) return true;
|
||||
return /^[\p{L}][\p{L}\-'']*\s+[A-Z](?:-?[A-Z])*\.?$/u.test(token);
|
||||
});
|
||||
}
|
||||
|
||||
function needsAmaAuthorAbbreviation(authorText) {
|
||||
const plain = htmlToPlainText(authorText).trim();
|
||||
if (!plain || isAmaAbbreviatedAuthorList(plain)) return false;
|
||||
return splitAuthorList(plain).some((token) => {
|
||||
const parts = token.split(/\s+/).filter(Boolean);
|
||||
if (parts.length < 2) return false;
|
||||
return parts[0].length > 2;
|
||||
});
|
||||
}
|
||||
|
||||
function buildAmaAuthorAbbreviation(authorText) {
|
||||
const authors = splitAuthorList(htmlToPlainText(authorText));
|
||||
return authors
|
||||
.map((token) => (/^et al\.?$/i.test(token) ? 'et al' : formatOneAmaAuthor(token)))
|
||||
.filter(Boolean)
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
function buildBookAmaAuthorComment(ref) {
|
||||
if (!ref || ref.refer_type !== 'book') return '';
|
||||
const authorSource = ref.author ? htmlToPlainText(ref.author) : '';
|
||||
if (!authorSource || !needsAmaAuthorAbbreviation(authorSource)) return '';
|
||||
const amaAuthors = buildAmaAuthorAbbreviation(authorSource);
|
||||
return amaAuthors ? 'AMA格式作者缩写:' + amaAuthors : '';
|
||||
}
|
||||
|
||||
const ref = {
|
||||
refer_type: 'book',
|
||||
author: 'Jacqueline Fawcett, Susan DeSanto-Madeya',
|
||||
title: 'Contemporary Nursing Knowledge',
|
||||
dateno: '(3rd Edition). Philadelphia, PA: F. A. Davis Company; 2013.',
|
||||
isbn: '978-0-8036-2765-9'
|
||||
};
|
||||
|
||||
const commentText = buildBookAmaAuthorComment(ref);
|
||||
console.log('comment text:', commentText);
|
||||
|
||||
const commentId = 0;
|
||||
const doc = new Document({
|
||||
numbering: {
|
||||
config: [{
|
||||
reference: 'ref-num',
|
||||
levels: [{
|
||||
level: 0,
|
||||
format: LevelFormat.DECIMAL,
|
||||
text: '%1.',
|
||||
alignment: AlignmentType.START,
|
||||
suffix: LevelSuffix.TAB,
|
||||
style: { paragraph: { indent: { left: 720, hanging: 360 } } }
|
||||
}]
|
||||
}]
|
||||
},
|
||||
comments: {
|
||||
children: [{
|
||||
id: commentId,
|
||||
author: 'Editor',
|
||||
initials: 'Ed',
|
||||
date: new Date(),
|
||||
children: [new Paragraph({ children: [new TextRun(commentText)] })]
|
||||
}]
|
||||
},
|
||||
sections: [{
|
||||
children: [new Paragraph({
|
||||
numbering: { reference: 'ref-num', level: 0 },
|
||||
children: [
|
||||
new CommentRangeStart(commentId),
|
||||
new TextRun('Jacqueline Fawcett, Susan DeSanto-Madeya. Contemporary Nursing Knowledge.'),
|
||||
new CommentRangeEnd(commentId),
|
||||
new TextRun({ children: [new CommentReference(commentId)] })
|
||||
]
|
||||
})]
|
||||
}]
|
||||
});
|
||||
|
||||
const buf = await Packer.toBuffer(doc);
|
||||
fs.writeFileSync('test-ref-comment-standalone.docx', buf);
|
||||
|
||||
const zip = await JSZip.loadAsync(buf);
|
||||
const docXml = await zip.file('word/document.xml').async('string');
|
||||
const commentsXml = zip.file('word/comments.xml');
|
||||
const relsXml = zip.file('word/_rels/document.xml.rels');
|
||||
const contentTypes = zip.file('[Content_Types].xml');
|
||||
|
||||
console.log('has comments.xml:', !!commentsXml);
|
||||
console.log('has commentReference in document:', docXml.includes('commentReference'));
|
||||
console.log('has comments rel in document.xml.rels:', relsXml ? (await relsXml.async('string')).includes('comments') : false);
|
||||
console.log('has comments in Content_Types:', contentTypes ? (await contentTypes.async('string')).includes('comments') : false);
|
||||
if (commentsXml) {
|
||||
console.log('comments preview:', (await commentsXml.async('string')).slice(0, 800));
|
||||
}
|
||||
40
scripts/test-ref-comment.mjs
Normal file
40
scripts/test-ref-comment.mjs
Normal file
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
Document,
|
||||
Paragraph,
|
||||
TextRun,
|
||||
CommentRangeStart,
|
||||
CommentRangeEnd,
|
||||
CommentReference,
|
||||
LevelFormat,
|
||||
LevelSuffix,
|
||||
AlignmentType,
|
||||
Packer
|
||||
} from 'docx';
|
||||
import JSZip from 'jszip';
|
||||
import fs from 'fs';
|
||||
import { buildBookAmaAuthorComment } from '../src/utils/referenceAuthorAma.js';
|
||||
import { buildManuscriptWordDocument } from '../src/utils/exportManuscriptWord.js';
|
||||
|
||||
const ref = {
|
||||
refer_type: 'book',
|
||||
author: 'Jacqueline Fawcett, Susan DeSanto-Madeya',
|
||||
title: 'Contemporary Nursing Knowledge',
|
||||
dateno: '(3rd Edition). Philadelphia, PA: F. A. Davis Company; 2013.',
|
||||
isbn: '978-0-8036-2765-9'
|
||||
};
|
||||
|
||||
console.log('comment text:', buildBookAmaAuthorComment(ref));
|
||||
|
||||
const doc = buildManuscriptWordDocument([], '', [ref], null, null);
|
||||
const buf = await Packer.toBuffer(doc);
|
||||
fs.writeFileSync('test-ref-comment.docx', buf);
|
||||
|
||||
const zip = await JSZip.loadAsync(buf);
|
||||
const docXml = await zip.file('word/document.xml').async('string');
|
||||
const commentsXml = zip.file('word/comments.xml');
|
||||
console.log('has comments.xml:', !!commentsXml);
|
||||
console.log('has commentReference:', docXml.includes('commentReference'));
|
||||
console.log('has commentRangeStart:', docXml.includes('commentRangeStart'));
|
||||
if (commentsXml) {
|
||||
console.log('comments preview:', (await commentsXml.async('string')).slice(0, 500));
|
||||
}
|
||||
49
scripts/test-ref-revision.mjs
Normal file
49
scripts/test-ref-revision.mjs
Normal file
@@ -0,0 +1,49 @@
|
||||
import {
|
||||
Document,
|
||||
Paragraph,
|
||||
TextRun,
|
||||
DeletedTextRun,
|
||||
InsertedTextRun,
|
||||
LevelFormat,
|
||||
LevelSuffix,
|
||||
AlignmentType,
|
||||
Packer
|
||||
} from 'docx';
|
||||
import JSZip from 'jszip';
|
||||
import fs from 'fs';
|
||||
|
||||
const doc = new Document({
|
||||
features: { trackRevisions: true },
|
||||
sections: [{
|
||||
children: [new Paragraph({
|
||||
children: [
|
||||
new DeletedTextRun({
|
||||
id: 1,
|
||||
author: 'Editor',
|
||||
date: new Date().toISOString(),
|
||||
text: 'David Harvey ',
|
||||
font: 'Charis SIL',
|
||||
size: 15
|
||||
}),
|
||||
new InsertedTextRun({
|
||||
id: 2,
|
||||
author: 'Editor',
|
||||
date: new Date().toISOString(),
|
||||
text: 'Harvey D ',
|
||||
font: 'Charis SIL',
|
||||
size: 15
|
||||
}),
|
||||
new TextRun('Contemporary Nursing Knowledge.')
|
||||
]
|
||||
})]
|
||||
}]
|
||||
});
|
||||
|
||||
const buf = await Packer.toBuffer(doc);
|
||||
fs.writeFileSync('test-ref-revision.docx', buf);
|
||||
const zip = await JSZip.loadAsync(buf);
|
||||
const docXml = await zip.file('word/document.xml').async('string');
|
||||
const settingsXml = await zip.file('word/settings.xml').async('string');
|
||||
console.log('has w:ins:', docXml.includes('<w:ins'));
|
||||
console.log('has w:del:', docXml.includes('<w:del'));
|
||||
console.log('trackRevisions:', settingsXml.includes('trackRevisions'));
|
||||
Reference in New Issue
Block a user