Theme Package I: Preparations#
Creating a theme product with the Diazo inline editor is an easy way to start and to test, but it is not a solid long term solution and you are also limited in what you can do that way.
Even if plone.app.theming
allows importing and exporting of a Diazo theme as a ZIP archive,
it might be preferable to manage your theme as an actual Plone product.
One of the most obvious reasons is that it will allow you to override Plone elements that are not accessible via pure Diazo features (such as overloading content view templates, viewlets, configuration settings, etc.).
Preparing Your Setup#
Install npm#
If you don't have npm already installed on your system please do it. npm comes with nodejs, we just need to install npm.
On Debian/Ubuntu for example you can do this with apt:
sudo apt install -y npm
On a Mac you can install npm using Homebrew:
brew install node
If you need a newer version of npm just update your version with npm itself:
npm install npm@latest -g
Install Grunt#
We also need to install grunt-cli globally.
If you already have it, you can skip this step.
npm install -g grunt-cli
Setup A Python Virtual Environment#
First, let's create a Python virtualenv:
virtualenv mrbobvenv
Then we enable the virtualenv:
source mrbobvenv/bin/activate
(mrbobvenv):$
Create A Product To Handle Your Diazo Theme#
To create a Plone 5 theme skeleton, you will use mr.bob's templates for Plone.
Install mr.bob And bobtemplates.plone#
To install mr.bob
, you can use pip:
(mrbobvenv): pip install mr.bob
and to install the required bobtemplates for Plone, do:
(mrbobvenv): pip install bobtemplates.plone==2.0
Create a Plone 5 theme product skeleton with mrbob. It will ask you some questions about the new theme package:
(mrbobvenv): mrbob -O ploneconf.theme bobtemplates:plone_theme_package
Welcome to mr.bob interactive mode. Before we generate directory structure, some questions need to be answered.
Answer with a question mark to display help.
Values in square brackets at the end of the questions show the default value if there is no answer.
--> Theme name [Theme]: Ploneconf Theme
--> Author name [Your Name]:
--> Author email [your.email@example.com]:
--> Author github username:
--> Package description [An add-on for Plone]: Plone Conference Training Theme
--> Plone version [5.0.8]:
Now you have a new Python package in your current folder:
(mrbobvenv): ls ploneconf.theme
CHANGES.rst LICENSE.GPL bootstrap-buildout.py package.json src
CONTRIBUTORS.rst LICENSE.rst bootstrap-buildout.pyc requirements.txt
Gruntfile.js MANIFEST.in buildout.cfg setup.cfg
HOWTO_DEVELOP.rst README.rst docs setup.py
It is now safe to deactivate the mrbob
virtualenv:
(mrbobvenv): deactivate
Install zc.buildout And Bootstrap Your Development Environment#
You can install Buildout globally or on a virtualenv.
We will install zc.buildout
in a new virtual environment using the provided requirements.txt
.
virtualenv buildoutvenv
source buildoutvenv/bin/activate
(buildoutvenv):$ cd ploneconf.theme
(buildoutvenv):$ pip install -r requirements.txt
(buildoutvenv):$ buildout bootstrap
Now you have everything in place and you can run buildout.
Depending on your internet connection and your local buildout cache this can take several minutes to complete.
(buildoutvenv): ./bin/buildout
After buildout finished successfully it is now safe to deactivate the buildoutvenv
virtualenv:
(buildoutvenv): deactivate
This will create the whole development environment for your package:
ls bin
addchangelogentry code-analysis-zptlint lasttagdiff prerelease
buildout coverage lasttaglog pybabel
bumpversion createcoverage libdoc pybot
check-manifest createfontdatachunk.py longtest release
code-analysis develop painter.py ride
code-analysis-check-manifest enhancer.py pilconvert.py robot
code-analysis-clean-lines explode.py pildriver.py robot-debug
code-analysis-csslint flake8 pilfile.py robot-server
code-analysis-find-untranslated fullrelease pilfont.py test
code-analysis-flake8 gifmaker.py pilprint.py thresholder.py
code-analysis-jscs i18ndude player.py viewer.py
code-analysis-jshint instance postrelease
Inspect Your Package Source#
Your package source code is in the src
folder:
tree src/ploneconf/theme/
src/ploneconf/theme
├── __init__.py
├── browser
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── configure.zcml
│ ├── overrides
│ └── static
├── configure.zcml
├── interfaces.py
├── locales
│ ├── ploneconf.theme.pot
│ └── update.sh
├── profiles
│ ├── default
│ │ ├── browserlayer.xml
│ │ ├── metadata.xml
│ │ ├── registry.xml
│ │ └── theme.xml
│ └── uninstall
│ ├── browserlayer.xml
│ └── theme.xml
├── setuphandlers.py
├── testing.py
├── tests
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── robot
│ │ └── test_example.robot
│ ├── test_robot.py
│ └── test_setup.py
└── theme
├── HOWTO_DEVELOP.rst
├── backend.xml
├── barceloneta
│ └── less
│ ├── accessibility.plone.less
│ ├── alerts.plone.less
│ ├── barceloneta-compiled.css
│ ├── barceloneta-compiled.css.map
│ ├── barceloneta.css
│ ├── barceloneta.plone.export.less
│ ├── barceloneta.plone.less
│ ├── barceloneta.plone.local.less
│ ├── behaviors.plone.less
│ ├── breadcrumbs.plone.less
│ ├── buttons.plone.less
│ ├── code.plone.less
│ ├── contents.plone.less
│ ├── controlpanels.plone.less
│ ├── deco.plone.less
│ ├── discussion.plone.less
│ ├── dropzone.plone.less
│ ├── event.plone.less
│ ├── fonts.plone.less
│ ├── footer.plone.less
│ ├── forms.plone.less
│ ├── formtabbing.plone.less
│ ├── grid.plone.less
│ ├── header.plone.less
│ ├── image.plone.less
│ ├── loginform.plone.less
│ ├── main.plone.less
│ ├── mixin.borderradius.plone.less
│ ├── mixin.buttons.plone.less
│ ├── mixin.clearfix.plone.less
│ ├── mixin.forms.plone.less
│ ├── mixin.grid.plone.less
│ ├── mixin.gridframework.plone.less
│ ├── mixin.images.plone.less
│ ├── mixin.prefixes.plone.less
│ ├── mixin.tabfocus.plone.less
│ ├── modal.plone.less
│ ├── normalize.plone.less
│ ├── pagination.plone.less
│ ├── pickadate.plone.less
│ ├── plone-toolbarlogo.svg
│ ├── portlets.plone.less
│ ├── print.plone.less
│ ├── scaffolding.plone.less
│ ├── search.plone.less
│ ├── sitemap.plone.less
│ ├── sitenav.plone.less
│ ├── sortable.plone.less
│ ├── states.plone.less
│ ├── tables.plone.less
│ ├── tablesorter.plone.less
│ ├── tags.plone.less
│ ├── thumbs.plone.less
│ ├── toc.plone.less
│ ├── tooltip.plone.less
│ ├── tree.plone.less
│ ├── type.plone.less
│ ├── variables.plone.less
│ └── views.plone.less
├── barceloneta-apple-touch-icon-114x114-precomposed.png
├── barceloneta-apple-touch-icon-144x144-precomposed.png
├── barceloneta-apple-touch-icon-57x57-precomposed.png
├── barceloneta-apple-touch-icon-72x72-precomposed.png
├── barceloneta-apple-touch-icon-precomposed.png
├── barceloneta-apple-touch-icon.png
├── barceloneta-favicon.ico
├── index.html
├── less
│ ├── custom.less
│ ├── plone.toolbar.vars.less
│ ├── roboto
│ │ ├── LICENSE.txt
│ │ ├── Roboto-Light.eot
│ │ ├── Roboto-Light.svg
│ │ ├── Roboto-Light.ttf
│ │ ├── Roboto-Light.woff
│ │ ├── Roboto-LightItalic.eot
│ │ ├── Roboto-LightItalic.svg
│ │ ├── Roboto-LightItalic.ttf
│ │ ├── Roboto-LightItalic.woff
│ │ ├── Roboto-Medium.eot
│ │ ├── Roboto-Medium.svg
│ │ ├── Roboto-Medium.ttf
│ │ ├── Roboto-Medium.woff
│ │ ├── Roboto-MediumItalic.eot
│ │ ├── Roboto-MediumItalic.svg
│ │ ├── Roboto-MediumItalic.ttf
│ │ ├── Roboto-MediumItalic.woff
│ │ ├── Roboto-Regular.eot
│ │ ├── Roboto-Regular.svg
│ │ ├── Roboto-Regular.ttf
│ │ ├── Roboto-Regular.woff
│ │ ├── Roboto-Thin.eot
│ │ ├── Roboto-Thin.svg
│ │ ├── Roboto-Thin.ttf
│ │ ├── Roboto-Thin.woff
│ │ ├── Roboto-ThinItalic.eot
│ │ ├── Roboto-ThinItalic.svg
│ │ ├── Roboto-ThinItalic.ttf
│ │ ├── Roboto-ThinItalic.woff
│ │ ├── RobotoCondensed-Light.eot
│ │ ├── RobotoCondensed-Light.svg
│ │ ├── RobotoCondensed-Light.ttf
│ │ ├── RobotoCondensed-Light.woff
│ │ ├── RobotoCondensed-LightItalic.eot
│ │ ├── RobotoCondensed-LightItalic.svg
│ │ ├── RobotoCondensed-LightItalic.ttf
│ │ └── RobotoCondensed-LightItalic.woff
│ ├── theme-compiled.css
│ ├── theme.less
│ └── theme.local.less
├── manifest.cfg
├── node_modules
│ └── bootstrap
│ ├── CHANGELOG.md
│ ├── Gruntfile.js
│ ├── LICENSE
│ ├── README.md
│ ├── dist
│ │ ├── css
│ │ │ ├── bootstrap-theme.css
│ │ │ ├── bootstrap-theme.css.map
│ │ │ ├── bootstrap-theme.min.css
│ │ │ ├── bootstrap-theme.min.css.map
│ │ │ ├── bootstrap.css
│ │ │ ├── bootstrap.css.map
│ │ │ ├── bootstrap.min.css
│ │ │ └── bootstrap.min.css.map
│ │ ├── fonts
│ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ ├── glyphicons-halflings-regular.svg
│ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ ├── glyphicons-halflings-regular.woff
│ │ │ └── glyphicons-halflings-regular.woff2
│ │ └── js
│ │ ├── bootstrap.js
│ │ ├── bootstrap.min.js
│ │ └── npm.js
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
│ ├── grunt
│ │ ├── bs-commonjs-generator.js
│ │ ├── bs-glyphicons-data-generator.js
│ │ ├── bs-lessdoc-parser.js
│ │ ├── bs-raw-files-generator.js
│ │ ├── change-version.js
│ │ ├── configBridge.json
│ │ ├── npm-shrinkwrap.json
│ │ └── sauce_browsers.yml
│ ├── js
│ │ ├── affix.js
│ │ ├── alert.js
│ │ ├── button.js
│ │ ├── carousel.js
│ │ ├── collapse.js
│ │ ├── dropdown.js
│ │ ├── modal.js
│ │ ├── popover.js
│ │ ├── scrollspy.js
│ │ ├── tab.js
│ │ ├── tooltip.js
│ │ └── transition.js
│ ├── less
│ │ ├── alerts.less
│ │ ├── badges.less
│ │ ├── bootstrap.less
│ │ ├── breadcrumbs.less
│ │ ├── button-groups.less
│ │ ├── buttons.less
│ │ ├── carousel.less
│ │ ├── close.less
│ │ ├── code.less
│ │ ├── component-animations.less
│ │ ├── dropdowns.less
│ │ ├── forms.less
│ │ ├── glyphicons.less
│ │ ├── grid.less
│ │ ├── input-groups.less
│ │ ├── jumbotron.less
│ │ ├── labels.less
│ │ ├── list-group.less
│ │ ├── media.less
│ │ ├── mixins
│ │ │ ├── alerts.less
│ │ │ ├── background-variant.less
│ │ │ ├── border-radius.less
│ │ │ ├── buttons.less
│ │ │ ├── center-block.less
│ │ │ ├── clearfix.less
│ │ │ ├── forms.less
│ │ │ ├── gradients.less
│ │ │ ├── grid-framework.less
│ │ │ ├── grid.less
│ │ │ ├── hide-text.less
│ │ │ ├── image.less
│ │ │ ├── labels.less
│ │ │ ├── list-group.less
│ │ │ ├── nav-divider.less
│ │ │ ├── nav-vertical-align.less
│ │ │ ├── opacity.less
│ │ │ ├── pagination.less
│ │ │ ├── panels.less
│ │ │ ├── progress-bar.less
│ │ │ ├── reset-filter.less
│ │ │ ├── reset-text.less
│ │ │ ├── resize.less
│ │ │ ├── responsive-visibility.less
│ │ │ ├── size.less
│ │ │ ├── tab-focus.less
│ │ │ ├── table-row.less
│ │ │ ├── text-emphasis.less
│ │ │ ├── text-overflow.less
│ │ │ └── vendor-prefixes.less
│ │ ├── mixins.less
│ │ ├── modals.less
│ │ ├── navbar.less
│ │ ├── navs.less
│ │ ├── normalize.less
│ │ ├── pager.less
│ │ ├── pagination.less
│ │ ├── panels.less
│ │ ├── popovers.less
│ │ ├── print.less
│ │ ├── progress-bars.less
│ │ ├── responsive-embed.less
│ │ ├── responsive-utilities.less
│ │ ├── scaffolding.less
│ │ ├── tables.less
│ │ ├── theme.less
│ │ ├── thumbnails.less
│ │ ├── tooltip.less
│ │ ├── type.less
│ │ ├── utilities.less
│ │ ├── variables.less
│ │ └── wells.less
│ └── package.json
├── package-lock.json
├── package.json
├── preview.png
├── rules.xml
├── template-overrides
├── tinymce-templates
│ └── image-grid-2x2.html
└── views
└── slider-images.pt.example
28 directories, 256 files
As you can see, the package already contains a Diazo theme including the Barceloneta resources:
tree -L 2 src/ploneconf/theme/theme/
src/ploneconf/theme/theme/
├── HOWTO_DEVELOP.rst
├── backend.xml
├── barceloneta
│ └── less
├── barceloneta-apple-touch-icon-114x114-precomposed.png
├── barceloneta-apple-touch-icon-144x144-precomposed.png
├── barceloneta-apple-touch-icon-57x57-precomposed.png
├── barceloneta-apple-touch-icon-72x72-precomposed.png
├── barceloneta-apple-touch-icon-precomposed.png
├── barceloneta-apple-touch-icon.png
├── barceloneta-favicon.ico
├── index.html
├── less
│ ├── custom.less
│ ├── plone.toolbar.vars.less
│ ├── roboto
│ ├── theme-compiled.css
│ ├── theme.less
│ └── theme.local.less
├── manifest.cfg
├── node_modules
│ └── bootstrap
├── package-lock.json
├── package.json
├── preview.png
├── rules.xml
├── template-overrides
├── tinymce-templates
│ └── image-grid-2x2.html
└── views
└── slider-images.pt.example
9 directories, 22 files
This theme basically provides you with a copy of the Plone 5 default theme (Barceloneta), and you can change everything you need to create your own theme.
The Barceloneta resources are in the folder barceloneta
.
This is basically a copy of the theme folder of plonetheme.barceloneta
.
We removed some unneeded files there, because we only need the Less part for partially including it in our file theme.less
.
We also have the icons and the file backend.xml
from Barceloneta in our theme folder.
In the folder theme/less
we have our CSS/Less files.
Our own CSS goes into the file custom.less
.
You can also add more Less files and include them in theme.less
, if you have a lot of custom CSS and you like to split it into multiple files.
The file theme.less
is our main Less file.
Here we include all other files we need.
It already has some includes of Barceloneta, Twitter Bootstrap and our cusomizations from the file custom.less
at the bottom.
We also have a file package.json
, which we can use to define external dependencies like Twitter Bootstrap or other CSS/JS packages we want to use in our theme.
For more information on how to do this, see Install External CSS And JavaScript Libraries With npm And Use Them In Your Theme.
Start Plone And Install Your Theme Product#
To start the Plone instance, run:
./bin/instance fg
The Plone instance will then be available at http://localhost:8080.
The default username is admin
and password is admin
.
Go to http://localhost:8080 and click the button Create a new Plone site to add a new Plone site.
Name the site
Plone
(which should be the default) and click on Create Plone Site.Go to the Plone Control Panel:
Go to the Add-ons control panel.
Click on the Install next to
Plone Theme: Ploneconf Theme
to install your add-on.The theme will be automatically enabled.
If something is wrong with the theme, you can always go to http://localhost:8080/Plone/@@theming-controlpanel and disable it.
This control panel will never be themed, so it works even if the theme might be broken.
In the next section we will adjust the skeleton we got from bobtemplates.plone
and fill it with our custom theme.