EhTagTranslation / EhSyringe

E 站注射器,将中文翻译注入到 E 站体内
MIT License
2.85k stars 115 forks source link

兼容其他脚本 #1271

Closed LuckyRabbitFeet closed 1 month ago

LuckyRabbitFeet commented 1 month ago

描述问题 我最近才更新了扩展,我注意到在翻译中增加了一条关于当前画廊图像数量的翻译,这条翻译破坏了原有的文本格式,我正在使用的一个脚本利用这个字段来分析当前页面中展示的图片数量,文本格式的变化导致脚本在获取第一个数字时出现了错误

我使用的脚本原本假定在通过空格切分字符串后获取的第二个值为起始数字,但是在替换文本后起始数字变成了获取的第一个值,这导致脚本执行意外中断

https://github.com/EhTagTranslation/EhSyringe/blob/ce22c706a6df10e580f9891103e3bdfb0271a3d4/src/services/ui-translation/data/gallery.ts#L133

我查看历史更新之后发现到这个更新是在这次提交中修改的

https://github.com/EhViewer-NekoInverter/EhSyringe/commit/424947e3bb269e2fa0136d36eeb2fe177d690e73#diff-abb858329386b5e78c01146e15e5f3fe44013db0468cd6adb93e6a4c1599154aR136

修改建议

新的翻译,例如 '展示中 $1 - $2,共 $3 张图像' or '正在展示 $1 - $2,共 $3 张图像'

相关网址

产生冲突的脚本:https://sleazyfork.org/zh-CN/scripts/33979-let-s-panda

在单页模式下可以复现问题

截图

如图可以发现脚本获取到了 NaN

image

相关代码

https://github.com/MinoLiu/Let-s-panda/blob/123d8767e6578848c43866c592aa0c9b0cd4d8df/src/main.js#L564-L575

环境

OpportunityLiu commented 1 month ago

处理过的啊,而且我这里一切正常啊,你是在哪个画廊下有问题的?

https://github.com/EhTagTranslation/EhSyringe/blob/ce22c706a6df10e580f9891103e3bdfb0271a3d4/src/plugin/syringe/index.ts#L481-L484

image

image

LuckyRabbitFeet commented 1 month ago

处理过的啊,而且我这里一切正常啊,你是在哪个画廊下有问题的?

https://github.com/EhTagTranslation/EhSyringe/blob/ce22c706a6df10e580f9891103e3bdfb0271a3d4/src/plugin/syringe/index.ts#L481-L484

image

image

感谢回复,看来我似乎没有 debug 到正确的错误位置,我根据你的建议重新检查了问题出现的场景:

在首次打开画廊的时候特殊处理代码是生效的,但是在刷新页面后就会出现如图所示错误,特殊处理的部分出现了重复的翻译后文本

image

我测试的画廊是 https://exhentai.org/g/3070177/b6aade502b/

OpportunityLiu commented 1 month ago

你是用的 Chrome 插件版本?

“刷新页面”具体时什么操作?按理说跟首次打开是没啥区别啊。

LuckyRabbitFeet commented 1 month ago

你是用的 Chrome 插件版本?

“刷新页面”具体时什么操作?按理说跟首次打开是没啥区别啊。

chrome 版本插件 v3.0.9

刷新指的是 chrome 浏览器页面刷新,通过点击地址栏左侧 “重新加载此页” 按钮实现

image

我的理解和你是一样的,感觉这个错误出现比较诡异,我正在拉取代码,看看能不能找到一些原因

OpportunityLiu commented 1 month ago

试一下 3.0.11 吧,没复现,盲修的

LuckyRabbitFeet commented 1 month ago

@OpportunityLiu

我在另外一台 Windows11 上也能复现

我分析了代码逻辑后认为这个问题可能是两个问题的混合,要分开分析

1)为什么针对 eh-syringe-ignore 的特殊处理失效了 2)为什么在 dom 中会出现重复的 eh-syringe-ignore 节点

第一个问题通过 v3.0.11 更新的过滤机制可以认为是修复了,由于这个问题是基于第二个问题出现的,所以可靠性可能要再测试测试

https://github.com/EhTagTranslation/EhSyringe/blob/e6b0a21c25f42f5dde5ad0d794ff86b9e9ca674d/src/plugin/syringe/index.ts#L316-L318

第二个问题出现的原因根据我的测试发现是因为以下代码导致的,我在其中增加了一些日志输出

https://github.com/LuckyRabbitFeet/EhSyringe/blob/0e6319ef48b210c4dfcc6170aca1b62f1415e645/src/plugin/syringe/index.ts#L194-L198

ready(() => {
    console.log('===============>> document loaded! <<==================');
    this.documentEnd = true;
    this.codePatch();
});

https://github.com/LuckyRabbitFeet/EhSyringe/blob/0e6319ef48b210c4dfcc6170aca1b62f1415e645/src/plugin/syringe/index.ts#L224-L232

if (this.documentEnd && node.childNodes) {
    console.log('进入 childNodes 的 childNodes');
    const nodeIterator = document.createNodeIterator(node);
    let childNode = nodeIterator.nextNode();
    while (childNode) {
        this.translateNode(childNode);
        childNode = nodeIterator.nextNode();
    }
}

https://github.com/LuckyRabbitFeet/EhSyringe/blob/0e6319ef48b210c4dfcc6170aca1b62f1415e645/src/plugin/syringe/index.ts#L485-L490

if (isElement(node, 'p') && node.classList.contains('gpc')) {
    console.log('start clone', node, node.innerText);
    /* 兼容熊猫书签,单独处理页码,保留原页码Element,防止熊猫书签取不到报错 */
    this.cloneAndPrependElement(node);
    console.log('add clone');
}

其中我发了一个用途未知的变量 documentEnd,在首次加载的时候因为没有缓存的原因,documentEnd 的值必然是 false,所以无法进入 L224-L232 的逻辑中,但是当点击 refresh 按钮刷新页面时,因为浏览器缓存的原因页面加载完成速度会比第一次快,此时 documentEnd 的值就会提早变为 true,然后就能进入 L224-L232 的逻辑中了,在这段逻辑中因为处理了 mutation.addedNodes.childNodes[] 的关系,就会导致目标 dom 被多次翻译,经过测试有多个 mutation 的子节点会包含例如 #gpc 在内的多个翻译目标节点

我录制了一个简短的视频来说明我的测试过程

https://github.com/user-attachments/assets/a74687bf-0c88-41c4-8742-d6978d6e2552

当我清除浏览器缓存时,可以明显看到 documentEnd 的状态在注入翻译前未被修改

image

第二次保留缓存后刷新,则可以看到 documentEnd 的状态提前于注入被修改为 true 了,之后就进入 L224-L232 的逻辑中,最终目标节点被多次翻译,生成了多个 eh-syringe-ignore 节点

image

综合以上分析,我认为这个问题的复现可能和硬件性能还有网络速度相关,问题本身的原因可能是 documentEnd 的异步更新导致的逻辑顺序问题以及 L224-L232 中对目标节点的重复处理

LuckyRabbitFeet commented 1 month ago

https://github.com/LuckyRabbitFeet/EhSyringe/blob/0e6319ef48b210c4dfcc6170aca1b62f1415e645/src/plugin/syringe/index.ts#L224-L232

if (this.documentEnd && node.childNodes) {
    console.log('进入 childNodes 的 childNodes');
    const nodeIterator = document.createNodeIterator(node);
    let childNode = nodeIterator.nextNode();
    while (childNode) {
        this.translateNode(childNode);
        childNode = nodeIterator.nextNode();
    }
}

请问一下这部分逻辑的目标是什么?

根据文档描述 addedNodes 已经包含了通过 MutationObserver 观察到的突变而添加到目标节点的节点,这样看来在页面加载时 MutationObserver 应该就能观察主体的整个加载过程,似乎就没有必要再进一步处理子节点的子节点了,实际上当我注释掉这段逻辑之后插件看上去也能正常工作(不过和我的测试量较少应该也有关系)

OpportunityLiu commented 1 month ago

翻了下提交记录,第一个提交就这么写的。。 https://github.com/EhTagTranslation/EhSyringe/commit/5e77adfce2f1fa7908b3a642cf545b4db827be87 @xioxin 还有印象吗?

OpportunityLiu commented 1 month ago

看了下确实不会包含子节点啊,去掉以后页面上动态添加元素的翻译就失效了 image

OpportunityLiu commented 1 month ago

我好像知道咋回事了,你再试试 3.0.12

LuckyRabbitFeet commented 1 month ago

我好像知道咋回事了,你再试试 3.0.12

看起来好像已经修复了,v3.0.12 在4个画廊做了测试没有出现类似问题

感谢修复!