Skip to content

Commit

Permalink
Fixed a Bug Where Table of Contents Wasn't Linking Correctly (#164)
Browse files Browse the repository at this point in the history
* Added a test to catch the user's bug

* Created a fix for the bug

* Cleaned up code

* Removed unused import

* Updated package version

* Updated changelog

* Expanded testing

* Updated poetry packages and changed requirements to 3.9+

* Reworked workflow

* Fixed a strange test case

* Updated version history

* Fixed a linter issue

* Cleaned up poetry file

* Updated python support table
  • Loading branch information
jrg94 authored Nov 19, 2024
1 parent 1a2f8ee commit 34a1d75
Show file tree
Hide file tree
Showing 9 changed files with 466 additions and 593 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: true
matrix:
python-version: ["3.8"]
python-version: ["3.9"]
poetry-version: ["1.4"]
os: ["ubuntu-latest"]

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: true
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
poetry-version: ["1.4"]
os: [ubuntu-latest, macos-latest, windows-latest]

Expand Down
9 changes: 5 additions & 4 deletions docs/python-support.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Python,3.11,3.10,3.9,3.8
SnakeMD >= 2.0,Yes,Yes,Yes,Yes
SnakeMD 0.12 - 0.15,Yes,Yes,Yes,Yes
SnakeMD < 0.12,,Yes,Yes,Yes
Python,3.13,3.12,3.11,3.10,3.9,3.8
SnakeMD >= 2.2.1,Yes,Yes,Yes,Yes,Yes,
SnakeMD 2.0 - 2.2.0,,,Yes,Yes,Yes,Yes
SnakeMD 0.12 - 0.15,,,Yes,Yes,Yes,Yes
SnakeMD < 0.12,,,,Yes,Yes,Yes
12 changes: 12 additions & 0 deletions docs/version-history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ as follows:
v2.x
----

* v2.2.1 [:pr:`#164`]

* Fixed a bug where headings with special characters would not link properly in the table of contents
* Dropped support for Python 3.8 due to deprecation
* Added support for Python 3.12 and 3.13

* v2.2.0 [:pr:`#152`, :pr:`153`, :pr:`#159`]

* Added documentation throughout the repo
* Expanded testing
* Added CSVTable Template and accompanying documentation

* v2.2.0b1 [:pr:`#140`, :pr:`#142`, :pr:`#143`, :pr:`#144`, :pr:`#145`, :pr:`#146`, :pr:`#149`]

* Expanded the Element requirements to include :code:`__repr__()` for developer friendly strings
Expand Down
985 changes: 410 additions & 575 deletions poetry.lock

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[tool.poetry]
name = "SnakeMD"
description = "A markdown generation library for Python."
version = "2.2.0"
version = "2.2.1"
license = "MIT"

authors = [
Expand All @@ -17,10 +17,11 @@ documentation = "https://www.snakemd.io/en/latest/docs/"
classifiers=[
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Operating System :: OS Independent",
"Topic :: Documentation :: Sphinx",
]
Expand All @@ -29,7 +30,7 @@ classifiers=[
Changelog = "https://www.snakemd.io/en/latest/version-history/"

[tool.poetry.dependencies]
python = "^3.8"
python = "^3.9"

[tool.poetry.group.test.dependencies]
coverage = "^7.2"
Expand All @@ -45,7 +46,7 @@ sphinx_rtd_theme = "^1.2"
black = "^23.3"
isort = "^5.12"
pydocstringformatter = "^v0.7"
pylint = "^2.17"
pylint = "^3.3"

# Pytest settings
[tool.pytest.ini_options]
Expand All @@ -71,7 +72,7 @@ fail_under = 95
# Black formatting settings
[tool.black]
line-length = 88
target-version = ['py38', 'py39', 'py310', 'py311']
target-version = ['py39', 'py310', 'py311', 'py312', 'py313']

# Pylint settings
[tool.pylint.format]
Expand All @@ -87,7 +88,7 @@ disable = [
# isort setttings
[tool.isort]
profile = "black"
py_version = 311
py_version = 313

# pydocstringformatter settings
[tool.pydocstringformatter]
Expand Down
21 changes: 17 additions & 4 deletions snakemd/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import csv
import logging
import os
import re

from .elements import Element, Heading, Inline, MDList, Table

Expand Down Expand Up @@ -157,6 +158,16 @@ def __str__(self) -> str:
def __repr__(self) -> str:
return f"TableOfContents(levels={self._levels!r})"

@staticmethod
def _convert_heading_to_anchor(text: str):
"""
A helper method for generating anchor text.
Technique is borrowed from the python markdown's
toc extension.
"""
anchor = re.sub(r'[^\w\s-]', '', text).strip().lower()
return re.sub(r'[-\s]+', "-", anchor)

def _get_headings(self) -> list[Heading]:
"""
Retrieves the list of headings from the current document.
Expand All @@ -172,7 +183,7 @@ def _get_headings(self) -> list[Heading]:

def _assemble_table_of_contents(
self, headings: list[Heading], position: int
) -> tuple(MDList, int):
) -> tuple[MDList, int]:
"""
Assembles the table of contents from the headings in the document.
Expand All @@ -186,10 +197,12 @@ def _assemble_table_of_contents(
level = headings[i].get_level()
table_of_contents = []
while i < len(headings) and headings[i].get_level() >= level:
if headings[i].get_level() == level:
heading_text: str = headings[i].get_text()
heading_level: int = headings[i].get_level()
if heading_level == level:
line = Inline(
headings[i].get_text(),
link=f"#{'-'.join(headings[i].get_text().lower().split())}",
heading_text,
link=f"#{self._convert_heading_to_anchor(heading_text)}",
)
table_of_contents.append(line)
i += 1
Expand Down
3 changes: 1 addition & 2 deletions tests/elements/test_quote.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from snakemd import Code, Heading, HorizontalRule, MDList, Quote
from snakemd import Code, Heading, HorizontalRule, MDList, Quote, Raw

# Constructor tests

Expand Down Expand Up @@ -48,6 +48,5 @@ def test_quote_mdlist():

def test_repr_can_create_object():
quote = Quote("")
exec("from snakemd import Raw")
obj = eval(repr(quote))
assert isinstance(obj, Quote)
12 changes: 12 additions & 0 deletions tests/templates/test_table_of_contents.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import markdown

from snakemd.document import Document
from snakemd.templates import TableOfContents

Expand All @@ -15,6 +17,16 @@ def test_table_of_contents_one_section():
doc.add_heading("Section", level=2)
toc.load(doc.get_elements())
assert str(toc) == "1. [Section](#section)"
assert markdown.markdown(str(doc), extensions=['toc']) == "<h2 id=\"section\">Section</h2>"


def test_table_of_contents_one_section_special_chars():
doc = Document()
toc = TableOfContents()
doc.add_heading("Section's", level=2)
toc.load(doc.get_elements())
assert str(toc) == "1. [Section's](#sections)"
assert markdown.markdown(str(doc), extensions=['toc']) == "<h2 id=\"sections\">Section's</h2>"


def test_table_of_contents_many_sections():
Expand Down

0 comments on commit 34a1d75

Please sign in to comment.