fix(douban): make title splitting self-contained for page evaluate

fix(douban): make title splitting self-contained for page evaluate

Co-authored-by: First-principles-0 <first-principles-0@users.noreply.github.com>
Co-authored-by: codex-mini0 <codex-mini0@users.noreply.github.com>
This commit is contained in:
Zhongyue Lin
2026-06-14 04:22:35 +08:00
committed by GitHub
parent c027944380
commit 1c88aff23f
2 changed files with 52 additions and 1 deletions
+2 -1
View File
@@ -67,7 +67,8 @@ function extractDoubanPublishYear(value) {
const match = normalizeText(value).match(/\b(19|20)\d{2}\b/);
return match?.[0] || '';
}
function splitDoubanTitle(fullTitle) {
export function splitDoubanTitle(fullTitle) {
const normalizeText = (value) => String(value || '').replace(/\s+/g, ' ').trim();
const normalized = normalizeText(fullTitle);
if (!normalized)
return { title: '', originalTitle: '' };
+50
View File
@@ -11,6 +11,7 @@ import {
promoteDoubanPhotoUrl,
resolveDoubanPhotoAssetUrl,
searchDouban,
splitDoubanTitle,
} from './utils.js';
function createFakeNode(text = '', attrs = {}) {
@@ -436,3 +437,52 @@ describe('inferDoubanSearchResultType', () => {
})).toBe('book');
});
});
// Regression for #1851: splitDoubanTitle must be self-contained so its
// .toString()-injected form runs inside page.evaluate, where the module scope
// (and therefore the module-level normalizeText) is unavailable. Pre-fix the
// injected copy threw `ReferenceError: normalizeText is not defined`.
describe('splitDoubanTitle — page.evaluate injection (#1851)', () => {
// Rebuild the function from its source in a fresh scope that, like the
// browser page context, has no access to the module-level normalizeText.
function injectViaToString(fn) {
// eslint-disable-next-line no-new-func
return new Function(`return (${fn.toString()})`)();
}
it('does not throw when injected into page.evaluate (normalizeText is not defined there)', () => {
const injected = injectViaToString(splitDoubanTitle);
expect(() => injected('盗梦空间 Inception')).not.toThrow();
});
it('splits a CJK + Latin title correctly when injected', () => {
const injected = injectViaToString(splitDoubanTitle);
expect(injected('盗梦空间 Inception')).toEqual({
title: '盗梦空间',
originalTitle: 'Inception',
});
});
it('returns the same result whether called directly or via injection', () => {
const injected = injectViaToString(splitDoubanTitle);
const samples = [
'盗梦空间 Inception',
'千与千寻 千と千尋の神隠し',
"哈尔的移动城堡 Howl's Moving Castle",
'无名之辈',
'',
' ',
];
for (const input of samples) {
expect(injected(input)).toEqual(splitDoubanTitle(input));
}
});
it('collapses internal whitespace in the injected copy', () => {
const injected = injectViaToString(splitDoubanTitle);
expect(injected(' 流浪地球 The Wandering Earth ')).toEqual({
title: '流浪地球',
originalTitle: 'The Wandering Earth',
});
});
});