Source code for __init__

#!/bin/python3
# coding: utf-8
"""
A Sphinx extension that enables watermarks for HTML output.

https://github.com/kallimachos/sphinxmark

Copyright 2021 Brian Moss

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

from pathlib import Path
from shutil import copy

from bottle import TEMPLATE_PATH, template
from PIL import Image, ImageDraw, ImageFont
from sphinx.application import Sphinx
from sphinx.environment import BuildEnvironment
from sphinx.util import logging

LOG = logging.getLogger(__name__)


[docs]def buildcss(app: Sphinx, buildpath: str, imagefile: str) -> str: """Create CSS file.""" # set default values div = "body" repeat = "repeat-y" position = "center" attachment = "scroll" if app.config.sphinxmark_div != "default": div = app.config.sphinxmark_div if app.config.sphinxmark_repeat is False: repeat = "no-repeat" if app.config.sphinxmark_fixed is True: attachment = "fixed" border = app.config.sphinxmark_border if border == "left" or border == "right": css = template("border", div=div, image=imagefile, side=border) else: css = template( "watermark", div=div, image=imagefile, repeat=repeat, position=position, attachment=attachment, ) LOG.debug(f"[sphinxmark] Template: {css}") cssname = "sphinxmark.css" cssfile = Path(buildpath, cssname) with open(cssfile, "w") as f: f.write(css) return cssname
[docs]def createimage(app: Sphinx, srcdir: Path, buildpath: Path) -> str: """Create PNG image from string.""" text = app.config.sphinxmark_text # draw transparent background width = app.config.sphinxmark_text_width height = app.config.sphinxmark_text_spacing img = Image.new("RGBA", (width, height), (255, 255, 255, 0)) d = ImageDraw.Draw(img) # set font fontfile = str(Path(srcdir, "arial.ttf")) font = ImageFont.truetype(fontfile, app.config.sphinxmark_text_size) # set x y location for text xsize, ysize = d.textsize(text, font) LOG.debug("[sphinxmark] x = " + str(xsize) + "\ny = " + str(ysize)) x = (width / 2) - (xsize / 2) y = (height / 2) - (ysize / 2) # add text to image color = app.config.sphinxmark_text_color d.text((x, y), text, font=font, fill=color) # set opacity img2 = img.copy() img2.putalpha(app.config.sphinxmark_text_opacity) img.paste(img2, img) # rotate image img = img.rotate(app.config.sphinxmark_text_rotation) # save image imagefile = f"textmark_{text}.png" imagepath = Path(buildpath, imagefile) img.save(imagepath, "PNG") LOG.debug(f"[sphinxmark] Image saved to: {imagepath}") return imagefile
[docs]def getimage(app: Sphinx) -> tuple: """Get image file.""" # append source directory to TEMPLATE_PATH so template is found srcdir = Path(__file__).parent.resolve() TEMPLATE_PATH.append(srcdir) staticbase = "_static" buildpath = Path(app.outdir, staticbase) try: buildpath.mkdir() except OSError: if not buildpath.is_dir(): raise if app.config.sphinxmark_image == "default": imagefile = "watermark-draft.png" imagepath = Path(srcdir, imagefile) copy(imagepath, buildpath) LOG.debug(f"[sphinxmark] Using default image: {imagefile}") elif app.config.sphinxmark_image == "text": imagefile = createimage(app, srcdir, buildpath) LOG.debug(f"[sphinxmark] Image: {imagefile}") else: imagefile = app.config.sphinxmark_image if app.config.html_static_path: staticpath = app.config.html_static_path[0] else: staticpath = "_static" LOG.debug(f"[sphinxmark] static path: {staticpath}") confdir = str(app.confdir) imagepath = Path(confdir, staticpath, imagefile) LOG.debug(f"[sphinxmark] Imagepath: {imagepath}") try: copy(imagepath, buildpath) except FileNotFoundError: LOG.info(" fail") raise return (buildpath, imagefile)
[docs]def watermark(app: Sphinx, env: BuildEnvironment) -> None: """Add watermark.""" if app.config.sphinxmark_enable is True: LOG.info("adding watermark...", nonl=True) try: buildpath, imagefile = getimage(app) cssname = buildcss(app, buildpath, imagefile) app.add_css_file(cssname) LOG.info(" done") except Exception as e: LOG.warning(f"Failed to add watermark: {e}") return
[docs]def setup(app: Sphinx) -> dict: """Configure setup for Sphinx extension. :param app: Sphinx application context. """ app.add_config_value("sphinxmark_enable", False, "html") app.add_config_value("sphinxmark_div", "default", "html") app.add_config_value("sphinxmark_border", None, "html") app.add_config_value("sphinxmark_repeat", True, "html") app.add_config_value("sphinxmark_fixed", False, "html") app.add_config_value("sphinxmark_image", "default", "html") app.add_config_value("sphinxmark_text", "default", "html") app.add_config_value("sphinxmark_text_color", (255, 0, 0), "html") app.add_config_value("sphinxmark_text_size", 100, "html") app.add_config_value("sphinxmark_text_width", 1000, "html") app.add_config_value("sphinxmark_text_opacity", 20, "html") app.add_config_value("sphinxmark_text_spacing", 400, "html") app.add_config_value("sphinxmark_text_rotation", 0, "html") app.connect("env-updated", watermark) return { "version": "0.2.1", "parallel_read_safe": True, "parallel_write_safe": True, }