Initial commit of LunaGen.

This commit is contained in:
Terry Hancock 2021-11-17 22:45:17 -06:00
commit b836bef771
231 changed files with 380150 additions and 0 deletions

7
.gitattributes vendored Normal file
View File

@ -0,0 +1,7 @@
*.png filter=lfs diff=lfs merge=lfs -text
*.otf filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text

339
LunaGen/doc/README.rst Normal file
View File

@ -0,0 +1,339 @@
LunaGen Guide
=============
..contents::
LunaGen is a static website generator for episodic media created
to support the "Lunatics_!" open animated series project. The site
structure it is designed for has:
* An index page with lists of episodes in (possibly) multiple series.
* A page for each episode, with structure determined by the theme and data.
* Additional special list pages for Characters, Settings, Sponsors, and Affiliates.
* Any additional hand-created pages desired.
The data driving the site is authored directly in YAML_ format.
The templates used for site generation (which can be overridden in themes) are
written in Jinja2_.
In addition, both theme and data also contain site "skeletons", which provide additional
files needed: most notably the CSS style sheets in the theme and the necessary images
and static HTML pages you want to use in your site source data directory.
It is very likely you will want to create a custom theme for your site. Please see
the `Theme Author Guide`_ for how to do that. This `Site Author Guide`_ is targeted
at users who simply want to use the package to generate a website using an existing
theme. Should you want to make changes to the code itself, you'll want to read the
`Developer Guide`.
Alternatives
------------
Is LunaGen for you? LunaGen sacrifices generality in order to provide an extremely
simple authoring environment for publishing episodic multimedia content.
I do not recommend it for publishing textual content simply because
it lacks any sophisticated markup language. It is also not a general purpose
content management system, as it is very specific to episodic data, and only
provides a few hard-coded special pages. Making all these assumptions allows
us to keep the data we have to write to update the site very short and simple,
but it also means we can't stretch the software much to do other tasks.
If you want a more text-intensive site, like a static blog listing, you should
probably check out more robust solutions like Pelican_ or Jekyll_, which are
optimized for that kind of use. Perhaps in the future we'll create some kind
of integration to allow LunaGen to be used along with other tools more easily.
We rejected those and designed our own generator because of the amount of
boilerplate we'd need to add to generate simple listings of the type we wanted
using a blog-oriented generator. Using YAML_ allows us to keep our information
field-oriented, with only a little descriptive text needed, but without the
overhead of a database-driven site.
Site Author Guide
-----------------
LunaGen site data consists primarily of a set of YAML_ files and a site skeleton
containing additional content files your site needs -- mostly images, but also
possibly static HTML pages that will simply be copied without modification to your
site.
In general, you should not include CSS files in your site skeleton. These should be
incorporated into a custom **theme** skeleton instead. However, any files you put in
your site skeleton will be copied to your site after the theme files, potentially
replacing them if there is a name collision. So you *can* override CSS this way, though
it's not recommended.
The YAML files for your site follow a very specific structure and some files are
mandatory. At the top level you will find:
``site.yaml``
This defines global variables needed throughout your site:
``sitename``
This is the name used for your entire site. Probably the name of the show.
It must be a simple identifier, and may be used to construct some filenames
or variables.
``sitetitle``
This is the fully-styled name for your site, which may contain punctuation
and spaces.
``imgdir``
This is the location where your images live in your site skeleton.
Whenever a template looks for an image, this will be prepended to the
URL. The exact location of the image below that will be determined by
the template and is theme-specific. So you can structure your images
anyway you like in a custom theme, but will need to learn the requirements
of a theme if you are using someone else's.
``stylesheets``
A list of stylesheets to be referenced by *every* page on your site.
This will be included first, followed by stylesheets requested in
other documents. TODO: this should really be in the theme.
``characters.yaml``
This is the data for a special page listing your series' characters.
TODO: should be optional.
``affiliates.yaml``
List of affiliate advertisements with ``name``, ``img``, and ``url`` fields
to generate the "affiliates banner". TODO: again, should be optional.
``products.yaml``
List of product ad images to advertise your merchandise storefront.
TODO: again, optional.
``software.yaml``
A list of software banners to call out your favorite production software,
advertising those projects so they get some support.
TODO: again, optional.
There is also an ``episodes`` directory, which contains the series and episode
data. Within it you will find:
``series.yaml``
This defines the available series of episodes, and defines several terms to
be used inside the episode files. It consists of a list of series, each of
which must define:
``name``
Name or title of the series, to be shown to the user.
``order``
This is an integer which is used to control the display order. It is
not directly shown, and does not have to be sequential (for example
we numbered our audiodrama series 100 to make sure it always appears
after the animated series). It also need not be in the same order
as the series are listed in your file.
``directory``
This is a brief identifier for the series, used as the directory name
for storing the episode files, and also as a key field.
``modes``
Defines the possible production modes for each episode. Should at least
contain a ``release`` mode for a finally-released episode, but it may
also have earlier workflow modes, such as ``fundraising`` or ``production``,
to show the state of the episode (and therefore what information will
be available for it). For each mode, there is a ``template`` value telling
what template the theme should use to format the episode.
TODO: this is theme-dependent, but I'm not sure how to separate it.
``credits``
This is a collection of definitions for credits blocks to be used in
your episode credits. It defines named blocks, for which the following
should be defined:
``order``
Controls the order of presentation of the fields.
``heading``
What heading to show in the credits listing on the output
page. For example, in our file, this tells us that ``animation_credits``
should be listed as "3D Models and Animation". Optional. If
no heading is provided, no heading will be shown.
``labels``
Controls how the credits will be listed. If this is a list,
it lists identifier and title pairs to be used in the listing.
The order of this list controls the order of the credits (they
may be identified in any order in the episode file).
The value may instead be one of the following strings:
``ordered``
Credits will simply be listed in the order presented in the
episode file, with labels expressed there.
``alpha``
Credits will be listed in alphabetized order.
The exact behavior of the labels value is controlled by the
credits template used, so may be theme-dependent.
``template``
Determines which template will be used to display this credits
block, determining layout behavior. The following are defined:
``centered_credits``
Credits will be listed in simple order, down the middle.
No columns are used, even on a wide screen. Typically used
for main credits.
``basic_credits``
Used for a variety of credit listings. Will try to save some
space by using columns to fill the screen better.
``cast_credits``
Designed to display paired credits, as in cast listings, with
character/actor pairings.
``music_credits``
This displays credits in blocks with named fields for each
title. This changes the interpretation of labels to refer
to the labels used in the individual blocks.
``sponsortypes``
Definitions for your sponsors. Determines what categories you have
and how they will be listed. Note that defining the sponsors here
means you can have a different system for different series.
For each type listed, the following fields may be defined:
``limit``
An integer expressing a limit on how many of this kind of sponsor
is accepted and will be listed (more than this will not be displayed).
``page``
An integer expressing the number of sponsors to be included in a single
block in the listing (this is used to space the sponsors out through
the credits).
``excludes``
The name of another sponsortype that can't be used on the same episode
as this one. Should suppress display of the other, but this isn't
implemented.
``template``
Template name to use for displaying a list of these sponsors.
``desc``
Description of the sponsor type. Will be used to create an informational
page for viewers and potential sponsors.
In the ``episodes`` directory, you will also find subdirectories for each series
using the directory names defined above. Inside each are files for each episode,
with episode-specific data:
*episode*``.yaml``
The following fields are required:
``series``
Backlink to the series identifier.
``episode``
The episode number -- an integer.
TODO: maybe change this to 'number' so we have episode.number instead
of episode.episode?
``mode``
Status of the episode, such as whether it's released, in-development,
in-production, etc. The value should be one of the values defined in
``modes`` in the ``series.yaml`` file. The value may also control
how other information in this file is handled and presented (and which
values are needed). In fact, this may be one way to handle information
that isn't available yet, such as animation credits for an episode that's
just in development.
``title``
The title presented for the episode. Used in several places.
``poster``
Image filename to be used to represent the episode. Ours are square
600x600 pixel images, but the format you use is theme-dependent.
``status``
A brief status message to be included under the title. Good for release
dates or fundraising messages.
``description``
One-paragraph description of the episode. The "blurb".
``credits``
The fields defined in this category must be the ones defined in the
series ``credits`` field. Here you will list the actual credits to
use, in a format determined by the template you listed.
``sponsors``
The actual sponsors, in formats determined by the templates you defined
in the series' ``sponsortypes`` fields. Typically includes ``name``,
``url``, and ``img`` fields for graphic sponsor types, or just a list of
strings for simple named credits (like Patrons or Backers).
``ordered`` and ``cast_credits`` require pairs to be defined of
credit name and credit, like this::
- - Director
- Terry Hancock
- - Writer
- Rosalyn Hunter
For credit blocks with listed labeled credits, the credits should
be given as mappings, using the identifiers you defined, like this::
mech_models:
- Chris Kuhn
Other fields are dependent on the mode, but may include:
``videos``
Videos to display in the video carousel for the episode page, typically
including at least a preview. Ours also include the full episode, a
brief explainer about our business model, and a thank-you message from
the creators. Each video need to define ``id``, ``name``, ``url``,
and ``btn``, needed by the video template.
``product``
Defines a product to pitch on the page. We use this to direct viewers to
the DVD or download bundle releases of our episode in our Gumroad store.
Values are defined by how they are used in the template. Ours provides:
``img``, ``url``, ``title``, and two message fields, ``msg1`` and ``msg2``
which are displayed under certain circumstances.
``funding``
A block defining fields for a crowdfunding campaign, which may include
multiple campaigns on separate platforms. This provides a combined display
of funds raised, and may include pre-sales, matching funds, sponsorships,
and fixed or flexible goal fundraising from crowdfunding platforms.
TODO:
Currently this is a display-only feature and requires manual updating, but
we might provide some kind of plugin system for updating this when the site
is regenerated.
Theme Author Guide
------------------
To be added: should explain the files, templates, and stylesheets a theme needs to
define and how they will be used.
Developer Guide
---------------
To be added: should explain how LunaGen works and how to contribute to it.
.. _Lunatics: http://lunatics.tv
.. _YAML: https://yaml.org/
.. _Jinja2: https://palletsprojects.com/p/jinja/
.. _Pelican: https://blog.getpelican.com/
.. _Jekyll: https://jekyllrb.com/

121
LunaGen/src/lunagen.py Executable file
View File

@ -0,0 +1,121 @@
#!/usr/bin/python3
# encoding: utf-8
'''
lunagen -- "Lunatics!" Project Release Site Generator
LunaGen generates a small static HTML website based on YAML
data documents containing the key release information. This
generates an index.html file containing the episode lists
for all series, individual release pages for each episode,
and additional pages for character list and story background.
This is meant to be a fan-focused site.
It also contains affiliate link, sponsor, advertising, and
other fundraising elements.
@author: Terry Hancock
@copyright: 2019 Anansi Spaceworks.
@license: GNU General Public License, version 2.0 or later. (Python code)
Creative Commons Attribution-ShareAlike, version 3.0 or later. (Website Templates).
@contact: digitante@gmail.com
'''
import os, sys
from optparse import OptionParser
import lunagen
def main(argv=None):
'''Command line options.'''
program_name = os.path.basename(sys.argv[0])
program_version = "v0.1"
program_build_date = "%s" % lunagen.Config.__updated__
program_version_string = '%%prog %s (%s)' % (program_version, program_build_date)
program_longdesc = '''\
LunaGen is a static HTML website generator designed for releasing
a series of episodes (technically: a series of series of episodes).
Data is authored using the YAML structured data language, which allows
for episode metadata and descriptions to be written in a human-friendly
format, which is then formatted into HTML using Jinja2 templates.
Once generated, the site is static and can simply be uploaded to a
standard web server with minimal or no configuration (like a static web host).
It was originally created to generate the release pages for
Anansi Spaceworks' "Lunatics!" series.
For details, please see the 'examples' and 'doc' directories.
'''
program_license = "Copyright 2019 Terry Hancock (Anansi Spaceworks) \
Licensed under the GNU General Public License, version 2.0\n"
if argv is None:
argv = sys.argv[1:]
#try:
# setup option parser
parser = OptionParser(version=program_version_string, epilog=program_longdesc, description=program_license)
parser.add_option("-i", "--in", dest="src", help="set input path [default: %default]", metavar="FILE")
parser.add_option("-o", "--out", dest="tgt", help="set output path [default: %default]", metavar="FILE")
parser.add_option("-v", "--verbose", dest="verbose", action="count", help="set verbosity level [default: %default]")
parser.add_option("-S", "--seed", dest="seed", help="set random number seed [default: None]", type="int")
# process options
(opts, args) = parser.parse_args(argv)
if opts.verbose:
verbose = opts.verbose
else:
verbose = 0
if verbose:
print("Opts = ", opts)
print("Args = ", args)
if opts.src:
src = opts.src
elif args:
src = args.pop(0)
else:
src = './site'
if opts.tgt:
tgt = opts.tgt
elif args:
tgt = args.pop(0)
else:
tgt = './build'
if verbose: print("Source = ", src)
if verbose: print("Target = ", tgt)
lunagen.LunaGen(src, tgt, verbose, opts.seed).gensite()
if __name__ == "__main__":
# if lunagen.Config.DEBUG:
# #sys.argv.append("-h")
# sys.argv.append("-v")
# if lunagen.Config.TESTRUN:
# import doctest
# doctest.testmod()
# if lunagen.Config.PROFILE:
# import cProfile
# import pstats
# profile_filename = 'lunagen_profile.txt'
# cProfile.run('main()', profile_filename)
# statsfile = open("profile_stats.txt", "wb")
# p = pstats.Stats(profile_filename, stream=statsfile)
# stats = p.strip_dirs().sort_stats('cumulative')
# stats.print_stats()
# statsfile.close()
# sys.exit(0)
sys.exit(main())

View File

@ -0,0 +1 @@
from .main import *

View File

@ -0,0 +1,70 @@
'''
Created on Oct 24, 2021
@author: terry
'''
import os
from distutils.dir_util import remove_tree, copy_tree
class LunaGenAddOn(object):
"""
Abstract base class for LunaGen Addons.
"""
name = 'my_addon' # Replace with string name of add-on (should match directory name).
desc = """\
An add-on to demonstrate add-on design.
Replace this text with a brief description of your add-on's purpose.
"""
@staticmethod
def load(site):
"""
Load the site data that the add-on needs to function.
Note that this is site data that the site designer has to provide,
which the addon will then interpret.
Client is the LunaGen instance, which subclasses jinja2.Environment.
Mandatory -- you must implement a loader.
"""
raise NotImplementedError
@classmethod
def copy_skeleton(cls, site):
skeleton = os.path.join(os.path.dirname(cls.file), 'skeleton')
#
print("Copying skeleton for %s from %s." % (cls.name, skeleton))
#
copy_tree(skeleton, site.tgtdir, verbose=site.verbose)
@staticmethod
def render(site):
"""
Render templates to images or do other tasks to prepare target site.
Optional.
- Focused on images or other binary data
- Should not be dependent on site data that might change
- may have additional dependencies (e.g. Inkscape or ImageMagick) on
software not installed on the server
- not run when RE-generating the site.
"""
pass
@staticmethod
def generate(site):
"""
Generate a page or pages in the target site.
Optional.
- Produces PAGES of HTML, SVG, etc.
- Uses templates provide by the chain of sources
- Should provide a default template, unless its using a standard site template
(i.e. don't leave it up to the theme)
- Dynamic. Regenerated in every site update.
"""
pass

View File

@ -0,0 +1,2 @@
# Addons should appear in this directory.
# Do not put code in this file.

View File

@ -0,0 +1,101 @@
/* Sponsorship Ad */
.sponsorship_packages_ad {
font-family: BioliniumBold;
font-size: 20pt;
text-align: center;
color: #ffffee;
transition: none;
border-style: solid;
border-width: 3pt;
border-color: blue;
background-color: #222233;
border-radius: 4vw;
margin: 1pt;
padding: 5pt;
}
/* Affiliate Ads */
.affiliate_carousel {
width: 100%;
min-width: 100%;
max-width: 100%;
height: 1.5in;
overflow: hidden;
display: block;
position: relative;
padding: 0px;
background-color: red;
}
.affiliate_content {
position: absolute;
top: 0in;
left: 0in;
width: 42in;
height: 1.5in;
padding: 0px;
margin: 0px;
display: flex;
justify-content: space-around;
align-content: center;
animation-name: affiliate_scroll;
animation-duration: 300s;
animation-iteration-count: infinite;
animation-timing-function: linear;
flex-shrink: 3in;
flex-grow: 18in;
background-color: black;
}
@keyframes affiliate_scroll {
from { left: 0in; }
to { left: -21in; }
}
.affiliate_item {
padding: 2px;
margin: 3px;
background-color: black;
width: 3in;
height: 1.5in;
position: relative;
color: black;
border-style: solid;
border-color: black;
border-width: 3pt;
}
.affiliate_image {
width: 3in;
height: 1.4in;
background-color: black;
position: absolute;
left: 0px;
top: 0px;
}
@media only screen and (max-width: 600px), (max-height: 600px) {
.affiliate_image,
.affiliate_item {
width: 4in;
height: 0.9in;
max-width: 1.9in;
min-width: 1.9in;
max-height: 0.9in;
min-height: 0.9in;
}
.affiliate_carousel {
height: 0.9in;
}
.affiliate_content {
width: 28in;
height: 1in;
}
@keyframes affiliate_scroll {
from { left: 0in; }
to { left: -14in; }
}
}

View File

@ -0,0 +1,45 @@
'''
Created on Oct 24, 2021
@author: terry
'''
import os, random
import yaml
import lunagen.addon
class Affiliates(lunagen.addon.LunaGenAddOn):
"""
Affiliates advertising bar.
"""
name = 'affiliates'
desc = """\
Randomly selects affiliate link ads from a list and sets them to
display on a scrolling bar on the page.
"""
file = __file__
@staticmethod
def load(site):
if site.verbose: print("Loading affiliates data.")
try:
with open(os.path.join(site.datadir, 'affiliates.yaml')) as aff_file:
affiliates = yaml.safe_load(aff_file)
stylesheets = site.sitedata['stylesheets']
site.sitedata.update(affiliates)
site.sitedata['stylesheets'] = site._collect_stylesheets(affiliates)
site.sitedata['affiliates'] = random.sample(
affiliates['affiliates'], min( int(affiliates['affiliates_at_once']),
len(affiliates['affiliates'])))
# Generates a single banner default:
site.sitedata['banners'] = iter(['affiliates_banner.j2'])
site._copy_skeleton(os.path.join(os.path.dirname(__file__), 'skeleton'))
except FileNotFoundError:
print("No affiliates.yaml file, so affiliates list is empty.")
site.sitedata['affiliates'] = []

View File

@ -0,0 +1,147 @@
# This file documents the sitedata values needed by the Affiliates Banner add-on.
---
stylesheets:
- affiliates
affiliates_at_once: 7 # How many banners do you want to rotate at a time?
affiliates_message: >
We benefit when you support these projects and services!
# A text caption that appears with the banner
affiliate_image_path: 'affiliates/'
# TODO: not yet implemented
# Relative path from site root to location affiliate banners are stored
affiliates: # Data for each banner - unlimited (randomly selected on generation)
- name: Ardour
url: https://ardour.org
img: ardour.png
type: Software We Use
- name: Audacity
url: https://audacityteam.org
img: audacity.png
type: Software We Use
- name: Blender
url: https://blender.org
img: blender.png
type: Software We Use
- name: Blender Cloud
url: https://cloud.blender.org
img: blender_cloud.png
type: Open Movie Platform
- name: BlendSwap
url: https://blendswap.com
img: blendswap.png
type: Shared Asset Archive
- name: Creative Commons
url: https://www.creativecommons.org
img: creativecommons.png
type: Free Culture Advocacy Group
- name: Debian
url: https://debian.org
img: debian.png
type: Software We Use
- name: Ethic Cinema
url: http://ethiccinema.org
img: ethiccinema.png
type: Free Culture Advocacy Group
- name: Free Software Foundation
url: https://www.fsf.org
img: freesoftwarefoundation.png
type: Free Software Advocacy Group
- name: Free Sound
url: https://freesound.org
img: freesound.png
type: Shared Asset Archive
- name: GIMP
url: https://gimp.org
img: gimp.png
type: Software We Use
- name: Inkscape
url: https://inkscape.org
img: inkscape.png
type: Software We Use
- name: Internet Archive
url: https://archive.org
img: internet_archive.png
type: Shared Asset Archive
- name: Jamendo
url: https://jamendo.com
img: jamendo.png
type: Shared Asset Archive
- name: Kdenlive
url: https://kdenlive.org
img: kdenlive.png
type: Software We Use
- name: Krita
url: https://krita.org
img: krita.png
type: Software We Use
- name: Mastodon
url: http://mastodon.social
img: mastodon.png
type: Social Media Platform We Use
- name: Morevna Project
url: https://morevnaproject.org
img: morevnaproject.png
type: Free Culture Project
- name: MusOpen
url: https://musopen.org
img: musopen.png
type: Shared Asset Archive
- name: Olive Video Editor
url: https://olivevideoeditor.org
img: olivevideoeditor.png
type: Software We Use
- name: Public Domain Files
url: http://www.publicdomainfiles.com
img: publicdomainfiles.png
type: Shared Asset Archive
- name: Public Knowledge
url: https://publicknowledge.org
img: publicknowledge.png
type: Free Culture Advocacy Group
- name: Question Copyright
url: https://questioncopyright.org
img: questioncopyright.png
type: Free Culture Advocacy Group
- name: Software Freedom Conservancy
url: https://sfconservancy.org
img: sfconservancy.png
type: Free Software Advocacy Group
- name: Ubuntu Studio
url: https://ubuntustudio.org
img: ubuntu_studio.png
type: Software We Use
- name: Urchn
url: https://urchn.org
img: urchn.png
type: Free Culture Studio

View File

@ -0,0 +1,25 @@
{# INCLUDE #}
{% if affiliates %}
<!-- Affiliate Links Banner Bar (INCLUDE) -->
<div id="AffiliateLinks" class="banner_bar">
<p class="fine_print">
{% if affiliates_message is defined %}
{{ affiliates_message }}</p>
{% else %}
Affiliate links: commissions support our project.</p>
{% endif %}
<div class="affiliate_carousel">
<div class="affiliate_content">
{% for i in range(2) %}
{% for affiliate in affiliates %}
<div class="affiliate_item">
<a href="{{affiliate.url}}" target="_blank" rel="nofollow" ><img src="{{imgdir}}/affiliates/{{affiliate.img}}"
alt="{{affiliate.name | escape}}" title="{{affiliate.name | escape}} - {{affiliate.type}}"
class="affiliate_image" /></a>
</div>
{% endfor %}
{% endfor %}
</div>
</div>
</div> <!-- AffiliateLinks -->
{% endif %}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,26 @@
/* Store products banner */
.store_banner {
width: 100%;
min-height: 0.5in;
max-height: 2in;
overflow: hidden;
display: flex;
flex-wrap: wrap;
flex-width: 2in;
justify-content: center;
}
.product_img {
width: 1in;
height: 0.5in;
display: inline-block;
padding: 0px;
margin: 0px;
}
@media only screen and (min-width: 7in) {
.product_img { width: 2in; height: 1in; }
}

View File

@ -0,0 +1,38 @@
'''
Created on Oct 27, 2021
@author: terry
'''
import os
import yaml
import lunagen.addon
class Products(lunagen.addon.LunaGenAddOn):
"""
Products with Banners.
"""
name = 'products'
desc = """\
Display a set of product banners for merch store.
"""
file = __file__
@staticmethod
def load(site):
if site.verbose: print("Loading store products data.")
try:
with open(os.path.join(site.datadir, 'products.yaml')) as prod_file:
products = yaml.safe_load(prod_file)
# stylesheets = site.sitedata['stylesheets']
site.sitedata.update(products)
site.sitedata['stylesheets'] = site._collect_stylesheets(products)
except FileNotFoundError:
print("No products.yaml file, so products list is empty.")
site.sitedata['products'] = []

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,11 @@
{# INCLUDE #}
<!-- Store Banner INCLUDE -->
<div id="store_banner" class="banner_bar">
<p class="fine_print">Lunatics! Shop: Profits support our project.</p>
<div class="store_banner">
{%- for product in products %}
<a href="{{product.url}}"><img src="{{imgdir}}/products/{{product.img}}" class="product_img"
alt="{{product.name}}" title="{{product.desc}}" /></a>
{%- endfor %}
</div>
</div>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 46 MiB

View File

@ -0,0 +1,291 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="88"
height="31"
viewBox="0 0 88 31"
version="1.1"
id="svg8"
inkscape:version="1.0.2 (1.0.2+r75+1)"
sodipodi:docname="eclipse.png.svg"
inkscape:export-filename="/project/terry/Dev/eclipse-workspace/LunaGen/src/lunagen/addons/softwarelist/skeleton/images/icons/eclipse.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs2">
<linearGradient
id="vlpc"
x1="151"
x2="112"
y1="192.4"
y2="137.3"
gradientTransform="matrix(0.5625,0,0,0.568,-9.4,-5.305)"
gradientUnits="userSpaceOnUse">
<stop
style="stop-color:#ffd43b"
offset="0"
id="stop875" />
<stop
style="stop-color:#ffe873"
offset="1"
id="stop877" />
</linearGradient>
<linearGradient
id="vlpb"
x1="26.65"
x2="135.7"
y1="20.6"
y2="114.4"
gradientTransform="matrix(0.5625,0,0,0.568,-9.4,-5.305)"
gradientUnits="userSpaceOnUse">
<stop
style="stop-color:#5a9fd4"
offset="0"
id="stop880" />
<stop
style="stop-color:#306998"
offset="1"
id="stop882" />
</linearGradient>
<radialGradient
id="vlpa"
cx="61.52"
cy="132.3"
r="29.04"
gradientTransform="matrix(2.383e-8,-0.2964,1.437,4.684e-7,-128.5,150.5)"
gradientUnits="userSpaceOnUse">
<stop
style="stop-color:#b8b8b8;stop-opacity:.498"
offset="0"
id="stop885" />
<stop
style="stop-color:#7f7f7f;stop-opacity:0"
offset="1"
id="stop887" />
</radialGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#878787"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="11.840909"
inkscape:cx="44.25254"
inkscape:cy="24.286204"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
units="px"
inkscape:window-width="2880"
inkscape:window-height="1620"
inkscape:window-x="826"
inkscape:window-y="228"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
id="grid833"
originx="4"
originy="1"
spacingx="8"
spacingy="5" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g1091"
transform="matrix(0.18193017,0,0,0.18193017,-11.670632,-53.420151)">
<path
fill="#2c2255"
d="M 101.124,392.936 H 84.38 c 2.217,7.605 6.331,14.422 12.354,20.445 9.602,9.604 21.148,14.398 34.65,14.398 2.699,0 5.314,-0.201 7.854,-0.584 10.17,-1.535 19.074,-6.133 26.703,-13.814 6.062,-6.021 10.205,-12.84 12.439,-20.445 h -6.795 -9.936 z"
id="path991" />
<g
id="g997">
<path
fill="#2c2255"
d="m 91.891,370.194 h -8.747 c -0.32,1.922 -0.538,3.884 -0.637,5.896 h 10.396 5.215 75.275 6.871 c -0.1,-2.012 -0.318,-3.974 -0.641,-5.896"
id="path993" />
<path
fill="#2c2255"
d="m 82.507,381.565 c 0.099,2.013 0.316,3.975 0.637,5.896 h 9.094 6.893 73.648 6.846 c 0.322,-1.921 0.542,-3.883 0.642,-5.896"
id="path995" />
</g>
<path
fill="#2c2255"
d="m 178.382,364.718 c -2.232,-7.626 -6.376,-14.474 -12.441,-20.54 -7.609,-7.608 -16.488,-12.174 -26.625,-13.71 -2.564,-0.389 -5.205,-0.593 -7.932,-0.593 -13.502,0 -25.049,4.769 -34.65,14.303 -6.025,6.066 -10.141,12.914 -12.357,20.54"
id="path999" />
<g
id="g1003">
<path
fill="#f7941e"
d="m 79.6,378.829 c 0,-25.824 19.395,-47.281 44.626,-51.055 -0.626,-0.023 -1.255,-0.049 -1.887,-0.049 -28.314,0 -51.269,22.881 -51.269,51.104 0,28.224 22.954,51.103 51.269,51.103 0.634,0 1.263,-0.023 1.891,-0.047 C 98.995,426.111 79.6,404.654 79.6,378.829 Z"
id="path1001" />
</g>
<rect
x="350.664"
y="323.66299"
fill="#f7941e"
width="10.197"
height="12.912"
id="rect1005" />
<path
fill="#2c2255"
d="m 265.529,376.799 v 4.986 h -46.885 c 0.442,7.022 2.558,12.369 6.345,16.044 3.788,3.678 9.062,5.514 15.822,5.514 3.916,0 7.712,-0.479 11.39,-1.438 3.676,-0.959 7.322,-2.402 10.945,-4.324 v 9.645 c -3.658,1.553 -7.408,2.734 -11.251,3.549 -3.843,0.812 -7.74,1.219 -11.693,1.219 -9.901,0 -17.743,-2.881 -23.525,-8.646 -5.782,-5.764 -8.673,-13.556 -8.673,-23.384 0,-10.16 2.743,-18.225 8.229,-24.19 5.486,-5.967 12.886,-8.951 22.195,-8.951 8.351,0 14.954,2.688 19.812,8.063 4.86,5.37 7.289,12.676 7.289,21.913 m -10.197,-2.992 c -0.075,-5.578 -1.636,-10.03 -4.683,-13.354 -3.049,-3.326 -7.085,-4.988 -12.109,-4.988 -5.69,0 -10.244,1.607 -13.661,4.822 -3.418,3.213 -5.385,7.74 -5.902,13.576 z"
id="path1007" />
<path
fill="#2c2255"
d="m 318.422,350.698 v 9.53 c -2.883,-1.588 -5.773,-2.778 -8.673,-3.573 -2.901,-0.795 -5.829,-1.191 -8.785,-1.191 -6.614,0 -11.749,2.096 -15.405,6.289 -3.658,4.193 -5.487,10.078 -5.487,17.65 0,7.573 1.829,13.459 5.487,17.651 3.656,4.195 8.791,6.289 15.405,6.289 2.956,0 5.884,-0.396 8.785,-1.188 2.897,-0.795 5.79,-1.986 8.673,-3.576 V 408 c -2.846,1.33 -5.793,2.328 -8.84,2.992 -3.05,0.666 -6.289,0.998 -9.727,0.998 -9.348,0 -16.773,-2.938 -22.277,-8.812 -5.506,-5.873 -8.258,-13.798 -8.258,-23.774 0,-10.121 2.779,-18.084 8.34,-23.886 5.56,-5.799 13.182,-8.7 22.859,-8.7 3.142,0 6.208,0.325 9.202,0.971 2.992,0.645 5.892,1.616 8.701,2.909"
id="path1009" />
<rect
x="327.64301"
y="324.151"
fill="#2c2255"
width="10.199"
height="86.231003"
id="rect1011" />
<path
fill="#2c2255"
d="m 350.664,348.312 h 10.197 v 62.07 h -10.197 z"
id="path1013" />
<path
fill="#2c2255"
d="m 383.549,401.072 v 32.92 h -10.252 v -85.68 h 10.252 v 9.423 c 2.145,-3.693 4.852,-6.438 8.12,-8.23 3.271,-1.789 7.177,-2.688 11.722,-2.688 7.537,0 13.661,2.991 18.37,8.979 4.711,5.986 7.065,13.855 7.065,23.607 0,9.756 -2.354,17.625 -7.065,23.608 -4.709,5.984 -10.833,8.979 -18.37,8.979 -4.545,0 -8.451,-0.896 -11.722,-2.689 -3.271,-1.789 -5.978,-4.533 -8.12,-8.229 m 34.693,-21.669 c 0,-7.5 -1.543,-13.384 -4.628,-17.65 -3.085,-4.266 -7.324,-6.399 -12.72,-6.399 -5.396,0 -9.636,2.133 -12.719,6.399 -3.085,4.269 -4.629,10.15 -4.629,17.65 0,7.502 1.544,13.387 4.629,17.651 3.083,4.27 7.323,6.4 12.719,6.4 5.396,0 9.635,-2.133 12.72,-6.4 3.085,-4.264 4.628,-10.149 4.628,-17.651"
id="path1015" />
<path
fill="#2c2255"
d="m 476.788,350.143 v 9.644 c -2.884,-1.478 -5.875,-2.586 -8.979,-3.326 -3.104,-0.738 -6.317,-1.106 -9.643,-1.106 -5.062,0 -8.857,0.774 -11.39,2.327 -2.531,1.552 -3.794,3.879 -3.794,6.982 0,2.363 0.901,4.221 2.714,5.57 1.81,1.348 5.447,2.631 10.918,3.852 l 3.489,0.775 c 7.241,1.553 12.388,3.739 15.436,6.567 3.049,2.826 4.573,6.771 4.573,11.83 0,5.765 -2.282,10.326 -6.848,13.689 -4.562,3.359 -10.833,5.043 -18.812,5.043 -3.324,0 -6.789,-0.324 -10.394,-0.969 -3.603,-0.646 -7.396,-1.617 -11.389,-2.91 V 397.58 c 3.771,1.961 7.482,3.428 11.14,4.408 3.658,0.979 7.278,1.467 10.862,1.467 4.804,0 8.496,-0.82 11.084,-2.465 2.587,-1.646 3.878,-3.963 3.878,-6.955 0,-2.771 -0.932,-4.896 -2.796,-6.375 -1.867,-1.478 -5.959,-2.9 -12.278,-4.269 l -3.545,-0.829 c -6.316,-1.33 -10.881,-3.371 -13.688,-6.123 -2.809,-2.752 -4.212,-6.529 -4.212,-11.334 0,-5.839 2.068,-10.345 6.207,-13.521 4.138,-3.178 10.013,-4.768 17.623,-4.768 3.769,0 7.314,0.276 10.641,0.83 3.328,0.558 6.394,1.388 9.203,2.497"
id="path1017" />
<path
fill="#2c2255"
d="m 540.93,376.799 v 4.986 h -46.885 c 0.443,7.022 2.558,12.369 6.347,16.044 3.785,3.678 9.062,5.514 15.82,5.514 3.918,0 7.713,-0.479 11.39,-1.438 3.678,-0.959 7.323,-2.402 10.946,-4.324 v 9.645 c -3.659,1.553 -7.409,2.734 -11.252,3.549 -3.841,0.812 -7.739,1.219 -11.69,1.219 -9.903,0 -17.744,-2.881 -23.524,-8.646 -5.784,-5.764 -8.675,-13.556 -8.675,-23.384 0,-10.16 2.744,-18.225 8.229,-24.19 5.486,-5.968 12.889,-8.951 22.196,-8.951 8.349,0 14.954,2.688 19.812,8.063 4.856,5.37 7.286,12.676 7.286,21.913 m -10.197,-2.992 c -0.076,-5.578 -1.636,-10.03 -4.686,-13.354 -3.049,-3.326 -7.086,-4.988 -12.106,-4.988 -5.689,0 -10.244,1.607 -13.66,4.822 -3.418,3.213 -5.389,7.74 -5.903,13.576 z"
id="path1019" />
<g
id="g1042">
<linearGradient
id="SVGID_1_"
gradientUnits="userSpaceOnUse"
x1="502.3848"
y1="-40.075699"
x2="502.3848"
y2="-113.7106"
gradientTransform="translate(-371,474.5)">
<stop
offset="0.3033"
style="stop-color:#473788"
id="stop1021" />
<stop
offset="0.872"
style="stop-color:#2C2255"
id="stop1023" />
</linearGradient>
<path
fill="url(#SVGID_1_)"
d="m 164.653,376.089 c -0.164,-2.021 -0.504,-3.992 -1.012,-5.896 h -64.51 c -0.508,1.902 -0.849,3.874 -1.013,5.896 z"
id="path1026"
style="fill:url(#SVGID_1_)" />
<linearGradient
id="SVGID_2_"
gradientUnits="userSpaceOnUse"
x1="502.38571"
y1="-40.074699"
x2="502.38571"
y2="-113.7096"
gradientTransform="translate(-371,474.5)">
<stop
offset="0.3033"
style="stop-color:#473788"
id="stop1028" />
<stop
offset="0.872"
style="stop-color:#2C2255"
id="stop1030" />
</linearGradient>
<path
fill="url(#SVGID_2_)"
d="M 164.653,381.565 H 98.119 c 0.164,2.021 0.503,3.991 1.012,5.896 h 64.511 c 0.508,-1.904 0.847,-3.875 1.011,-5.896 z"
id="path1033"
style="fill:url(#SVGID_2_)" />
<linearGradient
id="SVGID_3_"
gradientUnits="userSpaceOnUse"
x1="502.38571"
y1="-40.077599"
x2="502.38571"
y2="-113.7071"
gradientTransform="translate(-371,474.5)">
<stop
offset="0.3033"
style="stop-color:#473788"
id="stop1035" />
<stop
offset="0.8631"
style="stop-color:#2C2255"
id="stop1037" />
</linearGradient>
<path
fill="url(#SVGID_3_)"
d="m 131.386,412.217 c 13.397,0 24.945,-7.893 30.263,-19.281 h -60.526 c 5.318,11.388 16.866,19.281 30.263,19.281 z"
id="path1040"
style="fill:url(#SVGID_3_)" />
</g>
<g
id="g1050">
<path
fill="#ffffff"
d="m 93.188,381.565 h 4.884 66.706 8.763 6.657 c 0.046,-0.871 0.072,-1.748 0.072,-2.632 0,-0.955 -0.035,-1.901 -0.089,-2.845 H 173.54 164.777 98.071 92.842 82.507 c -0.054,0.942 -0.089,1.89 -0.089,2.845 0,0.884 0.026,1.761 0.072,2.632 z"
id="path1044" />
<path
fill="#ffffff"
d="M 100.928,364.718 H 84.376 c -0.544,1.783 -0.895,3.612 -1.232,5.477 h 8.525 7.259 64.679 9.16 6.547 c -0.338,-1.863 -0.773,-3.692 -1.316,-5.477"
id="path1046" />
<path
fill="#ffffff"
d="m 173.026,387.46 h -9.16 -64.678 -6.912 -9.133 c 0.328,1.863 0.701,3.691 1.236,5.476 h 16.807 60.682 9.962 6.488 c 0.534,-1.783 0.965,-3.611 1.294,-5.476 z"
id="path1048" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="88"
height="31"
viewBox="0 0 88 31"
version="1.1"
id="svg8"
inkscape:version="1.0.2 (1.0.2+r75+1)"
sodipodi:docname="jinja2.png.svg"
inkscape:export-filename="/project/terry/Dev/eclipse-workspace/LunaGen/src/lunagen/addons/softwarelist/skeleton/images/icons/jinja2.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs2">
<linearGradient
id="vlpc"
x1="151"
x2="112"
y1="192.4"
y2="137.3"
gradientTransform="matrix(0.5625,0,0,0.568,-9.4,-5.305)"
gradientUnits="userSpaceOnUse">
<stop
style="stop-color:#ffd43b"
offset="0"
id="stop875" />
<stop
style="stop-color:#ffe873"
offset="1"
id="stop877" />
</linearGradient>
<linearGradient
id="vlpb"
x1="26.65"
x2="135.7"
y1="20.6"
y2="114.4"
gradientTransform="matrix(0.5625,0,0,0.568,-9.4,-5.305)"
gradientUnits="userSpaceOnUse">
<stop
style="stop-color:#5a9fd4"
offset="0"
id="stop880" />
<stop
style="stop-color:#306998"
offset="1"
id="stop882" />
</linearGradient>
<radialGradient
id="vlpa"
cx="61.52"
cy="132.3"
r="29.04"
gradientTransform="matrix(2.383e-8,-0.2964,1.437,4.684e-7,-128.5,150.5)"
gradientUnits="userSpaceOnUse">
<stop
style="stop-color:#b8b8b8;stop-opacity:.498"
offset="0"
id="stop885" />
<stop
style="stop-color:#7f7f7f;stop-opacity:0"
offset="1"
id="stop887" />
</radialGradient>
<linearGradient
id="linearGradient6558">
<stop
style="stop-color:#575757;stop-opacity:1;"
offset="0"
id="stop6560" />
<stop
style="stop-color:#2f2f2f;stop-opacity:1;"
offset="1"
id="stop6562" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient6558"
id="radialGradient6564"
cx="61.297766"
cy="60.910986"
fx="61.297766"
fy="60.910986"
r="44.688254"
gradientTransform="matrix(1,0,0,0.945104,0,3.343747)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient6558"
id="radialGradient6580"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.945104,0.355158,3.334402)"
cx="61.297766"
cy="60.910986"
fx="61.297766"
fy="60.910986"
r="44.688254" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient6558"
id="linearGradient4173"
x1="255.15521"
y1="32.347946"
x2="279.8912"
y2="32.347946"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.8073249,0,0,0.8073249,57.960878,7.4036303)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient6558"
id="linearGradient5145"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7902775,0,0,0.82474,60.019977,8.0684132)"
x1="255.15521"
y1="32.347946"
x2="279.8912"
y2="32.347946" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#9bacc2"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="16.745574"
inkscape:cx="56.700057"
inkscape:cy="24.358228"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="true"
units="px"
inkscape:window-width="2760"
inkscape:window-height="1620"
inkscape:window-x="826"
inkscape:window-y="228"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
id="grid833"
originx="4"
originy="1"
spacingx="8"
spacingy="5" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>