Skip to content

Commit

Permalink
Merge pull request #266 from Alihtt/feature-markdown-add-id-extension
Browse files Browse the repository at this point in the history
Feature markdown add id extension
  • Loading branch information
agusmakmun authored Nov 14, 2024
2 parents 99eef77 + 62f3e6b commit 3efb54c
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
__pycache__
build/
dist/
venv/
*.egg-info/
*.pypirc
*.pyc
Expand Down
27 changes: 17 additions & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,27 @@ FROM alpine:3.16.0

WORKDIR /app

RUN set -xe;
# Install required packages including tini
RUN set -xe && \
apk add --no-cache python3 py3-pip tini && \
pip install --upgrade pip setuptools-scm

# Copy project files
COPY . .

RUN apk add --no-cache python3 py3-pip tini; \
pip install --upgrade pip setuptools-scm; \
python3 setup.py install; \
python3 martor_demo/manage.py makemigrations; \
python3 martor_demo/manage.py migrate; \
addgroup -g 1000 appuser; \
adduser -u 1000 -G appuser -D -h /app appuser; \
# Install Python dependencies and setup Django app
RUN python3 setup.py install && \
python3 martor_demo/manage.py makemigrations && \
python3 martor_demo/manage.py migrate

# Create user and set permissions
RUN addgroup -g 1000 appuser && \
adduser -u 1000 -G appuser -D -h /app appuser && \
chown -R appuser:appuser /app

USER appuser
EXPOSE 8000/tcp
ENTRYPOINT [ "tini", "--" ]
CMD [ "python3", "/app/martor_demo/manage.py", "runserver", "0.0.0.0:8000" ]

# Use full path for tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["python3", "/app/martor_demo/manage.py", "runserver", "0.0.0.0:8000"]
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* Supports Django Admin
* Toolbar Buttons
* Highlight `pre`
* Custom ID Attributes (Add custom IDs to any text element using `{#custom-id}` syntax, e.g., `# Heading1 {#my-h1-id}`, for easy linking and navigation.


### Preview
Expand Down Expand Up @@ -140,6 +141,7 @@ MARTOR_MARKDOWN_EXTENSIONS = [
'martor.extensions.emoji', # to parse markdown emoji
'martor.extensions.mdx_video', # to parse embed/iframe video
'martor.extensions.escape_html', # to handle the XSS vulnerabilities
"martor.extensions.mdx_add_id", # to parse id like {#this_is_id}
]

# Markdown Extensions Configs
Expand Down
37 changes: 37 additions & 0 deletions martor/extensions/mdx_add_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import markdown
from xml.etree import ElementTree

# Regex pattern to detect `{#id_name}` at the end of the line
ADD_ID_RE = r"(.+?)\s\{#([a-zA-Z0-9_-]+)\}$"


class AddIDPattern(markdown.inlinepatterns.Pattern):
"""Pattern to match Markdown text ending with `{#id}` and set it as an ID."""

def handleMatch(self, m):
text_content = m.group(2).strip() # Actual text content
id_value = m.group(3) # The ID inside `{#id}`

# Create a <span> element to hold the text and ID
el = ElementTree.Element("span")
el.text = markdown.util.AtomicString(text_content)
el.set("id", id_value)
return el


class AddIDExtension(markdown.Extension):
"""Add ID Extension for Python-Markdown."""

def extendMarkdown(self, md: markdown.core.Markdown, *args):
"""Register AddIDPattern with the Markdown parser."""
md.inlinePatterns.register(AddIDPattern(ADD_ID_RE, md), "add_id", 9)


def makeExtension(*args, **kwargs):
return AddIDExtension(*args, **kwargs)


if __name__ == "__main__":
import doctest

doctest.testmod()
1 change: 1 addition & 0 deletions martor/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"martor.extensions.emoji", # to parse markdown emoji
"martor.extensions.mdx_video", # to parse embed/iframe video
"martor.extensions.escape_html", # to handle the XSS vulnerabilities
"martor.extensions.mdx_add_id", # to parse id like {#this_is_id}
],
)

Expand Down
13 changes: 13 additions & 0 deletions martor/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ def test_markdownify(self):
# f'<p><a class="direct-mention-link" href="https://python.web.id/author/{self.user.username}/">{self.user.username}</a></p>',
# )

# Id
response = self.client.post(
"/martor/markdownify/",
{
"content": "__Advertisement :)__ {#ad-section}\n###### h6 Heading {#h6-heading}"
},
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.content.decode("utf-8"),
'<p><span id="ad-section"><strong>Advertisement :)</strong></span></p>\n<h6><span id="h6-heading">h6 Heading</span></h6>',
) # noqa: E501

def test_markdownify_xss_handled(self):
xss_payload_1 = "[aaaa](javascript:alert(1))"
response_1 = markdownify(xss_payload_1)
Expand Down

0 comments on commit 3efb54c

Please sign in to comment.