Skip to content

Commit 6e5899a

Browse files
committed
markdown: Fix graphicspath bug
Pattern matching was too rigid, replace with regex expression. Also make `markdown` non-private so it appears in API docs.
1 parent cf3b7cd commit 6e5899a

File tree

8 files changed

+75
-27
lines changed

8 files changed

+75
-27
lines changed

docs/source/filters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def generate_filters_docs():
2222
filters = (
2323
i.name
2424
for i in pkgutil.iter_modules(in2lambda.filters.__path__)
25-
if i.name[0] != "_"
25+
if i.name != "markdown"
2626
)
2727

2828
for filter_name in filters:

in2lambda/filters/PartPartSolSol/filter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import panflute as pf
88

99
from in2lambda.api.module import Module
10-
from in2lambda.filters._markdown import filter
10+
from in2lambda.filters.markdown import filter
1111

1212

1313
@filter

in2lambda/filters/PartSolPartSol/filter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import panflute as pf
99

1010
from in2lambda.api.module import Module
11-
from in2lambda.filters._markdown import filter
11+
from in2lambda.filters.markdown import filter
1212

1313

1414
@filter

in2lambda/filters/PartsOneSol/filter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import panflute as pf
1111

1212
from in2lambda.api.module import Module
13-
from in2lambda.filters._markdown import filter
13+
from in2lambda.filters.markdown import filter
1414

1515

1616
@filter

in2lambda/filters/PartsSepSol/filter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import panflute as pf
1111

1212
from in2lambda.api.module import Module
13-
from in2lambda.filters._markdown import filter
13+
from in2lambda.filters.markdown import filter
1414

1515

1616
@filter
Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Generic helper functions used during the Pandoc filter stage for markdown conversion."""
22

3+
import os
4+
import re
35
from functools import cache
46
from pathlib import Path
57

@@ -13,60 +15,103 @@
1315

1416
@cache
1517
def image_directories(tex_file: str) -> list[str]:
16-
"""Determines the image directories referenced by `graphicspath` in a given TeX document.
18+
r"""Determines the image directories referenced by `graphicspath` in a given TeX document.
1719
1820
Args:
1921
tex_file: The absolute path to a TeX file
2022
2123
Returns:
2224
The exact contents of `graphicspath`, regardless of whether the directories are
2325
absolute or relative.
26+
27+
Examples:
28+
>>> from in2lambda.filters.markdown import image_directories
29+
>>> import tempfile
30+
>>> import os
31+
>>> # Example TeX file with a graphicspath
32+
>>> temp_dir = tempfile.mkdtemp()
33+
>>> tex_file = os.path.join(temp_dir, 'test.tex')
34+
>>> with open(tex_file, 'w') as f:
35+
... f.write("\graphicspath{{subdir1/}{subdir2/}{subdir3/}}")
36+
45
37+
>>> image_directories(tex_file)
38+
['subdir1/', 'subdir2/', 'subdir3/']
39+
>>> with open(tex_file, 'w') as f:
40+
... f.write("\graphicspath{ { subdir1/ }, { subdir2/ }, { subdir3/ } }")
41+
57
42+
>>> image_directories.cache_clear()
43+
>>> image_directories(tex_file)
44+
['subdir1/', 'subdir2/', 'subdir3/']
45+
>>> with open(tex_file, 'w') as f:
46+
... f.write("No image directory")
47+
18
48+
>>> image_directories.cache_clear()
49+
>>> image_directories(tex_file)
50+
[]
2451
"""
2552
with open(tex_file, "r") as file:
2653
for line in file:
27-
# Assumes line is in the format \graphicspath{ {...}, {...}, ...}
2854
if "graphicspath" in line:
29-
return [
30-
i.strip("{").rstrip("}")
31-
for i in line.replace(" ", "")[len("\graphicspath{") : -1].split(
32-
","
33-
)
34-
]
55+
# Matches anything surrounded by curly braces, but excludes the top level
56+
# graphicspath brace.
57+
return [match.strip() for match in re.findall(r"{([^{]*?)}", line)]
3558
return []
3659

3760

61+
# TODO: This assumes the file extension is included, but that isn't required by LaTeX
62+
# See: https://www.overleaf.com/learn/latex/Inserting_Images#Generating_high-res_and_low-res_images
3863
def image_path(image_name: str, tex_file: str) -> Optional[str]:
39-
"""Determines the absolute path to an image referenced in a tex_file.
64+
r"""Determines the absolute path to an image referenced in a tex_file.
4065
4166
Args:
4267
image_name: The file name of the image e.g. example.png
4368
tex_file: The TeX file that references the image.
4469
4570
Returns:
4671
The absolute path to the image if it can be found. If not, it returns None.
72+
73+
Examples:
74+
>>> from in2lambda.filters.markdown import image_path
75+
>>> import tempfile
76+
>>> import os
77+
>>> # Example TeX file with a subdirectory
78+
>>> temp_dir = tempfile.mkdtemp()
79+
>>> tex_file = os.path.join(temp_dir, 'test.tex')
80+
>>> with open(tex_file, 'w') as f:
81+
... f.write("\graphicspath{{./subdir1/}{./subdir2/}{./subdir3/}}")
82+
51
83+
>>> # Example image in a relative subdirectory
84+
>>> sub_dir = os.path.join(temp_dir, 'subdir3')
85+
>>> os.makedirs(sub_dir)
86+
>>> with open(os.path.join(sub_dir, 'inside_folder.png'), 'w') as f:
87+
... pass
88+
>>> image_path("inside_folder.png", tex_file) == os.path.join(temp_dir, 'subdir3', "inside_folder.png")
89+
True
90+
>>> # Absolute path provided
91+
>>> image_path(os.path.join(temp_dir, 'subdir3', "inside_folder.png"), tex_file) == os.path.join(temp_dir, 'subdir3', "inside_folder.png")
92+
True
4793
"""
4894
# In case the filename is the exact absolute/relative location to the image
4995
# When handling relative locations (i.e. begins with dot), first go to the directory of the TeX file.
50-
filename = (
51-
f"{str(Path(tex_file).parent)}/" if image_name[0] == "." else ""
52-
) + image_name
96+
97+
filename = os.path.join(
98+
str(Path(tex_file).parent) if image_name[0] == "." else "", image_name
99+
)
53100

54101
if Path(filename).is_file():
55-
return filename
102+
return os.path.normpath(filename)
56103

57104
# Absolute or relative directories referenced by `graphicspath`
58105
image_locations = image_directories(tex_file)
59106

60107
for directory in image_locations:
61-
if directory[-1] != "/":
62-
directory += "/"
63-
filename = (
64-
(f"{str(Path(tex_file).parent)}/" if directory[0] == "." else "")
65-
+ directory
66-
+ image_name
108+
filename = os.path.join(
109+
str(Path(tex_file).parent) if directory[0] == "." else "",
110+
directory,
111+
image_name,
67112
)
68113
if Path(filename).is_file():
69-
return filename
114+
return os.path.normpath(filename)
70115
return None
71116

72117

in2lambda/katex_convert/katex_convert.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ def latex_to_katex(latex_string: str) -> str:
3434
3535
Returns:
3636
Hopefully, a valid KaTeX expression that's similar to the LaTeX expression.
37+
38+
Examples:
39+
>>>
3740
"""
3841
katex_string = replace_functions(delete_functions(latex_string))
3942
return katex_string
@@ -143,7 +146,7 @@ def brace_remover(latex_string: str, brace_start_index: int) -> str:
143146

144147

145148
if __name__ == "__main__":
146-
latex_input = """ \\textbf{Vector Algebra:} for two vectors $\\vec{a}$ and $\\vec{b}$ in $\\mathbb{R}^3$ given by \\norm{a}"""
149+
latex_input = "\\textbf{Vector Algebra:} for two vectors $\\vec{a}$ and $\\vec{b}$ in $\\mathbb{R}^3$ given by \\norm{a}"
147150

148151
katex_output = latex_to_katex(latex_input)
149152
print(katex_output)

in2lambda/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def runner(
130130
[
131131
i.name
132132
for i in pkgutil.iter_modules(in2lambda.filters.__path__)
133-
if i.name[0] != "_"
133+
if i.name != "markdown"
134134
],
135135
case_sensitive=False,
136136
),

0 commit comments

Comments
 (0)