Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

24 title #25

Merged
merged 2 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added examples/a.pdf
Binary file not shown.
5 changes: 4 additions & 1 deletion examples/src/2.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@

### Subsubsection 2

before

```python
```python {title=abc numbers=left}
AAA=1
```

```python {.output}
AAA=1
```

after

![figure](figure.pdf){#fig:figure}
90 changes: 69 additions & 21 deletions src/panpdf/filters/verbatim.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import annotations

import inspect
from dataclasses import dataclass
from typing import TYPE_CHECKING, ClassVar

Expand All @@ -10,12 +9,11 @@
from panpdf.tools import add_metadata_list, create_temp_file

if TYPE_CHECKING:
from collections.abc import Iterable
from pathlib import Path

from panflute import Doc, Element

DEFAULT_SHADE_COLOR = "\\definecolor{shadecolor}{RGB}{240,240,250}"


@dataclass(repr=False)
class Verbatim(Filter):
Expand All @@ -25,30 +23,80 @@ def __post_init__(self) -> None:
self.shaded = False

def action(self, elem: CodeBlock, doc: Doc) -> CodeBlock | list[Element]: # noqa: ARG002
if "output" not in elem.classes:
return elem

self.shaded = True
elem.classes.pop(elem.classes.index("output"))
pre = "\\vspace{-0.5\\baselineskip}\\definecolor{shadecolor}{rgb}{1,1,0.9}%"
return [RawBlock(pre, format="latex"), elem, RawBlock(DEFAULT_SHADE_COLOR, format="latex")]

if "output" in elem.classes:
return create_output(elem)

if "title" in elem.attributes:
return create_title(elem)

return create_default(elem)

def finalize(self, doc: Doc) -> None:
if self.shaded:
path = create_header()
add_metadata_list(doc, "include-in-header", path.as_posix())


def create_header() -> Path:
text = r"""
\ifdefined\Shaded
\usepackage{framed}
\renewenvironment{Shaded}{\begin{quotation}\begin{snugshade}\linespread{0.9}}%
{\end{snugshade}\end{quotation}}
\definecolor{shadecolor}{RGB}{240,240,250}
\DefineVerbatimEnvironment{Highlighting}{Verbatim}%
{commandchars=\\\{\},fontsize=\small,numbers=left}
"""
text = inspect.cleandoc(text)
text = f"{text}\n{DEFAULT_SHADE_COLOR}\n\\fi"
def create_output(code: CodeBlock) -> list[Element]:
code.classes.pop(code.classes.index("output"))

return [vspace(), *create_code_block(code, OUTPUT_SHADE_COLOR)]


def create_title(code: CodeBlock) -> list[Element]:
attrs = {"formatcom": f"\\color{{{TITLE_COLOR}}}\\bfseries"}
title = CodeBlock(code.attributes.pop("title"), attributes=attrs)

return [
*create_code_block(title, TITLE_SHADE_COLOR),
vspace(),
*create_code_block(code, DEFAULT_SHADE_COLOR),
]


def create_default(code: CodeBlock) -> list[Element]:
return create_code_block(code, DEFAULT_SHADE_COLOR)


def create_code_block(code: CodeBlock, rgb: Iterable) -> list[Element]:
env = define_verbatim_environment(code.attributes)
color = define_shade_color(rgb)

if not code.classes:
code.classes = ["text"]

return [RawBlock(f"{env}{color}", format="latex"), code]


def vspace() -> RawBlock:
return RawBlock("\\vspace{-0.5\\baselineskip}", format="latex")


TITLE_SHADE_COLOR = (0.9, 0.9, 1)
DEFAULT_SHADE_COLOR = (0.94, 0.94, 0.94)
OUTPUT_SHADE_COLOR = (1, 1, 0.9)
TITLE_COLOR = "NavyBlue"


def define_verbatim_environment(attrs: dict[str, str], fontsize: str = "small") -> str:
text = r"\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\},"
text = f"{text}fontsize=\\{fontsize}"
args = ",".join(f"{k}={v}" for k, v in attrs.items())
return f"{text},{args}}}" if args else text + "}"


def define_shade_color(rgb: Iterable) -> str:
rgb_str = ",".join(str(x) for x in rgb)
return f"\\definecolor{{shadecolor}}{{rgb}}{{{rgb_str}}}"


def create_header(linespread: float = 0.9) -> Path:
text = (
"\\ifdefined\\Shaded\\usepackage{framed}"
"\\renewenvironment{Shaded}{\\begin{quotation}\\begin{snugshade}\\linespread{"
f"{linespread}"
"}}{\\end{snugshade}\\end{quotation}}\\fi"
)
return create_temp_file(text, suffix=".tex")
3 changes: 2 additions & 1 deletion tests/filters/test_verbatim.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ def test_create_header():

path = create_header()
assert path.exists()
path.read_text("utf-8").startswith("\\ifdefined\\Shaded")
text = path.read_text("utf-8")
assert text.startswith("\\ifdefined\\Shaded")


def test_verbatim():
Expand Down