是的,这是可行的。让我们从简单的开始。首先,将以下内容添加到新主题组件的“头部(header)”标签页中。
<script type="text/discourse-plugin" version="0.8.42">
</script>
这是做什么的?这是一种由 Discourse 处理的特殊脚本标签。有什么好处呢?它允许你访问 插件 API 的方法。
你想给某些链接附加联盟代码。这意味着你需要修改帖子的内容。如果你查看插件 API,会发现确实有对应的方法。
使用方法如下:
api.decorateCookedElement(
element =\u003e {
// 在这里执行你的操作。
// 此处传入的 element 是已渲染帖子的 HTML 节点
},
{
// 选项放在这里
}
);
这是你需要包裹代码的容器,以便在帖子渲染时触发它。那么,让我们尝试一下。
我们将你的代码原样添加进去:
api.decorateCookedElement(
element =\u003e {
++ // 将下面的 "my-affiliate-id" 替换为你实际的联盟 ID
++ const aid = "my-affiliate-id";
++
++ // 仅在链接中尚未包含联盟 ID 时,追加带联盟 ID 的斜杠
++ const goglinks = document.querySelectorAll('a[href*="gog.com"]');
++ goglinks.forEach(function (el) {
++ if (!el.href.includes("pp=")) {
++ el.href = el.href.replace(/\?.*$/, "") + "?pp=" + aid;
++ }
++ });
},
{
// 选项放在这里
}
);
这样能行吗?可以,但它也在做一些多余的工作,因为我们是在查询整个 document 中的链接,而不是针对帖子元素。那么如何修复呢?
还记得我们传入方法的 element 参数吗?这时候它就派上用场了。
我们不再查询整个文档,而是查询我们要针对的元素。因此,我们将这行代码:
const goglinks = document.querySelectorAll('a[href*="gog.com"]');
改为:
const goglinks = element.querySelectorAll('a[href*="gog.com"]');
最终结果如下:
api.decorateCookedElement(
element =\u003e {
// 将下面的 "my-affiliate-id" 替换为你实际的联盟 ID
const aid = "my-affiliate-id";
// 仅在链接中尚未包含联盟 ID 时,追加带联盟 ID 的斜杠
-- const goglinks = document.querySelectorAll('a[href*="gog.com"]');
++ const goglinks = element.querySelectorAll('a[href*="gog.com"]');
goglinks.forEach(function (el) {
if (!el.href.includes("pp=")) {
el.href = el.href.replace(/\?.*$/, "") + "?pp=" + aid;
}
});
},
{
// 选项放在这里
}
);
现在效果很好,但我们还可以再优化一下。由于你只是给链接添加联盟 ID,因此在编辑器(composer)中并不需要触发这段代码。这时方法选项就派上用场了。
你可以传递给方法的一个选项是 onlyStream。
它的作用是什么?它告诉该方法,你只希望在帖子在主题内渲染时才执行此代码。让我们添加这个选项。
api.decorateCookedElement(
element =\u003e {
// 将下面的 "my-affiliate-id" 替换为你实际的联盟 ID
const aid = "my-affiliate-id";
// 仅在链接中尚未包含联盟 ID 时,追加带联盟 ID 的斜杠
const goglinks = element.querySelectorAll('a[href*="gog.com"]');
goglinks.forEach(function (el) {
if (!el.href.includes("pp=")) {
el.href = el.href.replace(/\?.*$/, "") + "?pp=" + aid;
}
});
},
{
++ onlyStream: true
}
);
现在,唯一剩下的就是将这段代码放入我们之前提到的特殊脚本标签中。
<script type="text/discourse-plugin" version="0.8.42">
api.decorateCookedElement(
element =\u003e {
// 将下面的 "my-affiliate-id" 替换为你实际的联盟 ID
const aid = "my-affiliate-id";
// 仅在链接中尚未包含联盟 ID 时,追加带联盟 ID 的斜杠
const goglinks = element.querySelectorAll('a[href*="gog.com"]');
goglinks.forEach(function (el) {
if (!el.href.includes("pp=")) {
el.href = el.href.replace(/\?.*$/, "") + "?pp=" + aid;
}
});
},
{
onlyStream: true
}
);
</script>
然后将其添加到你的组件的“头部(header)”标签页中,就完成了。我在这个示例中使用了 GOG,因为这是你询问的对象,但只要你知道 URL 结构,这种模式可以用于任何联盟计划。