From a335c4fe1544eceaa33e77a88b32edb1dea2108a Mon Sep 17 00:00:00 2001 From: Sean Brant Date: Sun, 10 Mar 2013 18:39:11 -0500 Subject: Adds pykss.contrib.django Provides a generic view as well as a template tag for generating style guides. --- README.rst | 7 + examples/djangoproject/djangoproject/__init__.py | 0 examples/djangoproject/djangoproject/settings.py | 25 ++++ .../djangoproject/static/css/buttons.css | 50 +++++++ .../djangoproject/static/css/layout.css | 143 +++++++++++++++++++++ .../djangoproject/templates/base.html | 23 ++++ .../djangoproject/templates/index.html | 8 ++ .../djangoproject/templates/styleguide.html | 19 +++ examples/djangoproject/djangoproject/urls.py | 10 ++ examples/djangoproject/djangoproject/wsgi.py | 5 + examples/djangoproject/manage.py | 10 ++ examples/djangoproject/requirements.txt | 2 + pykss/contrib/__init__.py | 0 pykss/contrib/django/__init__.py | 0 pykss/contrib/django/models.py | 0 pykss/contrib/django/static/pykss/js/kss.js | 47 +++++++ .../django/templates/pykss/styleguideblock.html | 37 ++++++ pykss/contrib/django/templatetags/__init__.py | 0 pykss/contrib/django/templatetags/pykss.py | 66 ++++++++++ pykss/contrib/django/views.py | 20 +++ 20 files changed, 472 insertions(+) create mode 100644 examples/djangoproject/djangoproject/__init__.py create mode 100644 examples/djangoproject/djangoproject/settings.py create mode 100644 examples/djangoproject/djangoproject/static/css/buttons.css create mode 100644 examples/djangoproject/djangoproject/static/css/layout.css create mode 100644 examples/djangoproject/djangoproject/templates/base.html create mode 100644 examples/djangoproject/djangoproject/templates/index.html create mode 100644 examples/djangoproject/djangoproject/templates/styleguide.html create mode 100644 examples/djangoproject/djangoproject/urls.py create mode 100644 examples/djangoproject/djangoproject/wsgi.py create mode 100644 examples/djangoproject/manage.py create mode 100644 examples/djangoproject/requirements.txt create mode 100644 pykss/contrib/__init__.py create mode 100644 pykss/contrib/django/__init__.py create mode 100644 pykss/contrib/django/models.py create mode 100644 pykss/contrib/django/static/pykss/js/kss.js create mode 100644 pykss/contrib/django/templates/pykss/styleguideblock.html create mode 100644 pykss/contrib/django/templatetags/__init__.py create mode 100644 pykss/contrib/django/templatetags/pykss.py create mode 100644 pykss/contrib/django/views.py diff --git a/README.rst b/README.rst index 232f2ab..0738c12 100644 --- a/README.rst +++ b/README.rst @@ -50,3 +50,10 @@ Usage >>> >>> styleguide.section('2.1.1').modifiers[0].description 'Subtle hover highlight' + + +Django Usage +------------ +If you would like to use KSS within a Django project `pykss.contrib.django` +provides a view and template tag to make it easier. Check out the example +Django project for usage. diff --git a/examples/djangoproject/djangoproject/__init__.py b/examples/djangoproject/djangoproject/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/djangoproject/djangoproject/settings.py b/examples/djangoproject/djangoproject/settings.py new file mode 100644 index 0000000..39b1c62 --- /dev/null +++ b/examples/djangoproject/djangoproject/settings.py @@ -0,0 +1,25 @@ +import os + +PROJECT_ROOT = os.path.dirname(__file__) + +DEBUG = True +SECRET_KEY = 'G0GS4C7QLq3FhdDYrNtDuEBoLuXzDqaS' +ROOT_URLCONF = 'djangoproject.urls' + +TEMPLATE_DIRS = [os.path.join(PROJECT_ROOT, 'templates')] + +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(PROJECT_ROOT, 'public') + +STATICFILES_DIRS = [os.path.join(PROJECT_ROOT, 'static')] +STATICFILES_FINDERS = [ + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +] + +PYKSS_DIRS = [os.path.join(PROJECT_ROOT, 'static', 'css')] + +INSTALLED_APPS = [ + 'django.contrib.staticfiles', + 'pykss.contrib.django', +] diff --git a/examples/djangoproject/djangoproject/static/css/buttons.css b/examples/djangoproject/djangoproject/static/css/buttons.css new file mode 100644 index 0000000..edcb4b3 --- /dev/null +++ b/examples/djangoproject/djangoproject/static/css/buttons.css @@ -0,0 +1,50 @@ +/* +Your standard form button. + +:hover - Highlights when hovering. +:disabled - Dims the button when disabled. +.primary - Indicates button is the primary action. +.smaller - A smaller button + +Styleguide 1.1 +*/ +button { + padding: 5px 15px; + line-height: normal; + font-family: "Helvetica Neue", Helvetica; + font-size: 12px; + font-weight: bold; + color: #666; + text-shadow: 0 1px rgba(255, 255, 255, 0.9); + border-radius: 3px; + border: 1px solid #ddd; + border-bottom-color: #bbb; + background: #f5f5f5; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='$start', endColorstr='$end'); + background: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e5e5e5)); + background: -moz-linear-gradient(top, #f5f5f5, #e5e5e5); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15); + cursor: pointer; } + button.primary, button.primary:hover { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4); + border-color: #74bb5a; + border-bottom-color: #509338; + background: #8add6d; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='$start', endColorstr='$end'); + background: -webkit-gradient(linear, left top, left bottom, from(#8add6d), to(#60b044)); + background: -moz-linear-gradient(top, #8add6d, #60b044); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); } + button.smaller { + font-size: 11px; + padding: 4px 7px; } + button:hover { + color: #337797; + background: #f0f7fa; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='$start', endColorstr='$end'); + background: -webkit-gradient(linear, left top, left bottom, from(#f0f7fa), to(#d8eaf2)); + background: -moz-linear-gradient(top, #f0f7fa, #d8eaf2); + border-color: #cbe3ee; + border-bottom-color: #97c7dd; } + button:disabled { + opacity: 0.5; } diff --git a/examples/djangoproject/djangoproject/static/css/layout.css b/examples/djangoproject/djangoproject/static/css/layout.css new file mode 100644 index 0000000..871d414 --- /dev/null +++ b/examples/djangoproject/djangoproject/static/css/layout.css @@ -0,0 +1,143 @@ +/*---------------------------------------------------------------------------- + @group Global Reset +----------------------------------------------------------------------------*/ +* { + padding:0; + margin:0; +} +h1, h2, h3, h4, h5, h6, p, pre, blockquote, label, ul, ol, dl, fieldset, address { margin:1em 0; } +li, dd { margin-left:5%; } +fieldset { padding: .5em; } +select option{ padding:0 5px; } + +.access{ display:none; } /* For accessibility related elements */ +.clear{ clear:both; height:0px; font-size:0px; line-height:0px; overflow:hidden; } +a{ outline:none; } +a img{ border:none; } + +.clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} +* html .clearfix {height: 1%;} +.clearfix {display:inline-block;} +.clearfix {display: block;} + +/* @end */ + +body{ + font-family:Helvetica, Arial, sans-serif; + font-size:14px; +} + +header{ + padding:10px; + + font-size:16px; + color:#666; + + background:#f1f1f1; + border-bottom:1px solid #ddd; +} + +#wrapper{ + width:600px; + padding-left:200px; +} + +nav[role=main]{ + float:left; + margin-left:-200px; + width:160px; +} +nav ul{ + margin-left:10px; +} +nav li{ + list-style-type:none; + margin:10px 0; +} +nav li a{ + text-decoration:none; + color:#666; +} + +/*---------------------------------------------------------------------------- + @group Styleguide Styles +----------------------------------------------------------------------------*/ + +h1.styleguide { + margin: 0 0 -5px 0; + font-size: 24px; + color: #000; } + +.styleguide-example { + margin: 15px 0; + background: rgba(255, 255, 255, 0.5); + border: 1px solid #ddd; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); } + .styleguide-example > h3 { + margin: 0; + padding: 5px; + color: #fff; + font-size: 12px; + text-transform: uppercase; + background: #333; + border-top: 1px solid #000; } + .styleguide-example > h3 em { + float: right; + text-transform: none; + font-style: normal; + font-weight: normal; + color: #999; } + .styleguide-example .styleguide-description { + padding: 10px 5px; + background: #f1f1f1; + border-bottom: 1px solid #ddd; } + .styleguide-example .styleguide-description p:first-child { + margin-top: 0; } + .styleguide-example .styleguide-description p:last-child { + margin-bottom: 0; } + .styleguide-example .styleguide-element { + position: relative; + padding: 20px; } + .styleguide-example .styleguide-element + .styleguide-element { + margin-top: -5px; + padding-top: 15px; + border-top: 1px solid #eee; } + .styleguide-example .styleguide-element .styleguide-modifier-name { + display: block; + position: absolute; + top: 0; + right: 0; + padding: 5px 8px; + font-size: 11px; + color: #999; + background: #f9f9f9; + border: 1px solid #eee; + border-top: none; } + .styleguide-example .styleguide-html { + padding: 5px 10px; + background: #edf6f8; + border-top: 1px solid #dde7ea; + overflow: auto; } + .styleguide-example .styleguide-html .highlight { + background: none; } + .styleguide-example ul.styleguide-modifiers { + margin: 0 0 0 10px; } + .styleguide-example ul.styleguide-modifiers li { + list-style-type: none; + margin-left: 0; } + .styleguide-example ul.styleguide-modifiers li strong { + font-family: Monaco, monospace; + font-size: 12px; + font-weight: normal; + color: #222; } + .styleguide-example > .styleguide-code { + font-family: Monaco, monospace; + } + +/* @end */ diff --git a/examples/djangoproject/djangoproject/templates/base.html b/examples/djangoproject/djangoproject/templates/base.html new file mode 100644 index 0000000..f52ed82 --- /dev/null +++ b/examples/djangoproject/djangoproject/templates/base.html @@ -0,0 +1,23 @@ + +{% load static %} + + + + Styleguide Example + + + + +
Styleguide Example
+
+
+
    +
  • Home
  • +
  • Styleguide
  • +
+
+ {% block content %}{% endblock %} +
+ + + diff --git a/examples/djangoproject/djangoproject/templates/index.html b/examples/djangoproject/djangoproject/templates/index.html new file mode 100644 index 0000000..06660ce --- /dev/null +++ b/examples/djangoproject/djangoproject/templates/index.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% block content %} +

Welcome

+

This is an example site. It doesn't really do anything, but it does have some rad buttons

+

+

Check out the styleguide to see the value here.

+{% endblock %} diff --git a/examples/djangoproject/djangoproject/templates/styleguide.html b/examples/djangoproject/djangoproject/templates/styleguide.html new file mode 100644 index 0000000..05d736d --- /dev/null +++ b/examples/djangoproject/djangoproject/templates/styleguide.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} +{% load pykss %} + +{% block content %} +{% styleguideblock styleguide "1.1" %} + +{% endstyleguideblock %} + +{% verbatim %} +

This block above was created with a simple template call:

+
+    
+{% styleguideblock styleguide "1.1" %}
+    <button class="{{ modifier.class_name }}">Example Button</button>
+{% endstyleguideblock %}
+    
+
+{% endverbatim %} +{% endblock %} diff --git a/examples/djangoproject/djangoproject/urls.py b/examples/djangoproject/djangoproject/urls.py new file mode 100644 index 0000000..061ec2c --- /dev/null +++ b/examples/djangoproject/djangoproject/urls.py @@ -0,0 +1,10 @@ +from django.conf.urls import patterns, url +from django.views.generic.base import TemplateView + +from pykss.contrib.django.views import StyleGuideView + + +urlpatterns = patterns('', + url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'), + url(r'^styleguide/$', StyleGuideView.as_view(template_name='styleguide.html'), name='styleguide'), +) diff --git a/examples/djangoproject/djangoproject/wsgi.py b/examples/djangoproject/djangoproject/wsgi.py new file mode 100644 index 0000000..d306fe1 --- /dev/null +++ b/examples/djangoproject/djangoproject/wsgi.py @@ -0,0 +1,5 @@ +import os +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoproject.settings') + +from django.core.wsgi import get_wsgi_application +application = get_wsgi_application() diff --git a/examples/djangoproject/manage.py b/examples/djangoproject/manage.py new file mode 100644 index 0000000..6c0acfc --- /dev/null +++ b/examples/djangoproject/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + + +if __name__ == '__main__': + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoproject.settings') + + from django.core.management import execute_from_command_line + execute_from_command_line(sys.argv) diff --git a/examples/djangoproject/requirements.txt b/examples/djangoproject/requirements.txt new file mode 100644 index 0000000..c52f862 --- /dev/null +++ b/examples/djangoproject/requirements.txt @@ -0,0 +1,2 @@ +Django==1.5 +https://github.com/seanbrant/pykss.git diff --git a/pykss/contrib/__init__.py b/pykss/contrib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pykss/contrib/django/__init__.py b/pykss/contrib/django/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pykss/contrib/django/models.py b/pykss/contrib/django/models.py new file mode 100644 index 0000000..e69de29 diff --git a/pykss/contrib/django/static/pykss/js/kss.js b/pykss/contrib/django/static/pykss/js/kss.js new file mode 100644 index 0000000..14a95cc --- /dev/null +++ b/pykss/contrib/django/static/pykss/js/kss.js @@ -0,0 +1,47 @@ +(function() { + var KssStateGenerator; + + KssStateGenerator = (function() { + + function KssStateGenerator() { + var idx, idxs, pseudos, replaceRule, rule, stylesheet, _i, _len, _len2, _ref, _ref2; + pseudos = /(\:hover|\:disabled|\:active|\:visited|\:focus)/g; + try { + _ref = document.styleSheets; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + stylesheet = _ref[_i]; + idxs = []; + _ref2 = stylesheet.cssRules; + for (idx = 0, _len2 = _ref2.length; idx < _len2; idx++) { + rule = _ref2[idx]; + if ((rule.type === CSSRule.STYLE_RULE) && pseudos.test(rule.selectorText)) { + replaceRule = function(matched, stuff) { + return matched.replace(/\:/g, '.pseudo-class-'); + }; + this.insertRule(rule.cssText.replace(pseudos, replaceRule)); + } + } + } + } catch (_error) {} + } + + KssStateGenerator.prototype.insertRule = function(rule) { + var headEl, styleEl; + headEl = document.getElementsByTagName('head')[0]; + styleEl = document.createElement('style'); + styleEl.type = 'text/css'; + if (styleEl.styleSheet) { + styleEl.styleSheet.cssText = rule; + } else { + styleEl.appendChild(document.createTextNode(rule)); + } + return headEl.appendChild(styleEl); + }; + + return KssStateGenerator; + + })(); + + new KssStateGenerator; + +}).call(this); diff --git a/pykss/contrib/django/templates/pykss/styleguideblock.html b/pykss/contrib/django/templates/pykss/styleguideblock.html new file mode 100644 index 0000000..8521ee1 --- /dev/null +++ b/pykss/contrib/django/templates/pykss/styleguideblock.html @@ -0,0 +1,37 @@ +
+ {% block styleguide_header %} +

{{ section.section }} {{ section.filename }}

+ {% endblock %} + + {% block styleguide_description %} +
+

{{ section.description }}

+ {% if section.modifiers %} +
    + {% for modifier in section.modifiers %} +
  • {{ modifier.name }} - {{ modifier.description }}
  • + {% endfor %} +
+ {% endif %} +
+ {% endblock %} + + {% block styleguide_element %} +
+ {{ example_html }} +
+ {% endblock %} + + {% block styleguide_modifier_elements %} + {% for example in modifier_examples %} +
+ {{ example.modifier.name }} + {{ example.html }} +
+ {% endfor %} + {% endblock %} + + {% block styleguide_code %} +
{{ escaped_html }}
+ {% endblock %} +
diff --git a/pykss/contrib/django/templatetags/__init__.py b/pykss/contrib/django/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pykss/contrib/django/templatetags/pykss.py b/pykss/contrib/django/templatetags/pykss.py new file mode 100644 index 0000000..f833ade --- /dev/null +++ b/pykss/contrib/django/templatetags/pykss.py @@ -0,0 +1,66 @@ +from django import template +from django.template.loader import render_to_string + + +register = template.Library() + + +class StyleGuideBlockNode(template.Node): + + def __init__(self, styleguide, reference, template_name, nodelist): + self.styleguide = styleguide + self.reference = reference + self.template_name = template_name + self.nodelist = nodelist + + def __repr__(self): + return '' + + def render(self, context): + styleguide = self.styleguide.resolve(context) + reference = self.reference.resolve(context) + template_name = self.template_name.resolve(context) + + section = styleguide.section(reference) + + example_html = self.nodelist.render(context) + + modifier_examples = [] + for modifier in section.modifiers: + context.update({'modifier': modifier}) + modifier_examples.append({ + 'modifier': modifier, + 'html': self.nodelist.render(context), + }) + + output = render_to_string(template_name, { + 'section': section, + 'example_html': example_html, + 'modifier_examples': modifier_examples, + }) + + return output + + +@register.tag +def styleguideblock(parser, token): + bits = token.contents.split() + + if len(bits) != 3: + raise template.TemplateSyntaxError("styleguideblock expected at least two arguments") + + try: + tag, styleguide, reference, template_name = bits + except ValueError: + tag, styleguide, reference = bits + template_name = '"pykss/styleguideblock.html"' + + nodelist = parser.parse(('endstyleguideblock',)) + parser.delete_first_token() + + return StyleGuideBlockNode( + styleguide=parser.compile_filter(styleguide), + reference=parser.compile_filter(reference), + template_name=parser.compile_filter(template_name), + nodelist=nodelist, + ) diff --git a/pykss/contrib/django/views.py b/pykss/contrib/django/views.py new file mode 100644 index 0000000..853bfc2 --- /dev/null +++ b/pykss/contrib/django/views.py @@ -0,0 +1,20 @@ +from django.conf import settings +from django.views.generic.base import TemplateView + +import pykss + + +class StyleGuideMixin(object): + + def get_styleguid(self): + dirs = getattr(settings, 'PYKSS_DIRS', []) + return pykss.Parser(*dirs) + + def get_context_data(self, **kwargs): + context = {'styleguide': self.get_styleguid()} + context.update(kwargs) + return super(StyleGuideMixin, self).get_context_data(**context) + + +class StyleGuideView(StyleGuideMixin, TemplateView): + pass -- cgit v1.2.3