Skip to content
Permalink
Browse files
Merge pull request #3137 from getnikola/config_bundles
Read bundles with configparser
  • Loading branch information
Kwpolska committed Aug 10, 2018
2 parents 7928304 + adbc4d6 commit 961bb42b941755ea3f2badace1adb489d3ab4ee3
Showing with 132 additions and 39 deletions.
  1. +2 −0 CHANGES.txt
  2. +27 −9 docs/creating-a-theme.rst
  3. +14 −6 docs/theming.rst
  4. +20 −4 nikola/data/themes/base/bundles
  5. +29 −4 nikola/data/themes/bootblog4/bundles
  6. +27 −4 nikola/data/themes/bootstrap4/bundles
  7. +13 −12 nikola/plugins/task/bundles.py
@@ -14,6 +14,8 @@ Features
"{postDate} (${messages("updated")} {updateDate})". If no update
time is specified, the posting time will be displayed alone.
* All built-in themes now support the ``DATE_FANCINESS`` option.
* Theme bundles are now parsed using the configparser module and
can support newlines inside entries as well as comments

Bugfixes
--------
@@ -813,15 +813,33 @@ Doing the same for layout-reverse, sidebar-overlay and the rest is left as an ex
Bundles
-------

If you have ``webassets`` installed and the ``USE_BUNDLES`` option set to True, Nikola can put several CSS or JS files together in a larger file,
which makes sites load faster. To do that, your theme needs a ``bundles`` file where the syntax is::

outputfile1.js=thing1.js,thing2.js,...
outputfile2.css=thing1.css,thing2.css,...

For the Lanyon theme, it should be like this::

assets/css/all.css=rst_base.css,nikola_rst.css,code.css,poole.css,lanyon.css,custom.css
If you have ``webassets`` installed and the ``USE_BUNDLES`` option set to True,
Nikola can put several CSS or JS files together in a larger file, which can
makes site load faster for some deployments. To do this, your theme needs
a ``bundles`` file. The file format is a modified
`config <https://docs.python.org/3/library/configparser.html>`_ file with no
defined section; the basic syntax is::

outputfile1.js=
thing1.js,
thing2.js,
...
outputfile2.css=
thing1.css,
thing2.css,
...

For the Lanyon theme, it should look like this::

assets/css/all.css=
rst_base.css,
nikola_rst.css,
code.css,
poole.css,
lanyon.css,
custom.css,

**Note:** trailing commas are optional

**Note:** Some themes also support the ``USE_CDN`` option meaning that in some cases it will load one bundle with all CSS and in other will load some CSS files
from a CDN and others from a bundle. This is complicated and probably not worth the effort.
@@ -73,12 +73,20 @@ parent, engine
older).

bundles
A text file containing a list of files to be turned into bundles using WebAssets.
For example:

.. code:: text

assets/css/all.css=bootstrap.min.css,rst_base.css,nikola_rst.css,code.css,baguetteBox.min.css,theme.css,custom.css
A `config <https://docs.python.org/3/library/configparser.html>`_ file
containing a list of files to be turned into bundles using WebAssets. For
example:

.. code:: ini

assets/css/all.css=
bootstrap.min.css,
rst_base.css,
nikola_rst.css,
code.css,
baguetteBox.min.css,
theme.css,
custom.css,

This creates a file called "assets/css/all.css" in your output that is the
combination of all the other file paths, relative to the output file.
@@ -1,4 +1,20 @@
assets/css/all.css=rst_base.css,nikola_rst.css,code.css,theme.css
assets/css/all-nocdn.css=rst_base.css,nikola_rst.css,code.css,theme.css,baguetteBox.min.css
assets/js/all.js=fancydates.js
assets/js/all-nocdn.js=baguetteBox.min.js,moment-with-locales.min.js,fancydates.js
; css bundles
assets/css/all.css=
rst_base.css,
nikola_rst.css,
code.css,
theme.css,
assets/css/all-nocdn.css=
rst_base.css,
nikola_rst.css,
code.css,
theme.css,
baguetteBox.min.css,

; javascript bundles
assets/js/all.js=
fancydates.js,
assets/js/all-nocdn.js=
baguetteBox.min.js,
moment-with-locales.min.js,
fancydates.js,
@@ -1,4 +1,29 @@
assets/css/all-nocdn.css=bootstrap.min.css,rst_base.css,nikola_rst.css,code.css,baguetteBox.min.css,theme.css,bootblog.css,custom.css
assets/css/all.css=rst_base.css,nikola_rst.css,code.css,baguetteBox.min.css,theme.css,bootblog.css,custom.css
assets/js/all-nocdn.js=jquery.min.js,popper.min.js,bootstrap.min.js,baguetteBox.min.js,moment-with-locales.min.js,fancydates.min.js
assets/js/all.js=fancydates.min.js
; css bundles
assets/css/all-nocdn.css=
bootstrap.min.css,
rst_base.css,
nikola_rst.css,
code.css,
baguetteBox.min.css,
theme.css,
bootblog.css,
custom.css,
assets/css/all.css=
rst_base.css,
nikola_rst.css,
code.css,
baguetteBox.min.css,
theme.css,
bootblog.css,
custom.css,

; javascript bundles
assets/js/all-nocdn.js=
jquery.min.js,
popper.min.js,
bootstrap.min.js,
baguetteBox.min.js,
moment-with-locales.min.js,
fancydates.min.js,
assets/js/all.js=
fancydates.min.js,
@@ -1,4 +1,27 @@
assets/css/all-nocdn.css=bootstrap.min.css,rst_base.css,nikola_rst.css,code.css,baguetteBox.min.css,theme.css,custom.css
assets/css/all.css=rst_base.css,nikola_rst.css,code.css,baguetteBox.min.css,theme.css,custom.css
assets/js/all-nocdn.js=jquery.min.js,popper.min.js,bootstrap.min.js,baguetteBox.min.js,moment-with-locales.min.js,fancydates.min.js
assets/js/all.js=fancydates.min.js
; css bundles
assets/css/all-nocdn.css=
bootstrap.min.css,
rst_base.css,
nikola_rst.css,
code.css,
baguetteBox.min.css,
theme.css,
custom.css,
assets/css/all.css=
rst_base.css,
nikola_rst.css,
code.css,
baguetteBox.min.css,
theme.css,
custom.css,

; javascript bundles
assets/js/all-nocdn.js=
jquery.min.js,
popper.min.js,
bootstrap.min.js,
baguetteBox.min.js,
moment-with-locales.min.js,
fancydates.min.js,
assets/js/all.js=
fancydates.min.js
@@ -27,6 +27,9 @@
"""Bundle assets using WebAssets."""


import configparser
import io
import itertools
import os

try:
@@ -125,19 +128,17 @@ def build_bundle(output, inputs):

def get_theme_bundles(themes):
"""Given a theme chain, return the bundle definitions."""
bundles = {}
for theme_name in themes:
bundles_path = os.path.join(
utils.get_theme_path(theme_name), 'bundles')
if os.path.isfile(bundles_path):
with open(bundles_path) as fd:
for line in fd:
try:
name, files = line.split('=')
files = [f.strip() for f in files.split(',')]
bundles[name.strip().replace('/', os.sep)] = files
except ValueError:
# for empty lines
pass
break
return bundles
config = configparser.ConfigParser()
header = io.StringIO('[bundles]\n')
with open(bundles_path, 'rt') as fd:
config.read_file(itertools.chain(header, fd))
bundles = {}
for name, files in config['bundles'].items():
name = name.strip().replace('/', os.sep)
files = [f.strip() for f in files.split(',') if f.strip()]
bundles[name] = files
return bundles

0 comments on commit 961bb42

Please sign in to comment.