Version 0.1.0 0.1.0
authorThierry Florac <tflorac@ulthar.net>
Sun, 11 May 2014 02:03:37 +0200
changeset 0 747fc65e13e2
child 1 367e761a2154
Version 0.1.0
MANIFEST.in
bootstrap.py
buildout.cfg
docs/CONTRIBUTORS.txt
docs/HISTORY.txt
docs/LICENSE.ZPL
docs/LICENSE.txt
docs/README.txt
setup.py
src/ztfy.baseskin.egg-info/PKG-INFO
src/ztfy.baseskin.egg-info/SOURCES.txt
src/ztfy.baseskin.egg-info/dependency_links.txt
src/ztfy.baseskin.egg-info/entry_points.txt
src/ztfy.baseskin.egg-info/namespace_packages.txt
src/ztfy.baseskin.egg-info/not-zip-safe
src/ztfy.baseskin.egg-info/requires.txt
src/ztfy.baseskin.egg-info/top_level.txt
src/ztfy/__init__.py
src/ztfy/baseskin/__init__.py
src/ztfy/baseskin/configure.zcml
src/ztfy/baseskin/doctests/README.txt
src/ztfy/baseskin/form.py
src/ztfy/baseskin/interfaces/__init__.py
src/ztfy/baseskin/interfaces/container.py
src/ztfy/baseskin/interfaces/form.py
src/ztfy/baseskin/interfaces/metas.py
src/ztfy/baseskin/layer.py
src/ztfy/baseskin/locales/en/LC_MESSAGES/ztfy.baseskin.mo
src/ztfy/baseskin/locales/en/LC_MESSAGES/ztfy.baseskin.po
src/ztfy/baseskin/locales/fr/LC_MESSAGES/ztfy.baseskin.mo
src/ztfy/baseskin/locales/fr/LC_MESSAGES/ztfy.baseskin.po
src/ztfy/baseskin/locales/ztfy.baseskin.pot
src/ztfy/baseskin/metas.py
src/ztfy/baseskin/metas.zcml
src/ztfy/baseskin/schema.py
src/ztfy/baseskin/skin.py
src/ztfy/baseskin/tal/__init__.py
src/ztfy/baseskin/tal/api.py
src/ztfy/baseskin/tal/configure.zcml
src/ztfy/baseskin/tal/interfaces.py
src/ztfy/baseskin/tests/__init__.py
src/ztfy/baseskin/tests/test_docs.py
src/ztfy/baseskin/tests/test_docstrings.py
src/ztfy/baseskin/viewlet.py
src/ztfy/baseskin/widget.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MANIFEST.in	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,4 @@
+include *.txt
+recursive-include docs *
+recursive-include src *
+global-exclude *.pyc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootstrap.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,178 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+"""
+
+import os
+import shutil
+import sys
+import tempfile
+
+from optparse import OptionParser
+
+tmpeggs = tempfile.mkdtemp()
+
+usage = '''\
+[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
+
+Bootstraps a buildout-based project.
+
+Simply run this script in a directory containing a buildout.cfg, using the
+Python that you want bin/buildout to use.
+
+Note that by using --find-links to point to local resources, you can keep 
+this script from going over the network.
+'''
+
+parser = OptionParser(usage=usage)
+parser.add_option("-v", "--version", help="use a specific zc.buildout version")
+
+parser.add_option("-t", "--accept-buildout-test-releases",
+                  dest='accept_buildout_test_releases',
+                  action="store_true", default=False,
+                  help=("Normally, if you do not specify a --version, the "
+                        "bootstrap script and buildout gets the newest "
+                        "*final* versions of zc.buildout and its recipes and "
+                        "extensions for you.  If you use this flag, "
+                        "bootstrap and buildout will get the newest releases "
+                        "even if they are alphas or betas."))
+parser.add_option("-c", "--config-file",
+                  help=("Specify the path to the buildout configuration "
+                        "file to be used."))
+parser.add_option("-f", "--find-links",
+                  help=("Specify a URL to search for buildout releases"))
+parser.add_option("--allow-site-packages",
+                  action="store_true", default=False,
+                  help=("Let bootstrap.py use existing site packages"))
+
+
+options, args = parser.parse_args()
+
+######################################################################
+# load/install setuptools
+
+try:
+    if options.allow_site_packages:
+        import setuptools
+        import pkg_resources
+    from urllib.request import urlopen
+except ImportError:
+    from urllib2 import urlopen
+
+ez = {}
+exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
+
+if not options.allow_site_packages:
+    # ez_setup imports site, which adds site packages
+    # this will remove them from the path to ensure that incompatible versions 
+    # of setuptools are not in the path
+    import site
+    # inside a virtualenv, there is no 'getsitepackages'. 
+    # We can't remove these reliably
+    if hasattr(site, 'getsitepackages'):
+        for sitepackage_path in site.getsitepackages():
+            sys.path[:] = [x for x in sys.path if sitepackage_path not in x]
+
+setup_args = dict(to_dir=tmpeggs, download_delay=0)
+ez['use_setuptools'](**setup_args)
+import setuptools
+import pkg_resources
+
+# This does not (always?) update the default working set.  We will
+# do it.
+for path in sys.path:
+    if path not in pkg_resources.working_set.entries:
+        pkg_resources.working_set.add_entry(path)
+
+######################################################################
+# Install buildout
+
+ws = pkg_resources.working_set
+
+cmd = [sys.executable, '-c',
+       'from setuptools.command.easy_install import main; main()',
+       '-mZqNxd', tmpeggs]
+
+find_links = os.environ.get(
+    'bootstrap-testing-find-links',
+    options.find_links or
+    ('http://downloads.buildout.org/'
+     if options.accept_buildout_test_releases else None)
+    )
+if find_links:
+    cmd.extend(['-f', find_links])
+
+setuptools_path = ws.find(
+    pkg_resources.Requirement.parse('setuptools')).location
+
+requirement = 'zc.buildout'
+version = options.version
+if version is None and not options.accept_buildout_test_releases:
+    # Figure out the most recent final version of zc.buildout.
+    import setuptools.package_index
+    _final_parts = '*final-', '*final'
+
+    def _final_version(parsed_version):
+        for part in parsed_version:
+            if (part[:1] == '*') and (part not in _final_parts):
+                return False
+        return True
+    index = setuptools.package_index.PackageIndex(
+        search_path=[setuptools_path])
+    if find_links:
+        index.add_find_links((find_links,))
+    req = pkg_resources.Requirement.parse(requirement)
+    if index.obtain(req) is not None:
+        best = []
+        bestv = None
+        for dist in index[req.project_name]:
+            distv = dist.parsed_version
+            if _final_version(distv):
+                if bestv is None or distv > bestv:
+                    best = [dist]
+                    bestv = distv
+                elif distv == bestv:
+                    best.append(dist)
+        if best:
+            best.sort()
+            version = best[-1].version
+if version:
+    requirement = '=='.join((requirement, version))
+cmd.append(requirement)
+
+import subprocess
+if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0:
+    raise Exception(
+        "Failed to execute command:\n%s" % repr(cmd)[1:-1])
+
+######################################################################
+# Import and run buildout
+
+ws.add_entry(tmpeggs)
+ws.require(requirement)
+import zc.buildout.buildout
+
+if not [a for a in args if '=' not in a]:
+    args.append('bootstrap')
+
+# if -c was provided, we push it back into args for buildout' main function
+if options.config_file is not None:
+    args[0:0] = ['-c', options.config_file]
+
+zc.buildout.buildout.main(args)
+shutil.rmtree(tmpeggs)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/buildout.cfg	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,47 @@
+[buildout]
+eggs-directory = /var/local/eggs
+include-site-packages = false
+extends = http://download.ztfy.org/webapp/ztfy.webapp.dev.cfg
+versions = versions
+newest = false
+allow-picked-versions = false
+src = src
+develop = .
+          /var/local/src/ztfy-bb/ztfy.base
+          /var/local/src/ztfy-bb/ztfy.extfile
+          /var/local/src/ztfy-bb/ztfy.file
+          /var/local/src/ztfy-bb/ztfy.jqueryui
+          /var/local/src/ztfy-bb/ztfy.utils
+parts = package i18n pyflakes pyflakesrun test
+
+[package]
+recipe = zc.recipe.egg
+eggs = ztfy.baseskin
+
+[i18n]
+recipe = z3c.recipe.i18n:i18n
+eggs = ${package:eggs}
+       z3c.recipe.i18n
+packages = ztfy.baseskin
+domain = ztfy.baseskin
+output = src/ztfy/baseskin/locales
+zcml = <include file="configure.zcml" />
+
+[pyflakes]
+recipe = zc.recipe.egg
+eggs = pyflakes
+scripts = pyflakes
+entry-points = pyflakes=pyflakes.scripts.pyflakes:main
+initialization = if not sys.argv[1:]: sys.argv[1:] = ["${buildout:src}"]
+
+[pyflakesrun]
+recipe = collective.recipe.cmd
+on_install = true
+cmds = ${buildout:directory}/bin/${pyflakes:scripts}
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = ztfy.baseskin [test]
+
+[versions]
+ztfy.baseskin = 0.1.0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/CONTRIBUTORS.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,1 @@
+- Thierry Florac <tflorac@ulthar.net> - Author
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/HISTORY.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,6 @@
+HISTORY
+=======
+
+0.1.0
+-----
+ - first release
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/LICENSE.ZPL	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,44 @@
+Zope Public License (ZPL) Version 2.1
+
+A copyright notice accompanies this license document that identifies the
+copyright holders.
+
+This license has been certified as open source. It has also been designated as
+GPL compatible by the Free Software Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    1. Redistributions in source code must retain the accompanying copyright 
+       notice, this list of conditions, and the following disclaimer. 
+
+    2. Redistributions in binary form must reproduce the accompanying 
+       copyright notice, this list of conditions, and the following 
+       disclaimer in the documentation and/or other materials provided with 
+       the distribution.
+
+    3. Names of the copyright holders must not be used to endorse or promote
+       products derived from this software without prior written permission 
+       from the copyright holders.
+
+    4. The right to distribute this software or to use it for any purpose does 
+       not give you the right to use Servicemarks (sm) or Trademarks (tm) of the 
+       copyright holders. Use of them is covered by separate agreement with the 
+       copyright holders.
+
+    5. If any files are modified, you must cause the modified files to carry
+       prominent notices stating that you changed the files and the date of any 
+       change.
+
+Disclaimer
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/LICENSE.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,9 @@
+ztfy.baseskin Copyright (c) 2014 Thierry Florac.
+All Rights Reserved.
+
+This software is subject to the provisions of the Zope Public License,
+Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+FOR A PARTICULAR PURPOSE.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/README.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,12 @@
+.. contents::
+
+Introduction
+============
+
+ZTFY.baseskin is a base package for all ZTFY's skin-related packages.
+
+It mainly contains:
+ - a whole set of skin-related interfaces shared by all skins
+ - a base layer
+ - a small set of forms, buttons and viewlets interfaces, classes and adapters
+   shared by all skin-related packages.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,57 @@
+from setuptools import setup, find_packages
+import os
+
+DOCS = os.path.join(os.path.dirname(__file__),
+                    'docs')
+
+README = os.path.join(DOCS, 'README.txt')
+HISTORY = os.path.join(DOCS, 'HISTORY.txt')
+CONTRIBS = os.path.join(DOCS, 'CONTRIBUTORS.txt')
+
+version = '0.1.0'
+long_description = open(README).read() + '\n\n' + \
+                   open(CONTRIBS).read() + '\n\n' + \
+                   open(HISTORY).read()
+
+tests_require = [
+    'zope.testing',
+]
+
+setup(name='ztfy.baseskin',
+      version=version,
+      description="ZTFY base skin package",
+      long_description=long_description,
+      # Get more strings from
+      # http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[
+        "Programming Language :: Python",
+        ],
+      keywords='ZTFY skin',
+      author='Thierry Florac',
+      author_email='tflorac@ulthar.net',
+      url='http://hg.ztfy.org/ztfy.baseskin',
+      license='zpl',
+      packages=find_packages('src'),
+      package_dir={'': 'src'},
+      namespace_packages=['ztfy'],
+      include_package_data=True,
+      package_data={'': ['*.zcml', '*.txt', '*.pt', '*.pot', '*.po', '*.mo', '*.png', '*.gif', '*.jpeg', '*.jpg', '*.css', '*.js']},
+      zip_safe=False,
+      tests_require=tests_require,
+      extras_require=dict(test=tests_require),
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+          'z3c.form',
+          'z3c.formui',
+          'z3c.jsonrpc',
+          'z3c.layer.pagelet',
+          'zope.component',
+          'zope.i18nmessageid',
+          'zope.interface',
+          'ztfy.base',
+          'ztfy.utils',
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy.baseskin.egg-info/PKG-INFO	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,34 @@
+Metadata-Version: 1.1
+Name: ztfy.baseskin
+Version: 0.1.0
+Summary: ZTFY base skin package
+Home-page: http://hg.ztfy.org/ztfy.baseskin
+Author: Thierry Florac
+Author-email: tflorac@ulthar.net
+License: zpl
+Description: .. contents::
+        
+        Introduction
+        ============
+        
+        ZTFY.baseskin is a base package for all ZTFY's skin-related packages.
+        
+        It mainly contains:
+         - a whole set of skin-related interfaces shared by all skins
+         - a base layer
+         - a small set of forms, buttons and viewlets interfaces, classes and adapters
+           shared by all skin-related packages.
+        
+        - Thierry Florac <tflorac@ulthar.net> - Author
+        
+        
+        HISTORY
+        =======
+        
+        0.1.0
+        -----
+         - first release
+        
+Keywords: ZTFY skin
+Platform: UNKNOWN
+Classifier: Programming Language :: Python
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy.baseskin.egg-info/SOURCES.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,45 @@
+MANIFEST.in
+setup.py
+docs/CONTRIBUTORS.txt
+docs/HISTORY.txt
+docs/LICENSE.ZPL
+docs/LICENSE.txt
+docs/README.txt
+src/ztfy/__init__.py
+src/ztfy.baseskin.egg-info/PKG-INFO
+src/ztfy.baseskin.egg-info/SOURCES.txt
+src/ztfy.baseskin.egg-info/dependency_links.txt
+src/ztfy.baseskin.egg-info/entry_points.txt
+src/ztfy.baseskin.egg-info/namespace_packages.txt
+src/ztfy.baseskin.egg-info/not-zip-safe
+src/ztfy.baseskin.egg-info/requires.txt
+src/ztfy.baseskin.egg-info/top_level.txt
+src/ztfy/baseskin/__init__.py
+src/ztfy/baseskin/configure.zcml
+src/ztfy/baseskin/form.py
+src/ztfy/baseskin/layer.py
+src/ztfy/baseskin/metas.py
+src/ztfy/baseskin/metas.zcml
+src/ztfy/baseskin/schema.py
+src/ztfy/baseskin/skin.py
+src/ztfy/baseskin/viewlet.py
+src/ztfy/baseskin/widget.py
+src/ztfy/baseskin/doctests/README.txt
+src/ztfy/baseskin/interfaces/__init__.py
+src/ztfy/baseskin/interfaces/container.py
+src/ztfy/baseskin/interfaces/form.py
+src/ztfy/baseskin/interfaces/metas.py
+src/ztfy/baseskin/locales/ztfy.baseskin.pot
+src/ztfy/baseskin/locales/en/LC_MESSAGES/ztfy.baseskin.mo
+src/ztfy/baseskin/locales/en/LC_MESSAGES/ztfy.baseskin.po
+src/ztfy/baseskin/locales/en/LC_MESSAGES/ztfy.baseskin.po~
+src/ztfy/baseskin/locales/fr/LC_MESSAGES/ztfy.baseskin.mo
+src/ztfy/baseskin/locales/fr/LC_MESSAGES/ztfy.baseskin.po
+src/ztfy/baseskin/locales/fr/LC_MESSAGES/ztfy.baseskin.po~
+src/ztfy/baseskin/tal/__init__.py
+src/ztfy/baseskin/tal/api.py
+src/ztfy/baseskin/tal/configure.zcml
+src/ztfy/baseskin/tal/interfaces.py
+src/ztfy/baseskin/tests/__init__.py
+src/ztfy/baseskin/tests/test_docs.py
+src/ztfy/baseskin/tests/test_docstrings.py
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy.baseskin.egg-info/dependency_links.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,1 @@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy.baseskin.egg-info/entry_points.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,3 @@
+
+      # -*- Entry points: -*-
+      
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy.baseskin.egg-info/namespace_packages.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,1 @@
+ztfy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy.baseskin.egg-info/not-zip-safe	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,1 @@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy.baseskin.egg-info/requires.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,13 @@
+setuptools
+z3c.form
+z3c.formui
+z3c.jsonrpc
+z3c.layer.pagelet
+zope.component
+zope.i18nmessageid
+zope.interface
+ztfy.base
+ztfy.utils
+
+[test]
+zope.testing
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy.baseskin.egg-info/top_level.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,1 @@
+ztfy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/__init__.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,1 @@
+__import__('pkg_resources').declare_namespace(__name__)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/__init__.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,12 @@
+# Copyright (c) 2008-2012 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+
+
+from zope.i18nmessageid import MessageFactory
+_ = MessageFactory('ztfy.baseskin')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/configure.zcml	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,81 @@
+<configure
+	xmlns="http://namespaces.zope.org/zope"
+	xmlns:browser="http://namespaces.zope.org/browser"
+	xmlns:i18n="http://namespaces.zope.org/i18n"
+	i18n_domain="ztfy.baseskin">
+
+	<i18n:registerTranslations directory="locales" />
+
+	<include file="metas.zcml" />
+
+	<!-- Skinnables traversal -->
+	<subscriber handler=".skin.handleSkinTraversal" />
+
+	<!-- Sub-packages includes -->
+	<include package=".tal" />
+
+	<!-- Forms viewlets managers -->
+	<browser:viewletManager
+		name="form_prefix"
+		class=".viewlet.FormPrefixViewletManager"
+		permission="zope.View"
+		layer=".layer.IBaseSkinLayer" />
+
+	<browser:viewletManager
+		name="widgets_prefix"
+		class=".viewlet.WidgetsPrefixViewletManager"
+		permission="zope.View"
+		layer=".layer.IBaseSkinLayer" />
+
+	<browser:viewletManager
+		name="widgets_suffix"
+		class=".viewlet.WidgetsSuffixViewletManager"
+		permission="zope.View"
+		layer=".layer.IBaseSkinLayer" />
+
+	<browser:viewletManager
+		name="form_suffix"
+		class=".viewlet.FormSuffixViewletManager"
+		permission="zope.View"
+		layer=".layer.IBaseSkinLayer" />
+
+
+	<!-- Custom widgets -->
+	<adapter
+		factory=".widget.ResetFieldWidget" />
+
+	<adapter
+		factory=".widget.ResetButtonAction"
+		provides="z3c.form.interfaces.IButtonAction" />
+
+	<adapter
+		factory=".widget.CloseFieldWidget" />
+
+	<adapter
+		factory=".widget.CloseButtonAction"
+		provides="z3c.form.interfaces.IButtonAction" />
+
+
+	<!-- Text renderers views -->
+	<browser:view
+		name=""
+		for="zope.app.renderer.plaintext.IPlainTextSource"
+		class="zope.app.renderer.plaintext.PlainTextToHTMLRenderer"
+		layer=".layer.IBaseSkinLayer"
+		permission="zope.Public" />
+
+	<browser:view
+		name=""
+		for="zope.app.renderer.stx.IStructuredTextSource"
+		class="zope.app.renderer.stx.StructuredTextToHTMLRenderer"
+		layer=".layer.IBaseSkinLayer"
+		permission="zope.Public" />
+
+	<browser:view
+		name=""
+		for="zope.app.renderer.rest.IReStructuredTextSource"
+		class="zope.app.renderer.rest.ReStructuredTextToHTMLRenderer"
+		layer=".layer.IBaseSkinLayer"
+		permission="zope.Public" />
+
+</configure>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/doctests/README.txt	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,3 @@
+ztfy.baseskin doctests
+======================
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/form.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2012 Thierry Florac <tflorac AT onf.fr>
+# All Rights Reserved.
+#
+
+
+# import standard packages
+
+# import Zope3 interfaces
+
+# import local interfaces
+
+# import Zope3 packages
+from zope.interface import implements
+from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
+
+# import local packages
+from ztfy.baseskin.interfaces.form import IFormObjectCreatedEvent, IFormObjectModifiedEvent
+
+
+class FormObjectCreatedEvent(ObjectCreatedEvent):
+    """Form object created event"""
+
+    implements(IFormObjectCreatedEvent)
+
+    def __init__(self, object, view):
+        self.object = object
+        self.view = view
+
+
+class FormObjectModifiedEvent(ObjectModifiedEvent):
+    """Form object modified event"""
+
+    implements(IFormObjectModifiedEvent)
+
+    def __init__(self, object, view, *descriptions):
+        ObjectModifiedEvent.__init__(self, object, *descriptions)
+        self.view = view
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/interfaces/__init__.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,129 @@
+#
+# Copyright (c) 2008-2014 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = "restructuredtext"
+
+# import standard packages
+
+# import Zope3 interfaces
+
+# import local interfaces
+
+# import Zope3 packages
+from zope.interface import Interface, Attribute
+from zope.schema import TextLine, Password
+
+# import local packages
+
+from ztfy.baseskin import _
+
+
+#
+# Skinning interfaces
+#
+
+class ISkinnable(Interface):
+    """Base skinnable content interface
+
+    This interface is used for any object managing a skin.
+    An adapter is used during traversal t automatically
+    apply selected skin.
+    """
+
+    def getSkin(self):
+        """Get skin name matching current context"""
+
+
+#
+# Default view interfaces
+#
+
+class IDefaultView(Interface):
+    """Interface used to get object's default view"""
+
+    viewname = TextLine(title=_("View name"),
+                        description=_("Name of the default view matching object, request and (optionally) current view"),
+                        required=True,
+                        default=u'@@index.html')
+
+    def getAbsoluteURL(self):
+        """Get full absolute URL of the default view"""
+
+
+class IContainedDefaultView(IDefaultView):
+    """Interface used to get object's default view while displayed inside a container"""
+
+
+#
+# Dialogs interfaces
+#
+
+class IDialog(Interface):
+    """Base interface for AJAX dialogs"""
+
+    dialog_class = Attribute(_("Default dialog CSS class"))
+
+    resources = Attribute(_("List of resources needed by this dialog"))
+
+
+class IDialogTitle(Interface):
+    """Dialog title getter interface"""
+
+    def getTitle(self):
+        """Get dialog title"""
+
+
+#
+# Base front-office views
+#
+
+class IBaseViewlet(Interface):
+    """Marker interface for base viewlets"""
+
+
+class IBaseIndexView(Interface):
+    """Marker interface for base index view"""
+
+
+#
+# Presentation management interfaces
+#
+
+class IBasePresentationInfo(Interface):
+    """Base interface for presentation infos"""
+
+
+class IPresentationForm(Interface):
+    """Marker interface for default presentation edit form"""
+
+
+class IPresentationTarget(Interface):
+    """Interface used inside skin-related edit forms"""
+
+    target_interface = Attribute(_("Presentation form target interface"))
+
+
+#
+# Login form attributes
+#
+
+class ILoginFormFields(Interface):
+    """Login form fields interface"""
+
+    username = TextLine(title=_("login-field", "Login"),
+                        required=True)
+
+    password = Password(title=_("password-field", "Password"),
+                        required=True)
+
+    came_from = TextLine(title=_("came-from", "Original address"),
+                         required=False)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/interfaces/container.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,91 @@
+#
+# Copyright (c) 2008-2014 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = "restructuredtext"
+
+# import standard packages
+
+# import Zope3 interfaces
+
+# import local interfaces
+
+# import Zope3 packages
+from zope.interface import Interface
+from zope.schema import Text
+
+# import local packages
+
+from ztfy.baseskin import _
+
+
+#
+# Main container interfaces
+#
+
+class IContainerBaseView(Interface):
+    """Marker interface for container base view"""
+
+
+class IOrderedContainerBaseView(Interface):
+    """Marker interface for ordered container based view"""
+
+
+class IOrderedContainerSorterColumn(Interface):
+    """Marker interface for container sorter column"""
+
+
+#
+# Container columns interfaces
+#
+
+class IIdColumn(Interface):
+    """Marker interface for ID column"""
+
+
+class INameColumn(Interface):
+    """Marker interface for name column"""
+
+
+class ITitleColumn(Interface):
+    """Marker interface for title column"""
+
+
+class IStatusColumn(Interface):
+    """Marker interface for status column"""
+
+
+class IActionsColumn(Interface):
+    """Marker interface for actions column"""
+
+
+class IContainerTableViewTitleCell(Interface):
+    """Container table view title cell adapter"""
+
+    prefix = Text(title=_("Text displayed before title link"))
+
+    before = Text(title=_("Text displayed before cell main text"))
+
+    after = Text(title=_("Text displayed after cell main text"))
+
+    suffix = Text(title=_("Text displayed after title link"))
+
+
+class IContainerTableViewStatusCell(Interface):
+    """Container table view status cell interface"""
+
+    content = Text(title=_("Content of status cell"))
+
+
+class IContainerTableViewActionsCell(Interface):
+    """Container table view actions cell interface"""
+
+    content = Text(title=_("Content of actions cell"))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/interfaces/form.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,304 @@
+#
+# Copyright (c) 2008-2014 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = "restructuredtext"
+
+# import standard packages
+
+# import Zope3 interfaces
+from z3c.form.interfaces import INPUT_MODE, IWidget, ISubForm, ISubmitWidget
+from zope.component.interfaces import IObjectEvent
+from zope.lifecycleevent.interfaces import IObjectCreatedEvent, IObjectModifiedEvent
+from zope.viewlet.interfaces import IViewletManager, IViewlet
+
+# import local interfaces
+
+# import Zope3 packages
+from zope.interface import Interface, Attribute
+from zope.schema import Bool, TextLine, Choice, List, Dict, Object
+
+# import local packages
+
+from ztfy.baseskin import _
+
+
+#
+# Custom widgets interfaces
+#
+
+class IResetWidget(ISubmitWidget):
+    """Reset button widget interface"""
+
+
+class ICloseWidget(ISubmitWidget):
+    """Close button widget interface"""
+
+
+#
+# Custom forms interfaces
+#
+
+def checkSubmitButton(form):
+    """Check form and widgets mode before displaying submit button"""
+    if form.mode != INPUT_MODE:
+        return False
+    for widget in form.widgets.values():
+        if widget.mode == INPUT_MODE:
+            return True
+    if IForm.providedBy(form):
+        for subform in form.subforms:
+            for widget in subform.widgets.values():
+                if widget.mode == INPUT_MODE:
+                    return True
+
+
+class IWidgetsGroup(Interface):
+    """Form widgets group interface"""
+
+    id = TextLine(title=_("Group ID"),
+                  required=False)
+
+    css_class = TextLine(title=_("CSS class"),
+                         required=False)
+
+    legend = TextLine(title=_("Group legend"),
+                      required=False)
+
+    help = TextLine(title=_("Group help"),
+                    required=False)
+
+    widgets = List(title=_("Group's widgets list"),
+                   value_type=Object(schema=IWidget))
+
+    switch = Bool(title=_("Switchable group?"),
+                  required=True,
+                  default=False)
+
+    checkbox_switch = Bool(title=_("Group switched via checkbox?"),
+                           required=True,
+                           default=False)
+
+    checkbox_field = TextLine(title=_("Field name matching switch checkbox?"),
+                              required=False)
+
+    checkbox_widget = Object(schema=IWidget,
+                             required=False)
+
+    checkbox_on = Attribute(_("Checkbox on?"))
+
+    hide_if_empty = Bool(title=_("Hide group if empty?"),
+                         description=_("""If 'Yes', a switchable group containing only """
+                                       """widgets with default values is hidden"""),
+                         required=True,
+                         default=False)
+
+    visible = Attribute(_("Visible group?"))
+
+    switchable = Attribute(_("Switchable group?"))
+
+
+class IBaseForm(Interface):
+    """Marker interface for any form"""
+
+
+class IGroupsBasedForm(IBaseForm):
+    """Groups based form"""
+
+    groups = Attribute(_("Form groups"))
+
+    def addGroup(self, group):
+        """Add given group to form"""
+
+
+class IForm(IBaseForm):
+    """Base form interface"""
+
+    title = TextLine(title=_("Form title"))
+
+    legend = TextLine(title=_("Form legend"),
+                      required=False)
+
+    subforms = List(title=_("Sub-forms"),
+                    value_type=Object(schema=ISubForm),
+                    required=False)
+
+    subforms_legend = TextLine(title=_("Subforms legend"),
+                               required=False)
+
+    tabforms = List(title=_("Tab-forms"),
+                    value_type=Object(schema=ISubForm),
+                    required=False)
+
+    autocomplete = Choice(title=_("Auto-complete"),
+                          values=('on', 'off'),
+                          default='on')
+
+    label_css_class = TextLine(title=_("Labels CSS class"),
+                               required=False,
+                               default=u'control-label col-md-3')
+
+    input_css_class = TextLine(title=_("Inputs CSS class"),
+                               required=False,
+                               default=u'col-md-9')
+
+    display_hints_on_widgets = Bool(title=_("Display hints on input widgets?"),
+                                    required=True,
+                                    default=False)
+
+    handle_upload = Bool(title=_("Handle uploads in form?"),
+                         description=_("Set to true when form handle uploads to get progress bar"),
+                         required=True,
+                         default=False)
+
+    callbacks = Dict(title=_("Widgets validation callbacks"),
+                     key_type=TextLine(),
+                     value_type=TextLine(),
+                     required=False)
+
+    def isDialog(self):
+        """Check to know if current form is in a modal dialog"""
+
+    def getForms(self):
+        """Get full list of main form and subforms"""
+
+    def createSubForms(self):
+        """Initialize sub-forms"""
+
+    def createTabForms(self):
+        """Initialize tab-forms"""
+
+    def getWidgetCallback(self, widget):
+        """Get submit callback associated with a given widget"""
+
+    def updateContent(self, object, data):
+        """Update given object with form data"""
+
+    def getSubmitOutput(self, writer, changes):
+        """Get submit output"""
+
+
+class IAJAXForm(IForm):
+    """AJAX form interface"""
+
+    handler = TextLine(title=_("Form AJAX handler"),
+                       description=_("Relative URL of AJAX handler"),
+                       required=False)
+
+    data_type = Choice(title=_("Form AJAX data type"),
+                       description=_(""),
+                       required=False,
+                       values=('json', 'jsonp', 'text', 'html', 'xml', 'script'))
+
+    form_options = Dict(title=_("Form AJAX data options"),
+                        required=False)
+
+    callback = TextLine(title=_("Submit callback"),
+                        description=_("Name of a custom form submit callback"),
+                        required=False)
+
+    def getFormOptions(self):
+        """Get custom AJAX POST data"""
+
+    def getAjaxErrors(self):
+        """Get errors associated with their respective widgets in a JSON dictionary"""
+
+
+class IInnerSubForm(ISubForm):
+    """Inner subform marker interface"""
+
+
+class IInnerTabForm(ISubForm):
+    """Inner tabform marker interface"""
+
+    tabLabel = TextLine(title=_("Tab label"),
+                        required=True)
+
+
+class IViewletsBasedForm(IForm):
+    """Viewlets based form interface"""
+
+    managers = List(title=_("Names list of viewlets managers included in this form"),
+                    value_type=TextLine(),
+                    required=True)
+
+
+class ISubFormViewlet(IViewlet):
+    """Sub-form viewlet interface"""
+
+    legend = Attribute(_("Sub-form legend"))
+
+    switchable = Attribute(_("Can the subform be hidden ?"))
+
+    visible = Attribute(_("Is the subform initially visible ?"))
+
+    callbacks = Dict(title=_("Widgets callbacks"),
+                     key_type=TextLine(),
+                     value_type=TextLine())
+
+    def getWidgetCallback(self, widget):
+        """Get submit callback associated with a given widget"""
+
+
+class ICustomExtractSubForm(ISubForm):
+    """SubForm interface with custom extract method"""
+
+    def extract(self):
+        """Extract data and errors from input request"""
+
+
+class ICustomUpdateSubForm(ISubForm):
+    """SubForm interface with custom update method"""
+
+    def updateContent(self, object, data):
+        """Update custom content with given data"""
+
+
+#
+# Default form content providers
+#
+
+class IFormViewletsManager(IViewletManager):
+    """Base forms viewlets manager interface"""
+
+
+class IFormPrefixViewletsManager(IFormViewletsManager):
+    """Form prefix viewlets manager interface"""
+
+
+class IWidgetsPrefixViewletsManager(IFormViewletsManager):
+    """Form widgets prefix viewlets manager interface"""
+
+
+class IWidgetsSuffixViewletsManager(IFormViewletsManager):
+    """Form widgets suffix viewlets manager interface"""
+
+
+class IFormSuffixViewletsManager(IFormViewletsManager):
+    """Form suffix viewlets manager interface"""
+
+
+#
+# Custom events interfaces
+#
+
+class IViewObjectEvent(IObjectEvent):
+    """View object event interface"""
+
+    view = Attribute(_("View in which event was fired"))
+
+
+class IFormObjectCreatedEvent(IObjectCreatedEvent, IViewObjectEvent):
+    """Object added event notify by form after final object creation"""
+
+
+class IFormObjectModifiedEvent(IObjectModifiedEvent, IViewObjectEvent):
+    """Form object modified event interface"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/interfaces/metas.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,87 @@
+### -*- coding: utf-8 -*- ####################################################
+##############################################################################
+#
+# Copyright (c) 2008-2013 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+__docformat__ = "restructuredtext"
+
+# import standard packages
+
+# import Zope3 interfaces
+
+# import local interfaces
+
+# import Zope3 packages
+from zope.interface import Interface, Attribute
+from zope.schema import List, Object
+
+# import local packages
+
+from ztfy.baseskin import _
+
+
+class IBaseMeta(Interface):
+    """Base meta header interface"""
+
+    def render(self):
+        """Render given meta header"""
+
+
+class IHTTPEquivMetaHeader(IBaseMeta):
+    """HTTP-Equiv meta header interface"""
+
+    http_equiv = Attribute(_("HTTP equiv header"))
+
+    value = Attribute(_("Meta content value"))
+
+
+class IContentMetaHeader(IBaseMeta):
+    """Content meta header interface"""
+
+    name = Attribute(_("Meta name"))
+
+    value = Attribute(_("Meta content value"))
+
+
+class IPropertyMetaHeader(IBaseMeta):
+    """Property meta header interface"""
+
+    property = Attribute(_("Meta property"))
+
+    value = Attribute(_("Meta content value"))
+
+
+class ILinkMetaHeader(IBaseMeta):
+    """Link meta header interface"""
+
+    rel = Attribute(_("Meta rel attribute"))
+
+    type = Attribute(_("Meta type attribute"))
+
+    href = Attribute(_("Meta link target"))
+
+
+class IContentMetasHeaders(Interface):
+    """Content metas headers interface"""
+
+    metas = List(title=_("Metas list"),
+                 description=_("Full list of metas associated with this content"),
+                 value_type=Object(schema=IContentMetaHeader))
+
+
+class IPageMetasHeaders(Interface):
+    """Full list of metas headers for given content"""
+
+    metas = List(title=_("Metas list"),
+                 description=_("Full list of metas associated with this content"),
+                 value_type=Object(schema=IContentMetaHeader))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/layer.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2012 Thierry Florac <tflorac AT onf.fr>
+# All Rights Reserved.
+#
+
+
+# import standard packages
+
+# import Zope3 interfaces
+from z3c.form.interfaces import IFormLayer
+from z3c.formui.interfaces import IFormUILayer
+from z3c.jsonrpc.layer import IJSONRPCLayer
+from z3c.layer.pagelet import IPageletBrowserLayer
+
+# import local interfaces
+
+# import Zope3 packages
+
+# import local packages
+
+
+class IBaseSkinLayer(IFormLayer, IFormUILayer, IPageletBrowserLayer, IJSONRPCLayer):
+    """Base skin layer"""
Binary file src/ztfy/baseskin/locales/en/LC_MESSAGES/ztfy.baseskin.mo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/locales/en/LC_MESSAGES/ztfy.baseskin.po	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,24 @@
+##############################################################################
+#
+# Copyright (c) 2003-2004 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+msgid ""
+msgstr ""
+"Project-Id-Version: Meaningless\n"
+"POT-Creation-Date: Sun May 11 01:41:23 2014\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Zope 3 Developers <zope-dev@zope.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: zope/app/locales/extract.py\n"
Binary file src/ztfy/baseskin/locales/fr/LC_MESSAGES/ztfy.baseskin.mo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/locales/fr/LC_MESSAGES/ztfy.baseskin.po	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,281 @@
+##############################################################################
+#
+# Copyright (c) 2003-2004 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+msgid ""
+msgstr ""
+"Project-Id-Version: Meaningless\n"
+"POT-Creation-Date: Sun May 11 01:41:23 2014\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Zope 3 Developers <zope-dev@zope.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: zope/app/locales/extract.py\n"
+
+#: ztfy/baseskin/interfaces/__init__.py:112
+msgid "Presentation form target interface"
+msgstr "Interface de la cible"
+
+#. Default: "Login"
+#: ztfy/baseskin/interfaces/__init__.py:122
+msgid "login-field"
+msgstr "Code utilisateur"
+
+#. Default: "Password"
+#: ztfy/baseskin/interfaces/__init__.py:125
+msgid "password-field"
+msgstr "Mot de passe"
+
+#. Default: "Original address"
+#: ztfy/baseskin/interfaces/__init__.py:128
+msgid "came-from"
+msgstr "Adresse d'origine"
+
+#: ztfy/baseskin/interfaces/__init__.py:53
+msgid "View name"
+msgstr "Nom de la vue"
+
+#: ztfy/baseskin/interfaces/__init__.py:54
+msgid ""
+"Name of the default view matching object, request and (optionally) current "
+"view"
+msgstr ""
+"Nom de la vue par défaut correspondant à l'objet, à la requête et (éventuellement) "
+"à la vue en cours"
+
+#: ztfy/baseskin/interfaces/__init__.py:73
+msgid "Default dialog CSS class"
+msgstr "Classe CSS par défaut du dialogue"
+
+#: ztfy/baseskin/interfaces/__init__.py:75
+msgid "List of resources needed by this dialog"
+msgstr "Liste des ressources nécessaires à ce dialogue"
+
+#: ztfy/baseskin/interfaces/container.py:73
+msgid "Text displayed before title link"
+msgstr "Texte affiché avant le lien sur le titre"
+
+#: ztfy/baseskin/interfaces/container.py:75
+msgid "Text displayed before cell main text"
+msgstr "Texte affiché avant le texte principal de la cellule"
+
+#: ztfy/baseskin/interfaces/container.py:77
+msgid "Text displayed after cell main text"
+msgstr "Texte affiché après le texte principal de la cellule"
+
+#: ztfy/baseskin/interfaces/container.py:79
+msgid "Text displayed after title link"
+msgstr "Texte affiché après le lien sur le titre"
+
+#: ztfy/baseskin/interfaces/container.py:85
+msgid "Content of status cell"
+msgstr "Contenu de la cellule de statut"
+
+#: ztfy/baseskin/interfaces/container.py:91
+msgid "Content of actions cell"
+msgstr "Contenu de la cellule d'actions"
+
+#: ztfy/baseskin/interfaces/form.py:104
+msgid "Visible group?"
+msgstr "Groupe visible ?"
+
+#: ztfy/baseskin/interfaces/form.py:116
+msgid "Form groups"
+msgstr "Groupes du formulaire"
+
+#: ztfy/baseskin/interfaces/form.py:125
+msgid "Form title"
+msgstr "Titre du formulaire"
+
+#: ztfy/baseskin/interfaces/form.py:127
+msgid "Form legend"
+msgstr "Légende du formulaire"
+
+#: ztfy/baseskin/interfaces/form.py:130
+msgid "Sub-forms"
+msgstr "Sous-formulaires"
+
+#: ztfy/baseskin/interfaces/form.py:134
+msgid "Subforms legend"
+msgstr "Légende des sous-formulaires"
+
+#: ztfy/baseskin/interfaces/form.py:137
+msgid "Tab-forms"
+msgstr "Sous-onglets"
+
+#: ztfy/baseskin/interfaces/form.py:141
+msgid "Auto-complete"
+msgstr "Auto-complétion"
+
+#: ztfy/baseskin/interfaces/form.py:145
+msgid "Labels CSS class"
+msgstr "Classe CSS des libellés"
+
+#: ztfy/baseskin/interfaces/form.py:149
+msgid "Inputs CSS class"
+msgstr "Classe CSS des contrôles"
+
+#: ztfy/baseskin/interfaces/form.py:153
+msgid "Display hints on input widgets?"
+msgstr "Afficher les info-bulles d'aide sur les champs de saisie"
+
+#: ztfy/baseskin/interfaces/form.py:157
+msgid "Handle uploads in form?"
+msgstr "Ce formulaire gère-t-il un téléchargement ?"
+
+#: ztfy/baseskin/interfaces/form.py:158
+msgid "Set to true when form handle uploads to get progress bar"
+msgstr "Positionné à la valeur 'True' lorsque le formulaire dispose de contrôles de dépôt "
+"de fichiers de façon à afficher une barre d'avancement"
+
+#: ztfy/baseskin/interfaces/form.py:162
+msgid "Widgets validation callbacks"
+msgstr "Fonction de rappel pour la vérification des contrôles de saisie"
+
+#: ztfy/baseskin/interfaces/form.py:192
+msgid "Form AJAX handler"
+msgstr "Gestionnaire AJAX"
+
+#: ztfy/baseskin/interfaces/form.py:193
+msgid "Relative URL of AJAX handler"
+msgstr "URL relative de prise en charge du formulaire"
+
+#: ztfy/baseskin/interfaces/form.py:196
+msgid "Form AJAX data type"
+msgstr "Type de données du POST AJAX"
+
+#: ztfy/baseskin/interfaces/form.py:201
+msgid "Form AJAX data options"
+msgstr "Options 'data' for formulaire"
+
+#: ztfy/baseskin/interfaces/form.py:204
+msgid "Submit callback"
+msgstr "Fonction de rappel de soumission du formulaire"
+
+#: ztfy/baseskin/interfaces/form.py:205
+msgid "Name of a custom form submit callback"
+msgstr "Nom d'une fonction spécifuque de soumission du formulaire"
+
+#: ztfy/baseskin/interfaces/form.py:222
+msgid "Tab label"
+msgstr "Libellé de l'onglet"
+
+#: ztfy/baseskin/interfaces/form.py:229
+msgid "Names list of viewlets managers included in this form"
+msgstr "Nom des gestionnaires de viewlets intégrés dans le formulaire"
+
+#: ztfy/baseskin/interfaces/form.py:237
+msgid "Sub-form legend"
+msgstr "Légende du sous-formulaire"
+
+#: ztfy/baseskin/interfaces/form.py:239
+msgid "Can the subform be hidden ?"
+msgstr "Le sous-formulaire peut-il être caché ?"
+
+#: ztfy/baseskin/interfaces/form.py:241
+msgid "Is the subform initially visible ?"
+msgstr "Le sous-formulaire est-il initialement visible ?"
+
+#: ztfy/baseskin/interfaces/form.py:243
+msgid "Widgets callbacks"
+msgstr "Fonctions de rappel associées aux composants"
+
+#: ztfy/baseskin/interfaces/form.py:296
+msgid "View in which event was fired"
+msgstr "Vue au sein de laquelle l'événement s'est déclenché"
+
+#: ztfy/baseskin/interfaces/form.py:67
+msgid "Group ID"
+msgstr "ID du groupe"
+
+#: ztfy/baseskin/interfaces/form.py:70
+msgid "CSS class"
+msgstr "Classe CSS"
+
+#: ztfy/baseskin/interfaces/form.py:73
+msgid "Group legend"
+msgstr "Légende du groupe"
+
+#: ztfy/baseskin/interfaces/form.py:76
+msgid "Group help"
+msgstr "Aide du groupe"
+
+#: ztfy/baseskin/interfaces/form.py:79
+msgid "Group's widgets list"
+msgstr "Liste des widgets du groupes"
+
+#: ztfy/baseskin/interfaces/form.py:82 ztfy/baseskin/interfaces/form.py:106
+msgid "Switchable group?"
+msgstr "Le groupe est-il 'basculable' ?"
+
+#: ztfy/baseskin/interfaces/form.py:86
+msgid "Group switched via checkbox?"
+msgstr "Bascule du groupe via une case à cocher ?"
+
+#: ztfy/baseskin/interfaces/form.py:90
+msgid "Field name matching switch checkbox?"
+msgstr "Nom du champ correspondant à la case à cocher"
+
+#: ztfy/baseskin/interfaces/form.py:96
+msgid "Checkbox on?"
+msgstr "Case à cocher active ?"
+
+#: ztfy/baseskin/interfaces/form.py:98
+msgid "Hide group if empty?"
+msgstr "Cacher un groupe vide ?"
+
+#: ztfy/baseskin/interfaces/form.py:99
+msgid ""
+"If 'Yes', a switchable group containing only widgets with default values is "
+"hidden"
+msgstr ""
+"Si 'Oui', un groupe 'basculable' ne contenant que des widgets avec des valeurs par "
+"défaut est masqué"
+
+#: ztfy/baseskin/interfaces/metas.py:43
+msgid "HTTP equiv header"
+msgstr "En-tête HTTP-equiv"
+
+#: ztfy/baseskin/interfaces/metas.py:45 ztfy/baseskin/interfaces/metas.py:53
+#: ztfy/baseskin/interfaces/metas.py:61
+msgid "Meta content value"
+msgstr "Valeur de la balise méta 'contenu'"
+
+#: ztfy/baseskin/interfaces/metas.py:51
+msgid "Meta name"
+msgstr "Nom de la métadonnée"
+
+#: ztfy/baseskin/interfaces/metas.py:59
+msgid "Meta property"
+msgstr "Propriété de la métadonnée"
+
+#: ztfy/baseskin/interfaces/metas.py:67
+msgid "Meta rel attribute"
+msgstr "Attribut 'rel' de la métadonnée"
+
+#: ztfy/baseskin/interfaces/metas.py:69
+msgid "Meta type attribute"
+msgstr "Type de l'attribut"
+
+#: ztfy/baseskin/interfaces/metas.py:71
+msgid "Meta link target"
+msgstr "Cible du lien"
+
+#: ztfy/baseskin/interfaces/metas.py:77 ztfy/baseskin/interfaces/metas.py:85
+msgid "Metas list"
+msgstr "Liste des métadonnées"
+
+#: ztfy/baseskin/interfaces/metas.py:78 ztfy/baseskin/interfaces/metas.py:86
+msgid "Full list of metas associated with this content"
+msgstr "Liste complète des métadonnées associées à ce contenu"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/locales/ztfy.baseskin.pot	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,277 @@
+##############################################################################
+#
+# Copyright (c) 2003-2004 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+msgid ""
+msgstr ""
+"Project-Id-Version: Meaningless\n"
+"POT-Creation-Date: Sun May 11 01:41:23 2014\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Zope 3 Developers <zope-dev@zope.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: zope/app/locales/extract.py\n"
+
+#: ztfy/baseskin/interfaces/__init__.py:112
+msgid "Presentation form target interface"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/__init__.py:122
+#. Default: "Login"
+msgid "login-field"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/__init__.py:125
+#. Default: "Password"
+msgid "password-field"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/__init__.py:128
+#. Default: "Original address"
+msgid "came-from"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/__init__.py:53
+msgid "View name"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/__init__.py:54
+msgid "Name of the default view matching object, request and (optionally) current view"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/__init__.py:73
+msgid "Default dialog CSS class"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/__init__.py:75
+msgid "List of resources needed by this dialog"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/container.py:73
+msgid "Text displayed before title link"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/container.py:75
+msgid "Text displayed before cell main text"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/container.py:77
+msgid "Text displayed after cell main text"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/container.py:79
+msgid "Text displayed after title link"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/container.py:85
+msgid "Content of status cell"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/container.py:91
+msgid "Content of actions cell"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:104
+msgid "Visible group?"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:116
+msgid "Form groups"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:125
+msgid "Form title"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:127
+msgid "Form legend"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:130
+msgid "Sub-forms"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:134
+msgid "Subforms legend"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:137
+msgid "Tab-forms"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:141
+msgid "Auto-complete"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:145
+msgid "Labels CSS class"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:149
+msgid "Inputs CSS class"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:153
+msgid "Display hints on input widgets?"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:157
+msgid "Handle uploads in form?"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:158
+msgid "Set to true when form handle uploads to get progress bar"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:162
+msgid "Widgets validation callbacks"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:192
+msgid "Form AJAX handler"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:193
+msgid "Relative URL of AJAX handler"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:196
+msgid "Form AJAX data type"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:201
+msgid "Form AJAX data options"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:204
+msgid "Submit callback"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:205
+msgid "Name of a custom form submit callback"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:222
+msgid "Tab label"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:229
+msgid "Names list of viewlets managers included in this form"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:237
+msgid "Sub-form legend"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:239
+msgid "Can the subform be hidden ?"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:241
+msgid "Is the subform initially visible ?"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:243
+msgid "Widgets callbacks"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:296
+msgid "View in which event was fired"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:67
+msgid "Group ID"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:70
+msgid "CSS class"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:73
+msgid "Group legend"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:76
+msgid "Group help"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:79
+msgid "Group's widgets list"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:82
+#: ztfy/baseskin/interfaces/form.py:106
+msgid "Switchable group?"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:86
+msgid "Group switched via checkbox?"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:90
+msgid "Field name matching switch checkbox?"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:96
+msgid "Checkbox on?"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:98
+msgid "Hide group if empty?"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/form.py:99
+msgid "If 'Yes', a switchable group containing only widgets with default values is hidden"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/metas.py:43
+msgid "HTTP equiv header"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/metas.py:45
+#: ztfy/baseskin/interfaces/metas.py:53
+#: ztfy/baseskin/interfaces/metas.py:61
+msgid "Meta content value"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/metas.py:51
+msgid "Meta name"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/metas.py:59
+msgid "Meta property"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/metas.py:67
+msgid "Meta rel attribute"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/metas.py:69
+msgid "Meta type attribute"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/metas.py:71
+msgid "Meta link target"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/metas.py:77
+#: ztfy/baseskin/interfaces/metas.py:85
+msgid "Metas list"
+msgstr ""
+
+#: ztfy/baseskin/interfaces/metas.py:78
+#: ztfy/baseskin/interfaces/metas.py:86
+msgid "Full list of metas associated with this content"
+msgstr ""
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/metas.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,131 @@
+### -*- coding: utf-8 -*- ####################################################
+##############################################################################
+#
+# Copyright (c) 2012 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+
+# import standard packages
+
+# import Zope3 interfaces
+
+# import local interfaces
+from ztfy.baseskin.interfaces.metas import IContentMetasHeaders, IContentMetaHeader, \
+    IHTTPEquivMetaHeader, IPropertyMetaHeader, \
+    ILinkMetaHeader, IPageMetasHeaders
+
+# import Zope3 packages
+from zope.component import adapts, getAdapters
+from zope.interface import implements, Interface
+
+# import local packages
+from ztfy.base.interfaces import IBaseContent
+
+
+class ContentMeta(object):
+    """Base content meta header"""
+
+    implements(IContentMetaHeader)
+
+    def __init__(self, name, value):
+        self.name = name
+        self.value = value
+
+    def render(self):
+        return """<meta name="%(name)s" content="%(content)s" />""" % {'name': self.name,
+                                                                       'content': self.value}
+
+
+class HTTPEquivMeta(object):
+    """HTTP-Equiv meta header, mainly used for content-type"""
+
+    implements(IHTTPEquivMetaHeader)
+
+    def __init__(self, http_equiv, value):
+        self.http_equiv = http_equiv
+        self.value = value
+
+    def render(self):
+        return """<meta http-equiv="%(http_equiv)s" content="%(content)s" />""" % {'http_equiv': self.http_equiv,
+                                                                                   'content': self.value}
+
+
+class PropertyMeta(object):
+    """Property meta header, mainly used for Facebook app_id"""
+
+    implements(IPropertyMetaHeader)
+
+    def __init__(self, property, value):
+        self.property = property
+        self.value = value
+
+    def render(self):
+        return """<meta property="%(property)s" content="%(content)s" />""" % {'property': self.property,
+                                                                               'content': self.value}
+
+
+class LinkMeta(object):
+    """Link meta header, mainly used for CSS or RSS links"""
+
+    implements(ILinkMetaHeader)
+
+    def __init__(self, rel, type, href):
+        self.rel = rel
+        self.type = type
+        self.href = href
+
+    def render(self):
+        return """<link rel="%(rel)s" type="%(type)s" href="%(href)s" />""" % {'rel': self.rel,
+                                                                               'type': self.type,
+                                                                               'href': self.href}
+
+
+class ContentMetasAdapter(object):
+    """Generic content metas adapter"""
+
+    adapts(Interface, Interface)
+    implements(IPageMetasHeaders)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    @property
+    def metas(self):
+        """Extract headers from all available metas adapters"""
+        result = []
+        for _name, adapter in getAdapters((self.context, self.request), IContentMetasHeaders):
+            result.extend(adapter.metas)
+        return result
+
+
+class BaseContentMetasHeadersAdapter(object):
+    """Base content metas adapter"""
+
+    adapts(IBaseContent, Interface)
+    implements(IContentMetasHeaders)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    @property
+    def metas(self):
+        result = []
+        result.append(HTTPEquivMeta('Content-Type', 'text/html; charset=UTF-8'))
+        description = self.context.description
+        if description:
+            result.append(ContentMeta('description', description.replace('\n', ' ')))
+        keywords = self.context.keywords
+        if keywords:
+            result.append(ContentMeta('keywords', keywords))
+        return result
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/metas.zcml	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,41 @@
+<configure
+	xmlns="http://namespaces.zope.org/zope"
+	i18n_domain="ztfy.baseskin">
+
+	<!-- Metas adapters -->
+	<class class=".metas.ContentMeta">
+		<allow interface=".interfaces.metas.IContentMetaHeader" />
+	</class>
+
+	<class class=".metas.HTTPEquivMeta">
+		<allow interface=".interfaces.metas.IHTTPEquivMetaHeader" />
+	</class>
+
+	<class class=".metas.PropertyMeta">
+		<allow interface=".interfaces.metas.IPropertyMetaHeader" />
+	</class>
+
+	<class class=".metas.LinkMeta">
+		<allow interface=".interfaces.metas.ILinkMetaHeader" />
+	</class>
+
+	<adapter
+		name="base"
+		factory=".metas.BaseContentMetasHeadersAdapter"
+		locate="True"
+		trusted="True" />
+
+	<class class=".metas.BaseContentMetasHeadersAdapter">
+		<allow interface=".interfaces.metas.IContentMetasHeaders" />
+	</class>
+
+	<adapter
+		factory=".metas.ContentMetasAdapter"
+		locate="True"
+		trusted="True" />
+
+	<class class=".metas.ContentMetasAdapter">
+		<allow interface=".interfaces.metas.IPageMetasHeaders" />
+	</class>
+
+</configure>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/schema.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2012 Thierry Florac <tflorac AT onf.fr>
+# All Rights Reserved.
+#
+
+
+# import standard packages
+
+# import Zope3 interfaces
+from z3c.form.interfaces import IButton
+
+# import local interfaces
+
+# import Zope3 packages
+from z3c.form.button import Button
+from zope.interface import implements
+
+# import local packages
+
+
+class IResetButton(IButton):
+    """Reset button interface"""
+
+
+class ResetButton(Button):
+    """Reset button"""
+
+    implements(IResetButton)
+
+
+class ICloseButton(IButton):
+    """Close button interface"""
+
+
+class CloseButton(Button):
+    """Close button"""
+
+    implements(ICloseButton)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/skin.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,43 @@
+### -*- coding: utf-8 -*- ####################################################
+##############################################################################
+#
+# Copyright (c) 2008 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+
+# import standard packages
+
+# import Zope3 interfaces
+from zope.publisher.interfaces.browser import IBrowserRequest, IBrowserSkinType
+from zope.traversing.interfaces import IBeforeTraverseEvent
+
+# import local interfaces
+from ztfy.baseskin.interfaces import ISkinnable
+
+# import Zope3 packages
+from zope.component import adapter, queryUtility
+from zope.publisher.skinnable import applySkin
+
+# import local packages
+
+
+@adapter(ISkinnable, IBeforeTraverseEvent)
+def handleSkinTraversal(object, event):
+    if IBrowserRequest.providedBy(event.request):
+        path = event.request.get('PATH_INFO', '')
+        if '++skin++' not in path:
+            skin_name = ISkinnable(object).getSkin()
+            if not skin_name:
+                skin_name = 'ZMI'
+            skin = queryUtility(IBrowserSkinType, skin_name)
+            if skin is not None:
+                applySkin(event.request, skin)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/tal/__init__.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,1 @@
+#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/tal/api.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,74 @@
+### -*- coding: utf-8 -*- ####################################################
+##############################################################################
+#
+# Copyright (c) 2008-2010 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+__docformat__ = "restructuredtext"
+
+# import standard packages
+
+# import Zope3 interfaces
+from zope.tales.interfaces import ITALESFunctionNamespace
+
+# import local interfaces
+from ztfy.baseskin.interfaces import IPresentationTarget
+from ztfy.baseskin.interfaces.metas import IPageMetasHeaders
+from ztfy.baseskin.tal.interfaces import ISkinTalesAPI, IContentMetasAPI
+
+# import Zope3 packages
+from zope.component import queryMultiAdapter
+from zope.interface import implements
+
+# import local packages
+
+
+class SkinTalesAPI(object):
+
+    implements(ISkinTalesAPI, ITALESFunctionNamespace)
+
+    def __init__(self, context):
+        self.context = context
+
+    def setEngine(self, engine):
+        self.request = engine.vars['request']
+
+    def presentation(self):
+        adapter = queryMultiAdapter((self.context, self.request), IPresentationTarget)
+        if adapter is not None:
+            interface = adapter.target_interface
+            return interface(self.context)
+
+
+class ContentMetasTalesAPI(object):
+
+    implements(IContentMetasAPI, ITALESFunctionNamespace)
+
+    def __init__(self, context):
+        self.context = context
+
+    def setEngine(self, engine):
+        self.request = engine.vars['request']
+
+    def items(self):
+        headers = queryMultiAdapter((self.context, self.request), IPageMetasHeaders)
+        if headers is None:
+            return []
+        else:
+            return headers.metas
+
+    def render(self):
+        headers = queryMultiAdapter((self.context, self.request), IPageMetasHeaders)
+        if headers is None:
+            return u''
+        else:
+            return '\n'.join((meta.render() for meta in headers.metas))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/tal/configure.zcml	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,17 @@
+<configure
+	xmlns="http://namespaces.zope.org/zope"
+	i18n_domain="ztfy.blog">
+
+	<adapter
+		name="skin"
+		factory=".api.SkinTalesAPI"
+		provides="zope.traversing.interfaces.IPathAdapter"
+		for="*" />
+
+	<adapter
+		name="metas"
+		factory=".api.ContentMetasTalesAPI"
+		provides="zope.traversing.interfaces.IPathAdapter"
+		for="*" />
+
+</configure>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/tal/interfaces.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,44 @@
+### -*- coding: utf-8 -*- ####################################################
+##############################################################################
+#
+# Copyright (c) 2008-2010 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+__docformat__ = "restructuredtext"
+
+# import standard packages
+
+# import Zope3 interfaces
+
+# import local interfaces
+
+# import Zope3 packages
+from zope.interface import Interface
+
+# import local packages
+
+
+class ISkinTalesAPI(Interface):
+    """'skin:' TALES namespace interface"""
+
+    def presentation(self):
+        """Get presentation of adapted context"""
+
+
+class IContentMetasAPI(Interface):
+    """'metas' TALES namespace interface"""
+
+    def items(self):
+        """Get list of metas headers"""
+
+    def render(self):
+        """Get content metas headers"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/tests/__init__.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,1 @@
+#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/tests/test_docs.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,55 @@
+# Copyright (c) 2008-2012 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+
+"""
+Generic Test case for 'ztfy.baseskin' doctest
+"""
+__docformat__ = 'restructuredtext'
+
+import unittest
+import doctest
+import sys
+import os
+
+
+current_dir = os.path.dirname(__file__)
+
+def doc_suite(test_dir, setUp=None, tearDown=None, globs=None):
+    """Returns a test suite, based on doctests found in /doctests."""
+    suite = []
+    if globs is None:
+        globs = globals()
+
+    flags = (doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE |
+             doctest.REPORT_ONLY_FIRST_FAILURE)
+
+    package_dir = os.path.split(test_dir)[0]
+    if package_dir not in sys.path:
+        sys.path.append(package_dir)
+
+    doctest_dir = os.path.join(package_dir, 'doctests')
+
+    # filtering files on extension
+    docs = [os.path.join(doctest_dir, doc) for doc in
+            os.listdir(doctest_dir) if doc.endswith('.txt')]
+
+    for test in docs:
+        suite.append(doctest.DocFileSuite(test, optionflags=flags,
+                                          globs=globs, setUp=setUp,
+                                          tearDown=tearDown,
+                                          module_relative=False))
+
+    return unittest.TestSuite(suite)
+
+def test_suite():
+    """returns the test suite"""
+    return doc_suite(current_dir)
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/tests/test_docstrings.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,59 @@
+# Copyright (c) 2008-2012 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+
+"""
+Generic Test case for 'ztfy.baseskin' doc strings
+"""
+__docformat__ = 'restructuredtext'
+
+import unittest
+import doctest
+import sys
+import os
+
+
+current_dir = os.path.abspath(os.path.dirname(__file__))
+
+def doc_suite(test_dir, globs=None):
+    """Returns a test suite, based on doc tests strings found in /*.py"""
+    suite = []
+    if globs is None:
+        globs = globals()
+
+    flags = (doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE |
+             doctest.REPORT_ONLY_FIRST_FAILURE)
+
+    package_dir = os.path.split(test_dir)[0]
+    if package_dir not in sys.path:
+        sys.path.append(package_dir)
+
+    # filtering files on extension
+    docs = [doc for doc in
+            os.listdir(package_dir) if doc.endswith('.py')]
+    docs = [doc for doc in docs if not doc.startswith('__')]
+
+    for test in docs:
+        fd = open(os.path.join(package_dir, test))
+        content = fd.read()
+        fd.close()
+        if '>>> ' not in content:
+            continue
+        test = test.replace('.py', '')
+        location = 'ztfy.baseskin.%s' % test
+        suite.append(doctest.DocTestSuite(location, optionflags=flags,
+                                          globs=globs))
+
+    return unittest.TestSuite(suite)
+
+def test_suite():
+    """returns the test suite"""
+    return doc_suite(current_dir)
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/viewlet.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,100 @@
+### -*- coding: utf-8 -*- ####################################################
+##############################################################################
+#
+# Copyright (c) 2008-2014 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+__docformat__ = "restructuredtext"
+
+# import standard packages
+
+# import Zope3 interfaces
+from zope.contentprovider.interfaces import IContentProvider
+
+# import local interfaces
+from ztfy.baseskin.interfaces.form import IFormViewletsManager, IFormPrefixViewletsManager, \
+    IWidgetsPrefixViewletsManager, IWidgetsSuffixViewletsManager, IFormSuffixViewletsManager
+
+# import Zope3 packages
+from z3c.template.template import getViewTemplate
+from zope.component import adapts
+from zope.interface import implements, Interface
+from zope.viewlet.viewlet import ViewletBase as Viewlet
+from zope.viewlet.manager import ViewletManagerBase as ViewletManager, WeightOrderedViewletManager
+
+# import local packages
+from ztfy.baseskin.layer import IBaseSkinLayer
+
+
+class ViewletManagerBase(ViewletManager):
+    """Template based viewlet manager class"""
+
+    template = getViewTemplate()
+
+
+class WeightViewletManagerBase(WeightOrderedViewletManager):
+    """Template based weighted viewlet manager class"""
+
+    template = getViewTemplate()
+
+
+class ViewletBase(Viewlet):
+    """Template based viewlet"""
+
+    render = getViewTemplate()
+
+
+class ContentProviderBase(object):
+    """Generic template based content provider"""
+
+    adapts(Interface, IBaseSkinLayer, Interface)
+    implements(IContentProvider)
+
+    def __init__(self, context, request, view):
+        self.context = context
+        self.request = request
+        self.__parent__ = view
+
+    def update(self):
+        pass
+
+    render = getViewTemplate()
+
+
+class FormViewletManager(WeightOrderedViewletManager):
+    """Base form viewlet manager"""
+
+    implements(IFormViewletsManager)
+
+
+class FormPrefixViewletManager(FormViewletManager):
+    """Form prefix viewlet manager, displayed before form"""
+
+    implements(IFormPrefixViewletsManager)
+
+
+class WidgetsPrefixViewletManager(FormViewletManager):
+    """Form widgets prefix display manager, displayed before widgets"""
+
+    implements(IWidgetsPrefixViewletsManager)
+
+
+class WidgetsSuffixViewletManager(FormViewletManager):
+    """Form widgets suffix viewlet manager, displayed after widgets"""
+
+    implements(IWidgetsSuffixViewletsManager)
+
+
+class FormSuffixViewletManager(FormViewletManager):
+    """Form suffix viewlet manager, displayed after form"""
+
+    implements(IFormSuffixViewletsManager)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ztfy/baseskin/widget.py	Sun May 11 02:03:37 2014 +0200
@@ -0,0 +1,88 @@
+#
+# Copyright (c) 2012 Thierry Florac <tflorac AT onf.fr>
+# All Rights Reserved.
+#
+
+
+# import standard packages
+
+# import Zope3 interfaces
+from z3c.form.interfaces import IFormLayer, IFieldWidget
+
+# import local interfaces
+from ztfy.baseskin.interfaces.form import IResetWidget, ICloseWidget
+from ztfy.baseskin.schema import IResetButton, ICloseButton
+
+# import Zope3 packages
+from z3c.form.action import Action
+from z3c.form.browser.submit import SubmitWidget
+from z3c.form.button import ButtonAction
+from z3c.form.widget import FieldWidget
+from zope.component import adapter, adapts
+from zope.interface import implementer, implementsOnly
+
+# import local packages
+
+
+#
+# Reset button widget and action
+#
+
+class ResetWidget(SubmitWidget):
+    """A reset button of a form."""
+
+    implementsOnly(IResetWidget)
+
+    klass = u'reset-widget'
+    css = u'reset'
+
+
+@adapter(IResetButton, IFormLayer)
+@implementer(IFieldWidget)
+def ResetFieldWidget(field, request):
+    reset = FieldWidget(field, ResetWidget(request))
+    reset.value = field.title
+    return reset
+
+
+class ResetButtonAction(ResetWidget, ButtonAction):
+    """Reset button action"""
+
+    adapts(IFormLayer, IResetButton)
+
+    def __init__(self, request, field):
+        Action.__init__(self, request, field.title)
+        ResetWidget.__init__(self, request)
+        self.field = field
+
+
+#
+# Close button widget and action
+#
+
+class CloseWidget(SubmitWidget):
+    """A dialog close button"""
+
+    implementsOnly(ICloseWidget)
+
+    klass = u'close-widget'
+    css = u'close'
+
+
+@adapter(ICloseButton, IFormLayer)
+@implementer(IFieldWidget)
+def CloseFieldWidget(field, request):
+    close = FieldWidget(field, CloseWidget(request))
+    close.value = field.title
+    return close
+
+
+class CloseButtonAction(CloseWidget, ButtonAction):
+    """Close button action"""
+
+    adapts(IFormLayer, ICloseButton)
+
+    def __init__(self, request, field):
+        Action.__init__(self, request, field.title)
+        CloseWidget.__init__(self, request)
+        self.field = field