Skip to content
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
31 changes: 31 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: HTML2Print Docker CI

on:
pull_request:
branches: [ "**" ]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Upgrade pip
run: |
python -m pip install --upgrade pip

- name: Install Python packages
run: |
pip install -r requirements.development.txt

- name: Build Docker image with PR branch
run: |
invoke build-docker \
--image pr-${{ github.event.pull_request.number }} \
--source=${{ github.event.pull_request.head.sha }}

- name: Run container and test StrictDoc installation
run: |
invoke test-docker \
--image pr-${{ github.event.pull_request.number }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# HTML2PDF JS file.
html2print/html2pdf_js/
# html2print/html2pdf_js/

.idea/
**/.wdm/
build/
dist/
tests/integration/.lit_test_times.txt
tests/integration/**/Output/
output/

55 changes: 55 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
FROM ubuntu:24.04

# Install dependencies
RUN apt-get update && apt-get install -y \
curl \
git \
python3 \
python3-pip \
python3-venv \
sudo \
vim \
wget \
&& rm -rf /var/lib/apt/lists/*

# Download and install Google Chrome
RUN wget -q -O google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
&& apt-get update \
&& apt-get install -y ./google-chrome.deb \
&& rm google-chrome.deb

# Create a new non-root user and group.
# NOTE: It is important that a non-root user is used because otherwise the
# Chrome Driver fails with: "User data directory is already in use"
# https://github.com/SeleniumHQ/selenium/issues/15327#issuecomment-2688613182
RUN groupadd -r html2print && useradd -r -m -g html2print html2print

# Grant the new user sudo privileges.
RUN echo "html2print ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/html2print

# Create a virtual environment in the user's home directory.
RUN python3 -m venv /opt/venv

# Ensure the virtual environment is used by modifying the PATH.
ENV PATH="/opt/venv/bin:$PATH"

# Install StrictDoc. Set default StrictDoc installation from PyPI but allow
# overriding it with an environment variable.
ARG HTML2PRINT_SOURCE="pypi"
ENV HTML2PRINT_SOURCE=${HTML2PRINT_SOURCE}

RUN if [ "$HTML2PRINT_SOURCE" = "pypi" ]; then \
pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir html2print; \
else \
pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir git+https://github.com/mettta/html2pdf_python.git@${HTML2PRINT_SOURCE}; \
fi; \
chmod -R 777 /opt/venv;

USER html2print

# Set the working directory to the user's home directory.
WORKDIR /data

ENTRYPOINT ["/bin/bash"]
2 changes: 2 additions & 0 deletions html2print/html2pdf_js/html2pdf.min.js

Large diffs are not rendered by default.

33 changes: 28 additions & 5 deletions html2print/html2print.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@
from selenium.webdriver.chrome.service import Service
from webdriver_manager.core.os_manager import ChromeType, OperationSystemManager

__version__ = "0.0.14"
__version__ = "0.0.15a2"

PATH_TO_HTML2PDF_JS = os.path.join(
os.path.dirname(os.path.join(__file__)), "html2pdf_js", "html2pdf.min.js"
)

DEFAULT_CACHE_DIR = os.path.join(Path.home(), ".html2print", "chromedriver")

PATH_TO_CHROME_DRIVER_DEBUG_LOG = "/tmp/chromedriver.log"

# HTML2PDF.js prints unicode symbols to console. The following makes it work on
# Windows which otherwise complains:
# UnicodeEncodeError: 'charmap' codec can't encode characters in position 129-130: character maps to <undefined>
Expand Down Expand Up @@ -303,7 +305,10 @@ class Done(Exception):


def create_webdriver(
chromedriver: Optional[str], path_to_cache_dir: str, page_load_timeout: int
chromedriver: Optional[str],
path_to_cache_dir: str,
page_load_timeout: int,
debug: bool = False,
) -> webdriver.Chrome:
print("html2print: creating ChromeDriver service.", flush=True) # noqa: T201
if chromedriver is None:
Expand All @@ -314,13 +319,20 @@ def create_webdriver(
path_to_chrome = chromedriver
print(f"html2print: ChromeDriver available at path: {path_to_chrome}") # noqa: T201

service = Service(path_to_chrome)
if debug:
service = Service(
path_to_chrome, log_output=PATH_TO_CHROME_DRIVER_DEBUG_LOG
)
else:
service = Service(path_to_chrome)

webdriver_options = Options()
webdriver_options.add_argument("start-maximized")
webdriver_options.add_argument("disable-infobars")
# Doesn't seem to be needed.
# webdriver_options.add_argument('--disable-gpu') # noqa: ERA001
webdriver_options.add_argument("--disable-extensions")
webdriver_options.add_argument("--headless")
webdriver_options.add_argument("--headless=chrome")
# FIXME: This is not nice but otherwise it does not work in Ubuntu 24-based Docker image.
# https://github.com/SeleniumHQ/selenium/issues/15327#issuecomment-2689287561
webdriver_options.add_argument("--no-sandbox")
Expand Down Expand Up @@ -415,6 +427,14 @@ def main():
"HTML file, load it, and let HTML2PDF.js finish its job."
),
)
command_parser_print.add_argument(
"--debug",
action="store_true",
help=(
f"Enables ChromeDriver logging to a file: "
f"{PATH_TO_CHROME_DRIVER_DEBUG_LOG}."
),
)
command_parser_print.add_argument(
"paths", nargs="+", help="Paths to input HTML file."
)
Expand Down Expand Up @@ -442,7 +462,10 @@ def main():
args.cache_dir if args.cache_dir is not None else DEFAULT_CACHE_DIR
)
driver = create_webdriver(
args.chromedriver, path_to_cache_dir, page_load_timeout
args.chromedriver,
path_to_cache_dir,
page_load_timeout,
debug=args.debug,
)

@atexit.register
Expand Down
64 changes: 63 additions & 1 deletion tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def run_invoke(
cmd,
environment: Optional[dict] = None,
warn: bool = False,
pty: bool = False,
) -> invoke.runners.Result:
def one_line_command(string):
return re.sub("\\s+", " ", string).strip()
Expand All @@ -39,7 +40,7 @@ def one_line_command(string):
env=environment,
hide=False,
warn=warn,
pty=False,
pty=pty,
echo=True,
)

Expand Down Expand Up @@ -267,3 +268,64 @@ def release(context, test_pypi=False, username=None, password=None):
{user_password}
""",
)


@task(aliases=["bd"])
def build_docker(
context,
image: str = "html2print:latest",
no_cache: bool = False,
source="pypi",
):
no_cache_argument = "--no-cache" if no_cache else ""
run_invoke(
context,
f"""
docker build .
--build-arg HTML2PRINT_SOURCE={source}
-t {image}
{no_cache_argument}
""",
)


@task(aliases=["rd"])
def run_docker(
context, image: str = "html2print:latest", command: Optional[str] = None
):
command_argument = (
f'/bin/bash -c "{command}"' if command is not None else ""
)
entry_point_argument = '--entrypoint=""' if command_argument else ""

run_invoke(
context,
f"""
docker run
--name html2print
--rm
-it
-v "$(pwd):/data"
{entry_point_argument}
{image}
{command_argument}
""",
pty=True,
)


@task(aliases=["td"])
def test_docker(context, image: str = "html2print:latest"):
run_invoke(
context,
"""
mkdir -p output/ && chmod 777 output/
""",
)
run_docker(
context,
image=image,
command=(
"cd tests/integration/01_hello_world && html2print print --debug index.html /data/output/index.pdf && cat /tmp/chromedriver.log"
),
)
4 changes: 2 additions & 2 deletions tests/integration/01_hello_world/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<head>
<meta charset="utf-8">
<title>Test page</title>
<script src="../../../submodules/html2pdf/dist/bundle.js"></script>
<link rel="stylesheet" href="../../../submodules/html2pdf/test/shared/css/main.css">
<script src="../../../html2print/html2pdf_js/html2pdf.min.js"></script>
<link rel="stylesheet" href="../../../tests/integration/main.css">
</head>

<body>
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/02_two_pages/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<head>
<meta charset="utf-8">
<title>Test page</title>
<script src="../../../submodules/html2pdf/dist/bundle.js"></script>
<link rel="stylesheet" href="../../../submodules/html2pdf/test/shared/css/main.css">
<script src="../../../html2print/html2pdf_js/html2pdf.min.js"></script>
<link rel="stylesheet" href="../../../tests/integration/main.css">
</head>

<body>
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/03_cache_dir_argument/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<head>
<meta charset="utf-8">
<title>Test page</title>
<script src="../../../submodules/html2pdf/dist/bundle.js"></script>
<link rel="stylesheet" href="../../../submodules/html2pdf/test/shared/css/main.css">
<script src="../../../html2print/html2pdf_js/html2pdf.min.js"></script>
<link rel="stylesheet" href="../../../tests/integration/main.css">
</head>

<body>
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/04_two_documents/index1.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<head>
<meta charset="utf-8">
<title>Test page</title>
<script src="../../../submodules/html2pdf/dist/bundle.js"></script>
<link rel="stylesheet" href="../../../submodules/html2pdf/test/shared/css/main.css">
<script src="../../../html2print/html2pdf_js/html2pdf.min.js"></script>
<link rel="stylesheet" href="../../../tests/integration/main.css">
</head>

<body>
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/04_two_documents/index2.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<head>
<meta charset="utf-8">
<title>Test page</title>
<script src="../../../submodules/html2pdf/dist/bundle.js"></script>
<link rel="stylesheet" href="../../../submodules/html2pdf/test/shared/css/main.css">
<script src="../../../html2print/html2pdf_js/html2pdf.min.js"></script>
<link rel="stylesheet" href="../../../tests/integration/main.css">
</head>

<body>
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/05_page_load_timeout/index1.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<head>
<meta charset="utf-8">
<title>Test page</title>
<script src="../../../submodules/html2pdf/dist/bundle.js"></script>
<link rel="stylesheet" href="../../../submodules/html2pdf/test/shared/css/main.css">
<script src="../../../html2print/html2pdf_js/html2pdf.min.js"></script>
<link rel="stylesheet" href="../../../tests/integration/main.css">
</head>

<body>
Expand Down
53 changes: 53 additions & 0 deletions tests/integration/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
body {
font-size: 16px;
line-height: 1.25;
}

[filler] {
background:repeating-linear-gradient(
-45deg,
rgba(100, 100, 100, .1),
rgba(100, 100, 100, .1) 10px,
rgba(100, 100, 100, .15) 10px,
rgba(100, 100, 100, .15) 20px
);
}

[filler='blue'] {
background:repeating-linear-gradient(
-45deg,
rgba(0, 175, 255, .1),
rgba(0, 175, 255, .1) 10px,
rgba(0, 175, 255, .15) 10px,
rgba(0, 175, 255, .15) 20px
);
}

[filler='red'] {
background:repeating-linear-gradient(
-45deg,
rgba(255, 25, 0, .1),
rgba(255, 25, 0, .1) 10px,
rgba(255, 25, 0, .15) 10px,
rgba(255, 25, 0, .15) 20px
);
}

[filler='green'] {
background:repeating-linear-gradient(
-45deg,
rgba(0, 175, 0, .1),
rgba(0, 175, 0, .1) 10px,
rgba(0, 175, 0, .15) 10px,
rgba(0, 175, 0, .15) 20px
);
}

[floater] {
outline: rgba(255, 0, 200, 0.2) 1px solid;
}

[floater='solid'] {
outline: rgba(255, 0, 55, 0.55) 1px solid;
overflow: auto;
}