111 lines
3.9 KiB
Python
111 lines
3.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
pdf_img
|
|
=======
|
|
|
|
Searches for any `<img>` tags within your article for which the source is a
|
|
PostScript, EPS, or PDF file. It will produce a PNG preview of the file,
|
|
which will also act as a link to the original file. This can be useful for
|
|
including scientific plots in articles and pages.
|
|
"""
|
|
|
|
import logging
|
|
import re
|
|
import os.path
|
|
|
|
from bs4 import BeautifulSoup, FeatureNotFound
|
|
from wand.image import Image
|
|
from wand.color import Color
|
|
from wand.exceptions import BlobError
|
|
|
|
from pelican import signals
|
|
from pelican.utils import mkdir_p, get_relative_path, path_to_url
|
|
from pelican.generators import ArticlesGenerator, PagesGenerator
|
|
|
|
import sys
|
|
if (sys.version_info[0]>2):
|
|
unicode = str
|
|
|
|
__version__ = '0.0.1'
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
preview_dir = '__pdf_previews__'
|
|
FORMAT_RE = re.compile(r'(?:\.pdf|\.ps|\.eps)\s*$',re.IGNORECASE)
|
|
pdf_imgs = {}
|
|
|
|
def process_content(article):
|
|
"""
|
|
Get a list of PDF, PS, and EPS files for which PNG previews must be generated.
|
|
Also make the substitutions in article content so that the PNG will be used as
|
|
a preview and provide a link to the original.
|
|
"""
|
|
try:
|
|
soup = BeautifulSoup(article._content,'lxml')
|
|
except FeatureNotFound:
|
|
soup = BeautifulSoup(article._content,'html.parser')
|
|
|
|
for img in soup.find_all('img',src=FORMAT_RE):
|
|
src = re.sub(article.settings['INTRASITE_LINK_REGEX'],'',img['src'].strip())
|
|
if src.startswith(('http://','https://','ftp://')): continue
|
|
if src.startswith('/'):
|
|
src = src[1:]
|
|
else:
|
|
# relative to the source path of this content
|
|
src = article.get_relative_source_path(os.path.join(article.relative_dir, src))
|
|
if src not in article._context['static_content']:
|
|
unquoted_path = src.replace('%20', ' ')
|
|
if unquoted_path in article._context['static_content']:
|
|
src = unquoted_path
|
|
linked_content = article._context['static_content'].get(src)
|
|
if not linked_content:
|
|
continue
|
|
link = img.wrap(soup.new_tag("a"))
|
|
link['href'] = img['src']
|
|
png_save_as = os.path.join(preview_dir, linked_content.save_as + '.png')
|
|
pdf_imgs[linked_content.source_path] = png_save_as
|
|
siteurl = article.get_siteurl()
|
|
if article.settings['RELATIVE_URLS']:
|
|
siteurl = path_to_url(get_relative_path(article.save_as))
|
|
png_url = '/'.join((siteurl, preview_dir, linked_content.url + '.png'))
|
|
png_url = png_url.replace('\\', '/')
|
|
img['src'] = png_url
|
|
|
|
article._content = unicode(soup)
|
|
|
|
|
|
def get_pdf_imgs(generators):
|
|
# Process the articles and pages
|
|
for generator in generators:
|
|
if isinstance(generator, ArticlesGenerator):
|
|
for article in generator.articles:
|
|
process_content(article)
|
|
elif isinstance(generator, PagesGenerator):
|
|
for page in generator.pages:
|
|
process_content(page)
|
|
|
|
|
|
def convert_pdfs(pelican):
|
|
"""
|
|
Create the PNGs from the original PDF, PS, and EPS files, placing them
|
|
in the approriate location in the output directory.
|
|
"""
|
|
with Color('white') as white:
|
|
for path in pdf_imgs:
|
|
outpath = os.path.join(pelican.output_path, pdf_imgs[path])
|
|
mkdir_p(os.path.dirname(outpath))
|
|
try:
|
|
with Image(filename=os.path.join(pelican.path, path)+'[0]',
|
|
resolution=100, background=white) as img:
|
|
img.format = 'png'
|
|
img.save(filename=outpath)
|
|
logger.info('Creating PNG preview of %s as %s', path,
|
|
pdf_imgs[path])
|
|
except BlobError:
|
|
logger.warn('Could create PNG preview of `{}`'.format(src))
|
|
|
|
|
|
def register():
|
|
signals.all_generators_finalized.connect(get_pdf_imgs)
|
|
signals.finalized.connect(convert_pdfs)
|