link characters and npcs in texts
This commit is contained in:
parent
a7294f309a
commit
dbd7193c90
|
@ -0,0 +1,22 @@
|
|||
# Generated by Django 4.2.1 on 2023-08-25 20:42
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("guild", "0014_alter_playsession_npcs"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="character",
|
||||
name="name",
|
||||
field=models.CharField(max_length=255, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="npc",
|
||||
name="name",
|
||||
field=models.CharField(max_length=255, unique=True),
|
||||
),
|
||||
]
|
|
@ -77,7 +77,7 @@ class Character(models.Model):
|
|||
RETIRED = "RETIRED", _("Retired")
|
||||
UNKNOWN = "UNKNOWN", _("Unknown")
|
||||
|
||||
name = models.CharField(max_length=255)
|
||||
name = models.CharField(max_length=255, unique=True)
|
||||
description = models.TextField()
|
||||
status = models.CharField(
|
||||
max_length=16, choices=Status.choices, default=Status.ALIVE
|
||||
|
@ -106,6 +106,10 @@ class Character(models.Model):
|
|||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@classmethod
|
||||
def get_by_name(cls, name):
|
||||
return cls.objects.filter(name=name).get()
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("guild:character_detail", kwargs={"pk": self.pk})
|
||||
|
||||
|
@ -203,7 +207,7 @@ class Reward(models.Model):
|
|||
|
||||
|
||||
class NPC(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
name = models.CharField(max_length=255, unique=True)
|
||||
description = models.TextField()
|
||||
|
||||
picture = models.ImageField(
|
||||
|
@ -222,3 +226,7 @@ class NPC(models.Model):
|
|||
|
||||
def get_absolute_url(self):
|
||||
return reverse("guild:npc_detail", kwargs={"pk": self.pk})
|
||||
|
||||
@classmethod
|
||||
def get_by_name(cls, name):
|
||||
return cls.objects.filter(name=name).get()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import markdown
|
||||
from django import template
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from guild_md.entity_links import GuildLinkExtension
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
@ -8,4 +9,4 @@ register = template.Library()
|
|||
@register.filter(name="md")
|
||||
@stringfilter
|
||||
def md(value):
|
||||
return markdown.markdown(value)
|
||||
return markdown.markdown(value, extensions=[GuildLinkExtension()])
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
"""
|
||||
Guild Journal Extension for Python-Markdown
|
||||
======================================
|
||||
|
||||
Converts [[NPC/Frankie]] to links.
|
||||
|
||||
Original code Copyright [Waylan Limberg](http://achinghead.com/).
|
||||
|
||||
All changes Copyright The Python Markdown Project
|
||||
|
||||
License: [BSD](https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
"""
|
||||
|
||||
from markdown.extensions import Extension
|
||||
from markdown.inlinepatterns import InlineProcessor
|
||||
from guild.models import NPC, Character
|
||||
import xml.etree.ElementTree as etree
|
||||
|
||||
|
||||
def build_url(category: str, name):
|
||||
"""Build a URL from the label, a base, and an end."""
|
||||
if category.lower() == "char":
|
||||
try:
|
||||
return Character.get_by_name(name).get_absolute_url()
|
||||
except Character.DoesNotExist:
|
||||
return ""
|
||||
elif category.lower() == "npc":
|
||||
try:
|
||||
return NPC.get_by_name(name).get_absolute_url()
|
||||
except NPC.DoesNotExist:
|
||||
return ""
|
||||
return ""
|
||||
|
||||
|
||||
class GuildLinkExtension(Extension):
|
||||
def extendMarkdown(self, md):
|
||||
self.md = md
|
||||
|
||||
# append to end of inline patterns
|
||||
GUILD_RE = r"\[\[([\w0-9_ -]+)\/([\w0-9_ -]+)\]\]"
|
||||
wikilinkPattern = GuildLinksInlineProcessor(GUILD_RE, self.getConfigs())
|
||||
wikilinkPattern.md = md
|
||||
md.inlinePatterns.register(wikilinkPattern, "guildlinks", 75)
|
||||
|
||||
|
||||
class GuildLinksInlineProcessor(InlineProcessor):
|
||||
def __init__(self, pattern, config):
|
||||
super().__init__(pattern)
|
||||
self.config = config
|
||||
|
||||
def handleMatch(self, m, data):
|
||||
if m.group(1).strip() and m.group(2).strip():
|
||||
category = m.group(1).strip()
|
||||
name = m.group(2).strip()
|
||||
url = build_url(category, name)
|
||||
a = etree.Element("a")
|
||||
a.text = name
|
||||
a.set("href", url)
|
||||
if url == "":
|
||||
a.set("class", "invalid-url")
|
||||
else:
|
||||
a = ""
|
||||
return a, m.start(0), m.end(0)
|
||||
|
||||
|
||||
def makeExtension(**kwargs): # pragma: no cover
|
||||
return GuildLinkExtension(**kwargs)
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
[pytest]
|
||||
DJANGO_SETTINGS_MODULE = guild_journal.settings
|
||||
python_files = tests.py test_*.py *_tests.py
|
|
@ -0,0 +1,48 @@
|
|||
import pytest
|
||||
import markdown
|
||||
from guild_md.entity_links import GuildLinkExtension
|
||||
from guild.models import NPC, Character
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
["objs", "md", "html"],
|
||||
[
|
||||
[
|
||||
[],
|
||||
"",
|
||||
"",
|
||||
],
|
||||
[
|
||||
[Character(name="Blimm")],
|
||||
"[[Char/Blimm]]",
|
||||
'<p><a href="/characters/1/">Blimm</a></p>',
|
||||
],
|
||||
[
|
||||
[Character(name="Blimm")],
|
||||
"[[Char/Lun]]",
|
||||
'<p><a class="invalid-url" href="">Lun</a></p>',
|
||||
],
|
||||
[
|
||||
[Character(name="Blimm"), Character(name="Lun")],
|
||||
"[[Char/Lun]] and [[Char/Blimm]]",
|
||||
'<p><a href="/characters/2/">Lun</a> and <a href="/characters/1/">Blimm</a></p>',
|
||||
],
|
||||
[
|
||||
[NPC(name="Frank")],
|
||||
"[[NPC/Frank]]",
|
||||
'<p><a href="/npcs/1/">Frank</a></p>',
|
||||
],
|
||||
[
|
||||
[NPC(name="Frank"), Character(name="Blimm")],
|
||||
"[[Char/Blimm]] and [[NPC/Frank]]",
|
||||
'<p><a href="/characters/1/">Blimm</a> and <a href="/npcs/1/">Frank</a></p>',
|
||||
],
|
||||
],
|
||||
)
|
||||
@pytest.mark.django_db
|
||||
def test_link_conversion(objs, md, html):
|
||||
for obj in objs:
|
||||
obj.save()
|
||||
|
||||
output = markdown.markdown(md, extensions=[GuildLinkExtension()])
|
||||
assert output == html
|
Loading…
Reference in New Issue