El problema: Quiero que los usuarios puedan publicar como personajes de RPG. Me gustaría que pudieran insertar una plantilla en una publicación, algo como esto:
[wrap="characterpost"]
[characterav]https://image.link.example.png[/characterav]
[charactername][[Nombre del personaje]][/charactername]
[/wrap]
Y luego usar un script para que la imagen reemplace el avatar original y el enlace del tema charactername se coloque delante del nombre de usuario. Por ejemplo, si la publicación normalmente dice “Nombre de usuario”, quiero reemplazarlo con “Nombre del personaje interpretado por Nombre de usuario”.
(El “Nombre del personaje” incluiría un enlace a un tema con la hoja del personaje, con suerte usando el componente temático wikilinks para facilitar su uso).
Pegué un esqueleto de publicación en Codepen y pude escribir algo de javascript que haría exactamente esto. Sin embargo, cuando se trató de agregarlo a un decorador de publicaciones y hacerlo funcionar en vivo con la API, me encontré con un obstáculo.
Aquí está lo que tengo en common>header ahora mismo:
<script type="text/discourse-plugin" version="0.8">
api.decorateCookedElement(
element => {
// encuentra la etiqueta characterpost dentro de la publicación
const characterPost = element.querySelector('[data-wrap="characterpost"]');
// encuentra el padre de la etiqueta characterpost, que contiene el avatar y el nombre de usuario
const characterPostParent = characterPost.closest('article');
// lo pongo rojo para ver si funciona
characterPostParent.style.backgroundColor = "red";
},
{
id: 'render-character-post', onlyStream: true, afterAdopt: true
}
);
</script>
Esto ha estado arrojando un error. ¿Es posible acceder al “wrapper” del “article” para las publicaciones usando decorateCookedElement para poder llegar al nombre de usuario y al avatar? Si no, ¿cómo puedo abordar esto?
¡Me encontré con esta publicación y pensé que podría intentarlo!
Aquí está la primera versión; espero que el código no sea demasiado horrible.
No probé exhaustivamente todos los casos extremos. Es un punto de partida.
Formato de envoltura esperado: [wrap=character avatar=\"<URL>\"]<Nombre>[/wrap]
Asegúrate de que haya una línea vacía debajo de [wrap]
Puedes personalizar el nombre del personaje con CSS (consulta las clases character y character-extra)
Avísame si tienes algún problema
Head
<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>
¡Esto es muy genial, gracias por compartir! Yo también estaba buscando algo similar. ¿Sabes si esto también afecta cómo aparecen las publicaciones en la búsqueda?
¡Buena pregunta! El nombre de la etiqueta y su contenido forman parte del contenido de la publicación; esto podría afectar el resultado de la búsqueda.
Intentaré algo más limpio, como usar una ventana modal y guardar en campos personalizados en su lugar.
EDITAR: Creo que entendí mal si te refieres a que los cambios aparezcan en el resultado de la búsqueda, la respuesta es no (tampoco aparecerá el HTML).
Pensar que podría ser una buena idea proponer, quizás en la wiki de la comunidad, una guía de plantillas de foros. A menudo, la gente busca ideas sobre diferentes tipos de configuraciones de foros. En este caso, podría ser un poco específico. Pero una plantilla de RPG de mesa que incluya esta característica que creaste.