问题在于:我希望用户能够以 RPG 角色的身份发帖。我希望他们能够在帖子中插入一个模板,例如以下所示:
[wrap="characterpost"]
[characterav]https://image.link.example.png[/characterav]
[charactername][[Character Name]][/charactername]
[/wrap]
然后使用一段脚本,让该图片替换掉原始头像,并将 charactername 主题链接放在用户名前面。例如,如果帖子通常显示为“用户名”,我希望将其替换为“角色名 由 用户名 扮演”。
(“角色名”将包含一个指向该角色资料帖的链接,希望仅使用 wikilinks 主题组件,以便更易于使用。)
我将一个帖子骨架粘贴到 Codepen 中,并成功编写了一段 JavaScript 来实现上述功能。然而,当我尝试将其添加到帖子装饰器(post decorator)中并通过 API 使其实时运行时,却遇到了障碍。
这是我目前在 common>header 中的代码:
<script type="text/discourse-plugin" version="0.8">
api.decorateCookedElement(
element => {
// 在帖子中查找 characterpost 标签
const characterPost = element.querySelector('[data-wrap="characterpost"]');
// 查找 characterpost 标签的父元素,其中包含头像和用户名
const characterPostParent = characterPost.closest('article');
// 将其背景设为红色,以检查是否正常工作
characterPostParent.style.backgroundColor = "red";
},
{
id: 'render-character-post', onlyStream: true, afterAdopt: true
}
);
</script>
这段代码一直在报错。是否可以通过 decorateCookedElement 访问帖子的 “article” 包装器,以便我获取用户名和头像?如果不行,我应该如何实现这一功能?
你好,unfairest,
我偶然发现了这个帖子,我想我可以试试!
这是第一个版本;希望代码不会太糟糕。 
我没有广泛测试所有边缘情况。这是一个起点。
- 预期的 wrap 格式:
[wrap=character avatar=\"<URL>\" name=\"<Name>\"][/wrap]
- 确保
[wrap] 下方有一个空行
- 您可以使用 CSS 自定义角色名称(请参阅
character 和 character-extra 类)
如果您有任何问题,请告诉我 
头部
<script type="text/discourse-plugin" version="0.8.13">
let characters = new Map();
function searchTag(obj, tag) {
if (!obj || !obj.firstObject) return;
const firstObj = obj.firstObject;
return firstObj.tagName === tag ? firstObj : searchTag(firstObj.children, tag);
}
api.addPostTransformCallback(post =>
{
if (post.post_number <= 1 || post.post_type !== 1) {
return;
}
const matches = post.cooked.match(/data-wrap="character"\s+data-avatar="(?<avatar>[^"]+)"\s+data-name="(?<name>[^"]+)"/i);
if (!matches) {
characters.delete(post.id);
return;
}
// TODO: sanity check for avatar/name
const {name, avatar} = matches.groups;
characters.set(post.id, {name, avatar});
});
api.reopenWidget("post-avatar", {
html(attrs) {
const html = this._super(attrs);
if (attrs.id && characters.has(attrs.id)) {
const imageHtml = searchTag(html, 'IMG');
if (imageHtml) {
imageHtml.properties.attributes.src = characters.get(attrs.id).avatar;
}
}
return html;
}
});
api.reopenWidget("poster-name", {
html(attrs) {
let html = this._super(attrs);
if (attrs.id && characters.has(attrs.id)) {
const h = require("virtual-dom").h;
html = [
h('span.character', this.userLink(attrs, characters.get(attrs.id).name)),
h('span.character-extra', 'played by'), // optional
...html
];
}
return html;
}
});
</script>
CSS
.names {
.character a {
font-weight: bold;
color: var(--tertiary-high);
}
.character-extra {
}
}
.cooked, .d-editor-preview {
p:has(> [data-wrap="character"]) {
display: none;
}
p:has(> [data-wrap="character"]) + * {
margin-top: 0;
}
}
这是它外观的小演示:
asc
3
这太酷了,谢谢分享!我也在找类似的东西。您知道这是否也会影响帖子在搜索中的显示方式吗?
好问题!标签名称及其内容是帖子内容的一部分;这可能会影响搜索结果。
我将尝试更简洁的方法,例如使用模态框,然后将其保存在自定义字段中。
编辑:我想我误解了
如果您谈论的是搜索结果中出现更改,答案是否定的(HTML也不会出现)。
Heliosurge
(Dan DeMontmorency)
5
这很酷。你的视频滚动得很快。网址是在论坛网站上吗?
Heliosurge
(Dan DeMontmorency)
10
也许可以考虑在社区维基上提议一个论坛模板指南。因为人们经常来寻找不同类型论坛设置的灵感。
在这种情况下,可能有点小众。但可以有一个桌面角色扮演游戏模板,其中包含您创建的这个功能。