Skip to content

Commit

Permalink
Heading functions can now use a Reference object
Browse files Browse the repository at this point in the history
  • Loading branch information
karelvaculik committed Aug 30, 2023
1 parent 4f3df55 commit 83bd5df
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 112 deletions.
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
## 0.2.0 (2023-08-18)

- Updated to newer versions of optional dependencies.
- Added new text elements `div` and `span`. Added new parameters to HTML elements - in particular `cl` and `attrs`.
- Deprecated `print_html` function. New `print` should be used instead.
- Deprecated `print_code` function. New `print_source_code` should be used instead.
- Added documentation.
- Added new text elements `div()` and `span()`. Added new parameters to HTML elements - in particular `cl` and `attrs`.
- Deprecated `print_html()` function. New `print()` should be used instead.
- Deprecated `print_code()` function. New `print_source_code()` should be used instead.
- Replaced code-prettify with highlight.js for code blocks.
- `print_h1`, ..., `print_h6` functions can now take a `Reference` object.

## 0.1.1 (2021-09-14)

Expand Down
51 changes: 51 additions & 0 deletions docs/examples/references.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

import pyreball as pb
import seaborn as sns

pb.set_title("References to Plots and Tables")

ref_ch_1 = pb.Reference()

pb.print_h1("First Table", reference=ref_ch_1)

N = 10
np.random.seed(1)
df = pd.DataFrame({"x": np.arange(1, N + 1), "y": np.random.random(N) * 4 + 3})
pb.print_table(df, caption="A data table.")

img_reference = pb.Reference()
table_ref = pb.Reference()
pb.print_div(
f"It is also possible to create references to tables and figures. "
f"For example Table {table_ref} shows sortable columns and "
f"Fig. {img_reference} displays a scatterplot. "
f"Each reference has a default text to be displayed, "
f"but this text can be overriden by using {pb.code('__call__()')} "
f"method on the reference when pasting it into the text. "
f"For example, here is a link to {img_reference('Scatterplot')}."
)
pb.print_table(
df, caption="A sortable table with a reference", reference=table_ref, sortable=True
)

pb.print_table(
df, caption="A table sorted by y column", sorting_definition=("y", "asc")
)

pb.print_h1("Charts")

fig, ax = plt.subplots()
sns.scatterplot(x="x", y="y", ax=ax, data=df)
ax.set(xlabel="x", ylabel="y")
pb.plot_graph(fig, caption="A plot with a reference.", reference=img_reference)

pb.print_div(
f"Note that you can use the references in your text multiple times, "
f"see again the reference to Table {table_ref} and Fig. {img_reference}. "
f"Of course, we cannot assign a single reference to multiple tables or figures. "
f"Last, but not least, one can use reference to Chapter {ref_ch_1}. "
f"Again, we can override the text and create a link to {ref_ch_1('First Chapter')}."
)
6 changes: 5 additions & 1 deletion docs/references.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# References

TBD
To create anchors to various items on the HTML page, it is possible to use [`Reference`](../api/pyreball_html/#pyreball.html.Reference) class.

{{ inline_source("docs/examples/references.py") }}

<iframe style="border:2px solid;" src="../examples/references.html" height="800" width="100%" title="Iframe Example"></iframe>
4 changes: 2 additions & 2 deletions examples/longer_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ def factorial(n):
pb.print_h2("References to Plots and Tables")

# Creating a reference to a graph and a table:
img_reference = pb.create_reference()
table_ref = pb.create_reference()
img_reference = pb.Reference()
table_ref = pb.Reference()
pb.print_div(
f"It is also possible to create references to tables and figures. "
f"For example Table {table_ref} shows sortable columns and Fig. {img_reference} displays a scatterplot."
Expand Down
2 changes: 1 addition & 1 deletion pyreball/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
__version__ = "0.2.0-alpha.1"

from pyreball.html import (
create_reference,
Reference,
plot_graph,
plot_multi_graph,
print,
Expand Down
63 changes: 49 additions & 14 deletions pyreball/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,16 @@
"""


def replace_ids(filename: Path) -> None:
# collect all ids in form of table-N-M
def _replace_ids(html_path: Path) -> None:
"""Replace IDs of HTML elements to create working anchors based on references.
Args:
html_path: Path to the HTML file.
"""
# collect all ids in form of "table-N-M", "img-N-M"
all_table_and_img_ids = set()
with open(filename, "r") as f:
chapter_text_replacemenets = []
with open(html_path, "r") as f:
for line in f:
# note that we don't need to replace only "table" ids by also "img" etc.
results = re.findall(r"table-id[\d]+-[\d]+", line)
Expand All @@ -124,10 +130,24 @@ def replace_ids(filename: Path) -> None:
results = re.findall(r"img-id[\d]+-[\d]+", line)
if results:
all_table_and_img_ids.update(results)
# now collect heading references:
results = re.findall(r"ch_id[\d]+_[^\"]+", line)
if results:
all_table_and_img_ids.update(results)
# obtain also the heading text
search_result_text = re.search(results[0] + r"\">([^<]+)<", line)
link_text = search_result_text.group(1) if search_result_text else ""
search_result_id = re.search(r"_(id[\d]+)_", results[0])
link_id = search_result_id.group(1) if search_result_id else ""
if link_id and link_text:
chapter_text_replacemenets.append(
(f">{link_id}<", f">{link_text}<")
)
# Prepare all replacement definitions for a substitutor below
replacements = []
for element_id in all_table_and_img_ids:
# Tables and images:
re_results = re.search(r"(.+)-(id\d+)-(\d+)", element_id)

if re_results:
# this must be first
replacements.append(
Expand All @@ -144,14 +164,29 @@ def replace_ids(filename: Path) -> None:
)
)

# Headings
re_results = re.search(r"ch_(id\d+)_(.+)", element_id)
if re_results:
# this must be first
replacements.append(
(
"ref-" + re_results.group(1),
"ch_" + re_results.group(2),
)
)
# this must be second (because it would catch the first case as well)
replacements.append((element_id, f"ch_{re_results.group(2)}"))
# add also replacements for links to chapters
replacements += chapter_text_replacemenets

# replace all table-N-M with table-M and Table N with Table M
substitutor = Substitutor(replacements=replacements)
modified_lines = []
with open(filename, "r") as f:
with open(html_path, "r") as f:
for line in f:
modified_lines.append(substitutor.sub(line))

with open(filename, "w") as f:
with open(html_path, "w") as f:
f.writelines(modified_lines)


Expand Down Expand Up @@ -365,8 +400,8 @@ def get_config_directory() -> Path:
# the config was generated, let's find out its directory
config_directory = Path(Path(PATH_TO_CONFIG_LOCATION).read_text())
if (
not (config_directory / CONFIG_INI_FILENAME).exists()
or not (config_directory / STYLES_TEMPLATE_FILENAME).exists()
not (config_directory / CONFIG_INI_FILENAME).exists()
or not (config_directory / STYLES_TEMPLATE_FILENAME).exists()
):
logger.warning(
f"{CONFIG_INI_FILENAME} or {STYLES_TEMPLATE_FILENAME} was not found in {config_directory}. "
Expand All @@ -380,7 +415,7 @@ def get_config_directory() -> Path:


def _get_output_dir_and_file_stem(
input_path: Path, output_path_str: Optional[str]
input_path: Path, output_path_str: Optional[str]
) -> Tuple[Path, str]:
if not input_path.is_file():
raise ValueError(f"File {input_path} does not exist.")
Expand Down Expand Up @@ -441,10 +476,10 @@ def main() -> None:
carefully_remove_directory_if_exists(directory=Path(path_str))

script_definitions = (
JAVASCRIPT_CHANGE_EXPAND
+ JAVASCRIPT_ON_LOAD
+ JAVASCRIPT_SORTABLE_TABLE
+ JAVASCRIPT_ROLLING_PLOTS
JAVASCRIPT_CHANGE_EXPAND
+ JAVASCRIPT_ON_LOAD
+ JAVASCRIPT_SORTABLE_TABLE
+ JAVASCRIPT_ROLLING_PLOTS
)

css_definitions = get_css(
Expand Down Expand Up @@ -476,7 +511,7 @@ def main() -> None:
with open(html_path, "a") as f:
f.write(html_end)

replace_ids(html_path)
_replace_ids(html_path)
insert_heading_title_and_toc(
filename=html_path, include_toc=parameters["toc"] == "yes"
)
Expand Down
Loading

0 comments on commit 83bd5df

Please sign in to comment.