Merge branch 'master' into master

This commit is contained in:
abeudin 2017-07-14 14:52:36 +02:00 committed by GitHub
commit b99c6ffb6c
18 changed files with 140 additions and 81 deletions

View File

@ -1,7 +1,12 @@
Changelog Changelog
========= =========
0.5 (2017-06-02) 0.6 (2017-07-14)
* Compatibility python 2 and 3
* Possibility to add custom css and js http://prosopopee.readthedocs.io/en/latest/theming.html
0.5 (2017-06-04)
* Add audio HTML5 player https://prosopopee.readthedocs.org/en/latest/sections.html#audio by beudbeud * Add audio HTML5 player https://prosopopee.readthedocs.org/en/latest/sections.html#audio by beudbeud
* Update Material theme by beudbeud * Update Material theme by beudbeud
@ -10,6 +15,7 @@ Changelog
* Add deploy and preview option https://prosopopee.readthedocs.io/en/latest/build.html#preview by beudbeud * Add deploy and preview option https://prosopopee.readthedocs.io/en/latest/build.html#preview by beudbeud
* Load only css and jss if the section is used by beudbeud * Load only css and jss if the section is used by beudbeud
* Possibility to add floating image in paragraph by beudbeud https://prosopopee.readthedocs.org/en/latest/sections.html#paragraph * Possibility to add floating image in paragraph by beudbeud https://prosopopee.readthedocs.org/en/latest/sections.html#paragraph
* fix some bugs
0.4 (2016-12-11) 0.4 (2016-12-11)

View File

@ -46,5 +46,6 @@ Documentation
sections sections
example example
build build
theming
authors authors
changelog changelog

View File

@ -151,6 +151,7 @@ This section is for add audio file with HTML5 player.::
- type: audio - type: audio
title: Title of song title: Title of song
image: song.ogg image: song.ogg
color: "#000" (optional)
Author Author

24
docs/theming.rst Normal file
View File

@ -0,0 +1,24 @@
Theming
=======
Custom css and js
-----------------
You can add easily css code and js code. You need create custom.css or custom.js
in root directory.
Override template
-----------------
If you wanna override template, you need create a "templates" directory and create your own template.
* home page : index.html
* gallery page: gallery-index.html
And for override sections you need create file in "templates/sections".
Create theme
------------
TODO

View File

@ -33,7 +33,7 @@ class Cache(object):
self.cache = {"version": CACHE_VERSION} self.cache = {"version": CACHE_VERSION}
if "version" not in self.cache or self.cache["version"] != CACHE_VERSION: if "version" not in self.cache or self.cache["version"] != CACHE_VERSION:
print "info: cache format as changed, prune cache" print("info: cache format as changed, prune cache")
self.cache = {"version": CACHE_VERSION} self.cache = {"version": CACHE_VERSION}
def needs_to_be_generated(self, source, target, options): def needs_to_be_generated(self, source, target, options):
@ -53,8 +53,7 @@ class Cache(object):
def cache_picture(self, source, target, options): def cache_picture(self, source, target, options):
self.cache[target] = {"size": os.path.getsize(source), "options": remove_superficial_options(options)} self.cache[target] = {"size": os.path.getsize(source), "options": remove_superficial_options(options)}
def __del__(self): def cache_dump(self):
self.json.dump(self.cache, open(self.cache_file_path, "w")) self.json.dump(self.cache, open(self.cache_file_path, "w"))
CACHE = Cache(json=json) CACHE = Cache(json=json)

View File

@ -13,15 +13,14 @@ Options:
""" """
import os import os
import yaml
import shutil import shutil
import socketserver
import http.server
import ruamel.yaml as yaml
#import yaml
from docopt import docopt from docopt import docopt
import SocketServer
import SimpleHTTPServer
import subprocess
from path import Path from path import Path
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
@ -94,18 +93,18 @@ class Video(object):
return return
ffmpeg_switches = { ffmpeg_switches = {
"source": source, "source": source,
"target": target, "target": target,
"loglevel": "-loglevel %s" % options["loglevel"], "loglevel": "-loglevel %s" % options["loglevel"],
"resolution": "-s %s" % options["resolution"], "resolution": "-s %s" % options["resolution"],
"resize": "-vf scale=-1:%s" % options.get("resize"), "resize": "-vf scale=-1:%s" % options.get("resize"),
"vbitrate": "-b:v %s" % options["vbitrate"], "vbitrate": "-b:v %s" % options["vbitrate"],
"abitrate": "-b:v %s" % options["abitrate"], "abitrate": "-b:v %s" % options["abitrate"],
"format": "-f %s" % options["format"], "format": "-f %s" % options["format"],
"binary": "%s" % options["binary"], "binary": "%s" % options["binary"],
"video": "-c:v %s" % options["video"], "video": "-c:v %s" % options["video"],
"audio": "-c:a %s" % options["audio"], "audio": "-c:a %s" % options["audio"],
"other": "%s" % options["other"] "other": "%s" % options["other"]
} }
warning("Generation", source) warning("Generation", source)
@ -168,11 +167,11 @@ class Audio(object):
return return
ffmpeg_switches = { ffmpeg_switches = {
"source": source, "source": source,
"target": target, "target": target,
"binary": "%s" % options["binary"], "binary": "%s" % options["binary"],
"loglevel": "-loglevel %s" % options["loglevel"], "loglevel": "-loglevel %s" % options["loglevel"],
"audio": "-c:a %s" % options["audio"] "audio": "-c:a %s" % options["audio"]
} }
warning("Generation", source) warning("Generation", source)
@ -215,13 +214,13 @@ class Image(object):
return return
gm_switches = { gm_switches = {
"source": source, "source": source,
"target": target, "target": target,
"auto-orient": "-auto-orient" if options["auto-orient"] else "", "auto-orient": "-auto-orient" if options["auto-orient"] else "",
"strip": "-strip" if options["strip"] else "", "strip": "-strip" if options["strip"] else "",
"quality": "-quality %s" % options["quality"] if "quality" in options else "-define jpeg:preserve-settings", "quality": "-quality %s" % options["quality"] if "quality" in options else "-define jpeg:preserve-settings",
"resize": "-resize %s" % options["resize"] if options.get("resize", None) is not None else "", "resize": "-resize %s" % options["resize"] if options.get("resize", None) is not None else "",
"progressive": "-interlace Line" if options.get("progressive", None) is True else "" "progressive": "-interlace Line" if options.get("progressive", None) is True else ""
} }
command = "gm convert '{source}' {auto-orient} {strip} {progressive} {quality} {resize} '{target}'".format(**gm_switches) command = "gm convert '{source}' {auto-orient} {strip} {progressive} {quality} {resize} '{target}'".format(**gm_switches)
@ -244,7 +243,7 @@ class Image(object):
if not options["auto-orient"] and not options["strip"]: if not options["auto-orient"] and not options["strip"]:
shutil.copyfile(source, target) shutil.copyfile(source, target)
print("%s%s%s" % (source, "->", target)) print(("%s%s%s" % (source, "->", target)))
else: else:
# Do not consider quality settings here, since we aim to copy the input image # Do not consider quality settings here, since we aim to copy the input image
# better to preserve input encoding setting # better to preserve input encoding setting
@ -273,15 +272,22 @@ def get_settings():
error(Path("settings.yaml").exists(), "I can't find a " error(Path("settings.yaml").exists(), "I can't find a "
"settings.yaml in the current working directory") "settings.yaml in the current working directory")
settings = yaml.safe_load(open("settings.yaml", "r")) try:
settings = yaml.safe_load(open("settings.yaml", "r"))
except yaml.YAMLError as exc:
if hasattr(exc, 'problem_mark'):
mark = exc.problem_mark
error(False, "There are something wrong in settings.yaml line %s" % (mark.line))
else:
error(False, "There are omething wrong in settings.yaml")
error(isinstance(settings, dict), "Your settings.yaml should be a dict") error(isinstance(settings, dict), "Your settings.yaml should be a dict")
for key, value in DEFAULTS.items(): for key, value in list(DEFAULTS.items()):
if key not in settings: if key not in settings:
settings[key] = value settings[key] = value
for key, value in SETTINGS.items(): for key, value in list(SETTINGS.items()):
if key not in settings: if key not in settings:
settings[key] = value settings[key] = value
@ -357,7 +363,14 @@ def process_directory(gallery_name, settings, parent_templates, parent_gallery_p
else: else:
gallery_path = gallery_name gallery_path = gallery_name
gallery_settings = yaml.safe_load(open(Path(".").joinpath(gallery_path, "settings.yaml").abspath(), "r")) try:
gallery_settings = yaml.safe_load(open(Path(".").joinpath(gallery_path, "settings.yaml").abspath(), "r"))
except yaml.YAMLError as exc:
if hasattr(exc, 'problem_mark'):
mark = exc.problem_mark
error(False, "There are something wrong in %s/settings.yaml line %s" % (gallery_path, mark.line))
else:
error(False, "There are something wrong in %s/settings.yaml" % (gallery_path))
error(isinstance(gallery_settings, dict), "Your %s should be a dict" % gallery_name.joinpath("settings.yaml")) error(isinstance(gallery_settings, dict), "Your %s should be a dict" % gallery_name.joinpath("settings.yaml"))
error(gallery_settings.get("title"), "You should specify a title in %s" % gallery_name.joinpath("settings.yaml")) error(gallery_settings.get("title"), "You should specify a title in %s" % gallery_name.joinpath("settings.yaml"))
@ -458,7 +471,7 @@ def build_gallery(settings, gallery_settings, gallery_path, template):
name=gallery_path.split('/', 1)[-1] name=gallery_path.split('/', 1)[-1]
).encode("Utf-8") ).encode("Utf-8")
open(Path("build").joinpath(gallery_path, "index.html"), "w").write(html) open(Path("build").joinpath(gallery_path, "index.html"), "wb").write(html)
# XXX shouldn't this be a call to build_gallery? # XXX shouldn't this be a call to build_gallery?
# Build light mode gallery # Build light mode gallery
@ -493,11 +506,12 @@ def build_gallery(settings, gallery_settings, gallery_path, template):
name=gallery_path.split('/', 1)[-1] name=gallery_path.split('/', 1)[-1]
).encode("Utf-8") ).encode("Utf-8")
open(Path("build").joinpath(gallery_light_path, "index.html"), "w").write(html) open(Path("build").joinpath(gallery_light_path, "index.html"), "wb").write(html)
def build_index(settings, galleries_cover, templates, gallery_path='', sub_index=False, gallery_settings={}): def build_index(settings, galleries_cover, templates, gallery_path='', sub_index=False, gallery_settings={}):
index_template = templates.get_template("index.html") index_template = templates.get_template("index.html")
reverse = gallery_settings.get('reverse', settings.get('reverse', True)) reverse = gallery_settings.get('reverse', settings.get('reverse', True))
if reverse: if reverse:
galleries_cover = reversed(sorted(filter(lambda x: x != {}, galleries_cover), key=lambda x: x["date"])) galleries_cover = reversed(sorted(filter(lambda x: x != {}, galleries_cover), key=lambda x: x["date"]))
@ -519,7 +533,7 @@ def build_index(settings, galleries_cover, templates, gallery_path='', sub_index
Video=Video Video=Video
).encode("Utf-8") ).encode("Utf-8")
open(Path("build").joinpath(gallery_path, "index.html"), "w").write(html) open(Path("build").joinpath(gallery_path, "index.html"), "wb").write(html)
def main(): def main():
@ -538,11 +552,10 @@ def main():
error(Path("build").exists(), "Please build the website before launch preview") error(Path("build").exists(), "Please build the website before launch preview")
os.chdir('build') os.chdir('build')
handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", 9000), handler)
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler print('Start server on http://localhost:9000')
httpd = SocketServer.TCPServer(("", 9000), Handler)
print "Start server on http://localhost:9000"
# gracefully handle interrupt here # gracefully handle interrupt here
httpd.serve_forever() httpd.serve_forever()
@ -570,6 +583,14 @@ def main():
templates = get_gallery_templates(theme) templates = get_gallery_templates(theme)
templates.add_extension('jinja2.ext.with_') templates.add_extension('jinja2.ext.with_')
if Path("custom.js").exists():
shutil.copy(Path("custom.js"), Path(".").joinpath("build", "", "static", "js"))
settings["custom_js"] = True
if Path("custom.css").exists():
shutil.copy(Path("custom.css"), Path(".").joinpath("build", "", "static", "css"))
settings["custom_css"] = True
for gallery in galleries_dirs: for gallery in galleries_dirs:
front_page_galleries_cover.append(process_directory(gallery, settings, templates)) front_page_galleries_cover.append(process_directory(gallery, settings, templates))
@ -578,12 +599,13 @@ def main():
xml = feed_template.render( xml = feed_template.render(
settings=settings, settings=settings,
galleries=reversed(sorted(filter(lambda x: x != {}, front_page_galleries_cover), key=lambda x: x["date"])) galleries=reversed(sorted([x for x in front_page_galleries_cover if x != {}], key=lambda x: x["date"]))
).encode("Utf-8") ).encode("Utf-8")
open(Path("build").joinpath("feed.xml"), "w").write(xml) open(Path("build").joinpath("feed.xml"), "wb").write(xml)
build_index(settings, front_page_galleries_cover, templates) build_index(settings, front_page_galleries_cover, templates)
CACHE.cache_dump()
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -5,6 +5,9 @@
{% set licence_url = settings.licence.url %} {% set licence_url = settings.licence.url %}
{% set licence_name = settings.licence.name %} {% set licence_name = settings.licence.name %}
{% endif %} {% endif %}
{% if settings.custom_js %}
<script type="text/javascript" src="../static/js/custom.js" charset="utf-8"></script>
{% endif %}
<footer> <footer>
<p>Generated using <a href="https://github.com/psycojoker/prosopopee">Prosopopée</a> · content under <a href="{{ licence_url }}">{{ licence_name }}</a> · atom logo by <a href="https://thenounproject.com/jjjon/">Jonathan Li</a> under <a href="https://creativecommons.org/licenses/by/3.0/">CC-BY</a></p> <p>Generated using <a href="https://github.com/psycojoker/prosopopee">Prosopopée</a> · content under <a href="{{ licence_url }}">{{ licence_name }}</a> · atom logo by <a href="https://thenounproject.com/jjjon/">Jonathan Li</a> under <a href="https://creativecommons.org/licenses/by/3.0/">CC-BY</a></p>
</footer> </footer>

View File

@ -12,6 +12,9 @@
{% if gallery.audio_enabled %} {% if gallery.audio_enabled %}
<link type="text/css" rel="stylesheet" href="../static/css/mediaelementplayer.css" media="screen,projection"/> <link type="text/css" rel="stylesheet" href="../static/css/mediaelementplayer.css" media="screen,projection"/>
{% endif %} {% endif %}
{% if settings.custom_css %}
<link type="text/css" rel="stylesheet" href="../static/css/custom.css" media="screen,projection"/>
{% endif %}
<!--Let browser know website is optimized for mobile--> <!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
{% if gallery.description %} {% if gallery.description %}
@ -79,18 +82,16 @@ $('audio').mediaelementplayer({
}); });
{% endif %} {% endif %}
var video = $("video"); function goFullscreen(id) {
video.on('click', function(e){ var element = document.getElementById(id);
var vid = video[0]; if (element.requestFullscreen) {
vid.play(); element.requestFullscreen();
if (vid.requestFullscreen) { } else if (element.mozRequestFullScreen) {
vid.requestFullscreen(); element.mozRequestFullScreen();
} else if (vid.mozRequestFullScreen) { } else if (element.webkitRequestFullScreen) {
vid.mozRequestFullScreen(); element.webkitRequestFullScreen();
} else if (vid.webkitRequestFullscreen) { }
vid.webkitRequestFullscreen(); }
}
});
$(function() { $(function() {
$("img.lazy").lazyload({ $("img.lazy").lazyload({

View File

@ -3,6 +3,9 @@
{% block css %} {% block css %}
<link type="text/css" rel="stylesheet" href="static/css/fonts.css" media="screen,projection"/> <link type="text/css" rel="stylesheet" href="static/css/fonts.css" media="screen,projection"/>
<link type="text/css" rel="stylesheet" href="static/css/style.css" media="screen,projection"/> <link type="text/css" rel="stylesheet" href="static/css/style.css" media="screen,projection"/>
{% if settings.custom_css %}
<link type="text/css" rel="stylesheet" href="static/css/custom.css" media="screen,projection"/>
{% endif %}
{% endblock %} {% endblock %}
{% block logo %} {% block logo %}

View File

@ -6,7 +6,7 @@
{% set format = extension %} {% set format = extension %}
{% endif %} {% endif %}
{{ audio.copy() }} {{ audio.copy() }}
<div class="audio-player"> <div class="audio-player" {% if section.color %} style="background: {{ section.color }};"{% endif %}>
<h2>{% if section.title %}{{ section.title }}{% else %}{{ audio }}{% endif %}</h2> <h2>{% if section.title %}{{ section.title }}{% else %}{{ audio }}{% endif %}</h2>
<audio controls preload=none> <audio controls preload=none>
<source src="{{ audio }}.{{ extension }}" type="audio/{{ format }}"> <source src="{{ audio }}.{{ extension }}" type="audio/{{ format }}">

View File

@ -9,7 +9,7 @@
<section class="bordered-picture baguette" style="position: relative;"> <section class="bordered-picture baguette" style="position: relative;">
<div class="caption"> <div class="caption">
<img class="lazy" data-original="{{ video.generate_thumbnail("2000") }}" src="" alt=""> <img class="lazy" data-original="{{ video.generate_thumbnail("2000") }}" src="" alt="">
<video class="lazy responsive-video" id="video" poster="{{ video.generate_thumbnail("2000") }}" alt="" autoplay="autoplay" loop="loop" preload="none" muted> <video class="lazy responsive-video" id="{{ video }}" onclick="goFullscreen('{{ video }}');" poster="{{ video.generate_thumbnail("2000") }}" alt="" autoplay="autoplay" loop="loop" preload="none" muted>
<source src="{{ video }}.{{ format }}" type="video/{{ format }}"> <source src="{{ video }}.{{ format }}" type="video/{{ format }}">
</video> </video>
{% if caption %} {% if caption %}

View File

@ -12,7 +12,7 @@
{% set format = settings.ffmpeg.extension %} {% set format = settings.ffmpeg.extension %}
{{ video.copy() }} {{ video.copy() }}
<img class="lazy" data-original="{{ video.generate_thumbnail("600") }}" src="" alt=""> <img class="lazy" data-original="{{ video.generate_thumbnail("600") }}" src="" alt="">
<video class="lazy responsive-video" id="video" poster="{{ video.generate_thumbnail("600") }}" alt="" autoplay="autoplay" loop="loop" preload="auto" muted> <video class="lazy responsive-video" id="{{ video }}" onclick="goFullscreen('{{ video }}');" poster="{{ video.generate_thumbnail("600") }}" alt="" autoplay="autoplay" loop="loop" preload="auto" muted>
<source src="{{ video }}.{{ format }}" type="video/{{ format }}"> <source src="{{ video }}.{{ format }}" type="video/{{ format }}">
</video> </video>
{% if caption %} {% if caption %}

View File

@ -62,18 +62,16 @@ $(document).ready(function(){
$('.parallax').parallax(); $('.parallax').parallax();
}); });
var video = $("video.lazy"); function goFullscreen(id) {
video.on('click', function(e){ var element = document.getElementById(id);
var vid = video[0]; if (element.requestFullscreen) {
vid.play(); element.requestFullscreen();
if (vid.requestFullscreen) { } else if (element.mozRequestFullScreen) {
vid.requestFullscreen(); element.mozRequestFullScreen();
} else if (vid.mozRequestFullScreen) { } else if (element.webkitRequestFullScreen) {
vid.mozRequestFullScreen(); element.webkitRequestFullScreen();
} else if (vid.webkitRequestFullscreen) { }
vid.webkitRequestFullscreen(); }
}
});
{% if gallery.audio_enabled %} {% if gallery.audio_enabled %}
$('audio').mediaelementplayer({ $('audio').mediaelementplayer({

View File

@ -6,7 +6,7 @@
{% set format = extension %} {% set format = extension %}
{% endif %} {% endif %}
{{ audio.copy() }} {{ audio.copy() }}
<div class="audio-player"> <div class="audio-player" {% if section.color %} style="background: {{ section.color }};"{% endif %}>
<h2>{% if section.title %}{{ section.title }}{% else %}{{ audio }}{% endif %}</h2> <h2>{% if section.title %}{{ section.title }}{% else %}{{ audio }}{% endif %}</h2>
<audio controls preload=none> <audio controls preload=none>
<source src="{{ audio }}.{{ extension }}" type="audio/{{ format }}"> <source src="{{ audio }}.{{ extension }}" type="audio/{{ format }}">

View File

@ -12,7 +12,7 @@
<div class="bordered-picture baguette caption"> <div class="bordered-picture baguette caption">
{% if video %} {% if video %}
<img class="responsive-img lazy z-depth-2" data-original="{{ video.generate_thumbnail("2000") }}" alt=""> <img class="responsive-img lazy z-depth-2" data-original="{{ video.generate_thumbnail("2000") }}" alt="">
<video class="lazy responsive-video" poster="{{ video.generate_thumbnail("2000") }}" alt="" autoplay="autoplay" loop="loop" preload="auto" muted=""> <video class="lazy responsive-video" id="{{ video }}" onclick="goFullscreen('{{ video }}');" poster="{{ video.generate_thumbnail("2000") }}" alt="" autoplay="autoplay" loop="loop" preload="auto" muted>
<source src="{{ video }}.{{ format }}" type="video/{{ format }}"> <source src="{{ video }}.{{ format }}" type="video/{{ format }}">
</video> </video>
{% else %} {% else %}

View File

@ -12,7 +12,7 @@
{% set format = settings.ffmpeg.extension %} {% set format = settings.ffmpeg.extension %}
{{ video.copy() }} {{ video.copy() }}
<img class="z-depth-2 lazy responsive-img" data-original="{{ video.generate_thumbnail("600") }}" src="" alt=""> <img class="z-depth-2 lazy responsive-img" data-original="{{ video.generate_thumbnail("600") }}" src="" alt="">
<video class="lazy responsive-video" id="video" poster="{{ video.generate_thumbnail("600") }}" alt="" autoplay="autoplay" loop="loop" preload="auto" muted> <video class="lazy responsive-video" id="{{ video }}" onclick="goFullscreen('{{ video }}');" poster="{{ video.generate_thumbnail("600") }}" alt="" autoplay="autoplay" loop="loop" preload="auto" muted>
<source src="{{ video }}.{{ format }}" type="video/{{ format }}"> <source src="{{ video }}.{{ format }}" type="video/{{ format }}">
</video> </video>
{% if caption %} {% if caption %}

View File

@ -1,4 +1,5 @@
jinja2 jinja2
pyyaml
path.py path.py
docopt docopt
ruamel.yaml
future

View File

@ -12,8 +12,8 @@ except ImportError:
setup(name='prosopopee', setup(name='prosopopee',
version='0.4', version='0.6',
description='exposure.co clone in a static web generating tool', description='A static website generator that allows you to tell a story with your pictures',
author='Laurent Peuch', author='Laurent Peuch',
long_description=read_md('README.md') + "\n\n\n" + open('docs/changelog.rst').read(), long_description=read_md('README.md') + "\n\n\n" + open('docs/changelog.rst').read(),
author_email='cortex@worlddomination.be', author_email='cortex@worlddomination.be',