Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

introduce php css-xfire handler

  • Loading branch information...
commit 49bce6fb926889fa8cadd12563a81d56d4734bea 0 parents
@docteurklein authored
2  .gitignore
@@ -0,0 +1,2 @@
+css.log
+dirs.php
15 .gitmodules
@@ -0,0 +1,15 @@
+[submodule "vendor/css-parser"]
+ path = vendor/css-parser
+ url = https://github.com/sabberworm/PHP-CSS-Parser.git
+[submodule "vendor/Finder"]
+ path = vendor/Finder
+ url = https://github.com/symfony/Finder.git
+[submodule "vendor/class-loader"]
+ path = vendor/class-loader
+ url = https://github.com/symfony/ClassLoader.git
+[submodule "vendor/Symfony/Component/Finder"]
+ path = vendor/Symfony/Component/Finder
+ url = https://github.com/symfony/Finder.git
+[submodule "vendor/Symfony/Component/ClassLoader"]
+ path = vendor/Symfony/Component/ClassLoader
+ url = https://github.com/symfony/ClassLoader.git
161 CssManipulator.php
@@ -0,0 +1,161 @@
+<?php
+
+/**
+ * CSS rules manipulator
+ *
+ * @author Florian Klein <florian.klein@free.fr>
+ */
+class CssManipulator
+{
+ /**
+ * __construct
+ *
+ * @param CSSDocument $css
+ */
+ public function __construct(CSSDocument $css, \Closure $logger = null)
+ {
+ $this->css = $css;
+ $this->logger = $logger;
+ }
+
+ private function log()
+ {
+ if(null !== $logger = $this->logger) {
+ $logger(print_r(func_get_args(), true));
+ }
+ }
+
+ /**
+ * createRule
+ *
+ * @param mixed $propery
+ * @param mixed $value
+ * @param mixed $important
+ * @return void
+ */
+ public function createRule($propery, $value = null, $important = false)
+ {
+ $rule = new CSSRule($property);
+ $rule->setValue($value);
+
+ return $rule;
+ }
+
+ /**
+ * createDeclarationBlock
+ *
+ * @param mixed $selector
+ * @return void
+ */
+ public function createDeclarationBlock($selector)
+ {
+ $declaration = new CSSDeclarationBlock();
+ $declaration->setSelectors($selector);
+
+ return $declaration;
+ }
+
+ /**
+ * addDeclarationBlock
+ *
+ * @param CSSDeclarationBlock $declaration
+ * @return void
+ */
+ public function addDeclarationBlock(CSSDeclarationBlock $declaration)
+ {
+ $this->log('adding ', $declaration);
+ $this->css->append($declaration);
+ }
+
+ /**
+ * removeDeclarationBlocks removes declaration blocks that match **exactly** the selector
+ *
+ * @param CSSSelector $selector
+ * @return void
+ */
+ public function removeDeclarationBlocks(CSSSelector $selector)
+ {
+ $this->log('remove ', $selector);
+ foreach($this->css->getAllDeclarationBlocks() as $declaration) {
+ $this->log('trying ', $selector, $declaration->getSelectors());
+ if($this->hasSelector($declaration, $selector)) {
+ $this->css->remove($declaration);
+ $this->log('removing ', $declaration);
+ }
+ }
+ }
+
+ /**
+ * addRules add rule to all blocks that match selector, or create one if no match
+ *
+ * @param CSSSelector $selector
+ * @param CSSRule $rule
+ * @return void
+ */
+ public function addRule(CSSSelector $selector, CSSRule $rule)
+ {
+ $this->log('add ', $rule, ' to ', $selector);
+ $found = false;
+ foreach($this->css->getAllDeclarationBlocks() as $declaration) {
+ if($this->hasSelector($declaration, $selector)) {
+ if ($rule->getValue()) {
+ $this->log('adding ', $rule, ' to ', $declaration);
+ $declaration->addRule($rule);
+ }
+ $found = true;
+ }
+ }
+
+ if (!$found) {
+ $declaration = $this->createDeclarationBlock((string)$selector);
+ if ($rule->getValue()) {
+ $this->log('adding ', $rule, ' to ', $declaration);
+ $declaration->addRule($rule);
+ }
+ $this->addDeclarationBlock($declaration);
+ }
+ }
+
+ /**
+ * removeRules
+ *
+ * @param CSSSelector $selector
+ * @param CSSRule $rule
+ * @return void
+ */
+ public function removeRule(CSSSelector $selector, CSSRule $rule)
+ {
+ $this->log('remove ', $rule);
+ foreach($this->css->getAllDeclarationBlocks() as $declaration) {
+ if($this->hasSelector($declaration, $selector)) {
+ $declaration->removeRule($rule->getRule());
+ $this->log('removing ', $rule);
+ }
+ }
+ }
+
+ private function hasSelector(CSSDeclarationBlock $declaration, CSSSelector $selector)
+ {
+ foreach($declaration->getSelectors() as $compare) {
+ if((string)$selector === (string)$compare) {
+ $this->log('found that ', (string)$selector, ' equals ', (string)$compare);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * save
+ *
+ * @param mixed $path
+ * @return boolean
+ */
+ public function save($path)
+ {
+ $this->log('saving to ', $path);
+ return @file_put_contents($path, (string)$this->css);
+ }
+}
+
26 README.md
@@ -0,0 +1,26 @@
+# PHP css-xfire handler
+
+## Handle live css manipulation from firebug to modify css source files.
+
+### how-to
+
+* clone the project
+
+ git clone http://github.com/docteurklein/css-manipulator.git css-manipulator
+ cd css-manipulator
+ git submodule update --init
+
+ echo "<?php $dirs = array(__DIR__.'/css');" > dirs.php
+
+* make the index.php file accessible at something like `http://css.local:8080`
+
+* configure css-xfire extension
+ * launch firefox
+ * install firebug
+ * [install css-xfire](http://code.google.com/p/css-x-fire/wiki/Installation#Details)
+ * open ``about:config``
+ * configure ``extensions.cssxfire@cssxfire.*`` keys to fit your config
+
+* relaunch firefox
+* edit your css live!
+* observe the diff of your css files located in ``__DIR__.'/css'`` (depending on what you put in ``dirs.php``)
13 autoload.php
@@ -0,0 +1,13 @@
+<?php
+
+require 'vendor/css-parser/CSSParser.php';
+require 'CssManipulator.php';
+require 'vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php';
+
+use Symfony\Component\ClassLoader\UniversalClassLoader;
+
+$loader = new UniversalClassLoader();
+$loader->registerNamespaces(array(
+ 'Symfony\\Component' => __DIR__.'/vendor',
+));
+$loader->register();
5 dirs.php.dist
@@ -0,0 +1,5 @@
+<?php
+
+$dirs = array(
+ __DIR__.'/tests',
+);
54 index.php
@@ -0,0 +1,54 @@
+<?php
+
+require 'autoload.php';
+require 'dirs.php';
+
+use Symfony\Component\Finder\Finder;
+
+$finder = new Finder;
+
+$finder
+ ->files()
+ ->name('*.css')
+ ->in($dirs); // coming from dirs.php
+;
+
+$rule= new CSSRule(@$_GET['property']);
+$rule->setValue(@$_GET['value']);
+
+// $params is coming from firebug's css-xfire extension
+$params = array(
+ 'selector' => new CSSSelector(@$_GET['selector']),
+ 'rule' => $rule,
+ 'property' => @$_GET['property'],
+ 'value' => @$_GET['value'],
+ 'deleted' => @$_GET['deleted'] === 'true',
+ 'href' => @$_GET['href'],
+ 'media' => @$_GET['media'],
+);
+
+$fd = fopen('css.log','a');
+$logger = function($log) use($fd) {
+ fwrite($fd, $log);
+};
+
+foreach($finder as $file) {
+ $parser = new CSSParser(file_get_contents((string)$file));
+ $css = $parser->parse();
+
+ $manipulator = new CssManipulator($css, $logger);
+
+ if($params['deleted']) {
+ if($params['value']) {
+ $manipulator->removeRule($params['selector'], $params['rule']);
+ }
+ else {
+ $manipulator->removeDeclarationBlocks($params['selector']);
+ }
+ }
+ else {
+ $manipulator->addRule($params['selector'], $params['rule']);
+ }
+
+ $manipulator->save((string)$file);
+}
142 tests/index.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
+ <meta name="author" content="Dave Shea" />
+ <meta name="keywords" content="design, css, cascading, style, sheets, xhtml, graphic design, w3c, web standards, visual, display" />
+ <meta name="description" content="A demonstration of what can be accomplished visually through CSS-based design." />
+ <meta name="robots" content="all" />
+
+ <title>css Zen Garden: The Beauty in CSS Design</title>
+
+ <link rel="stylesheet" type="text/css" href="/tests/test.css" />
+</head>
+
+<!--
+
+
+ This xhtml document is marked up to provide the designer with the maximum possible flexibility.
+ There are more classes and extraneous tags than needed, and in a real world situation, it's more
+ likely that it would be much leaner.
+
+ However, I think we can all agree that even given that, we're still better off than if this had been
+ built with tables.
+
+
+-->
+
+<body id="css-zen-garden">
+
+<div id="container">
+ <div id="intro">
+ <div id="pageHeader">
+ <h1><span>css Zen Garden</span></h1>
+ <h2><span>The Beauty of <acronym title="Cascading Style Sheets">CSS</acronym> Design</span></h2>
+ </div>
+
+ <div id="quickSummary">
+ <p class="p1"><span>A demonstration of what can be accomplished visually through <acronym title="Cascading Style Sheets">CSS</acronym>-based design. Select any style sheet from the list to load it into this page.</span></p>
+ <p class="p2"><span>Download the sample <a href="zengarden-sample.html" title="This page's source HTML code, not to be modified.">html file</a> and <a href="zengarden-sample.css" title="This page's sample CSS, the file you may modify.">css file</a></span></p>
+ </div>
+
+ <div id="preamble">
+ <h3><span>The Road to Enlightenment</span></h3>
+ <p class="p1"><span>Littering a dark and dreary road lay the past relics of browser-specific tags, incompatible <acronym title="Document Object Model">DOM</acronym>s, and broken <acronym title="Cascading Style Sheets">CSS</acronym> support.</span></p>
+ <p class="p2"><span>Today, we must clear the mind of past practices. Web enlightenment has been achieved thanks to the tireless efforts of folk like the <acronym title="World Wide Web Consortium">W3C</acronym>, <acronym title="Web Standards Project">WaSP</acronym> and the major browser creators.</span></p>
+ <p class="p3"><span>The css Zen Garden invites you to relax and meditate on the important lessons of the masters. Begin to see with clarity. Learn to use the (yet to be) time-honored techniques in new and invigorating fashion. Become one with the web.</span></p>
+ </div>
+ </div>
+
+ <div id="supportingText">
+ <div id="explanation">
+ <h3><span>So What is This About?</span></h3>
+ <p class="p1"><span>There is clearly a need for <acronym title="Cascading Style Sheets">CSS</acronym> to be taken seriously by graphic artists. The Zen Garden aims to excite, inspire, and encourage participation. To begin, view some of the existing designs in the list. Clicking on any one will load the style sheet into this very page. The code remains the same, the only thing that has changed is the external .css file. Yes, really.</span></p>
+ <p class="p2"><span><acronym title="Cascading Style Sheets">CSS</acronym> allows complete and total control over the style of a hypertext document. The only way this can be illustrated in a way that gets people excited is by demonstrating what it can truly be, once the reins are placed in the hands of those able to create beauty from structure. To date, most examples of neat tricks and hacks have been demonstrated by structurists and coders. Designers have yet to make their mark. This needs to change.</span></p>
+ </div>
+
+ <div id="participation">
+ <h3><span>Participation</span></h3>
+ <p class="p1"><span>Graphic artists only please. You are modifying this page, so strong <acronym title="Cascading Style Sheets">CSS</acronym> skills are necessary, but the example files are commented well enough that even <acronym title="Cascading Style Sheets">CSS</acronym> novices can use them as starting points. Please see the <a href="http://www.mezzoblue.com/zengarden/resources/" title="A listing of CSS-related resources"><acronym title="Cascading Style Sheets">CSS</acronym> Resource Guide</a> for advanced tutorials and tips on working with <acronym title="Cascading Style Sheets">CSS</acronym>.</span></p>
+ <p class="p2"><span>You may modify the style sheet in any way you wish, but not the <acronym title="HyperText Markup Language">HTML</acronym>. This may seem daunting at first if you&#8217;ve never worked this way before, but follow the listed links to learn more, and use the sample files as a guide.</span></p>
+ <p class="p3"><span>Download the sample <a href="zengarden-sample.html" title="This page's source HTML code, not to be modified.">html file</a> and <a href="zengarden-sample.css" title="This page's sample CSS, the file you may modify.">css file</a> to work on a copy locally. Once you have completed your masterpiece (and please, don&#8217;t submit half-finished work) upload your .css file to a web server under your control. <a href="http://www.mezzoblue.com/zengarden/submit/" title="Use the contact form to send us your CSS file">Send us a link</a> to the file and if we choose to use it, we will spider the associated images. Final submissions will be placed on our server.</span></p>
+ </div>
+
+ <div id="benefits">
+ <h3><span>Benefits</span></h3>
+ <p class="p1"><span>Why participate? For recognition, inspiration, and a resource we can all refer to when making the case for <acronym title="Cascading Style Sheets">CSS</acronym>-based design. This is sorely needed, even today. More and more major sites are taking the leap, but not enough have. One day this gallery will be a historical curiosity; that day is not today.</span></p>
+ </div>
+
+ <div id="requirements">
+ <h3><span>Requirements</span></h3>
+ <p class="p1"><span>We would like to see as much <acronym title="Cascading Style Sheets, version 1">CSS1</acronym> as possible. <acronym title="Cascading Style Sheets, version 2">CSS2</acronym> should be limited to widely-supported elements only. The css Zen Garden is about functional, practical <acronym title="Cascading Style Sheets">CSS</acronym> and not the latest bleeding-edge tricks viewable by 2% of the browsing public. The only real requirement we have is that your <acronym title="Cascading Style Sheets">CSS</acronym> validates.</span></p>
+ <p class="p2"><span>Unfortunately, designing this way highlights the flaws in the various implementations of <acronym title="Cascading Style Sheets">CSS</acronym>. Different browsers display differently, even completely valid <acronym title="Cascading Style Sheets">CSS</acronym> at times, and this becomes maddening when a fix for one leads to breakage in another. View the <a href="http://www.mezzoblue.com/zengarden/resources/" title="A listing of CSS-related resources">Resources</a> page for information on some of the fixes available. Full browser compliance is still sometimes a pipe dream, and we do not expect you to come up with pixel-perfect code across every platform. But do test in as many as you can. If your design doesn&#8217;t work in at least IE5+/Win and Mozilla (run by over 90% of the population), chances are we won&#8217;t accept it.</span></p>
+ <p class="p3"><span>We ask that you submit original artwork. Please respect copyright laws. Please keep objectionable material to a minimum; tasteful nudity is acceptable, outright pornography will be rejected.</span></p>
+ <p class="p4"><span>This is a learning exercise as well as a demonstration. You retain full copyright on your graphics (with limited exceptions, see <a href="http://www.mezzoblue.com/zengarden/submit/guidelines/">submission guidelines</a>), but we ask you release your <acronym title="Cascading Style Sheets">CSS</acronym> under a Creative Commons license identical to the <a href="http://creativecommons.org/licenses/sa/1.0/" title="View the Zen Garden's license information.">one on this site</a> so that others may learn from your work.</span></p>
+ <p class="p5"><span>Bandwidth graciously donated by <a href="http://www.dreamfirestudios.com/">DreamFire Studios</a></span></p>
+ </div>
+
+ <div id="footer">
+ <a href="http://validator.w3.org/check/referer" title="Check the validity of this site&#8217;s XHTML">xhtml</a> &nbsp;
+ <a href="http://jigsaw.w3.org/css-validator/check/referer" title="Check the validity of this site&#8217;s CSS">css</a> &nbsp;
+ <a href="http://creativecommons.org/licenses/by-nc-sa/1.0/" title="View details of the license of this site, courtesy of Creative Commons.">cc</a> &nbsp;
+ <a href="http://mezzoblue.com/zengarden/faq/#s508" title="Read about the accessibility of this site">508</a> &nbsp;
+ <a href="http://www.mezzoblue.com/zengarden/faq/#aaa" title="Read about the accessibility of this site">aaa</a>
+ </div>
+
+ </div>
+
+
+ <div id="linkList">
+ <!--extra div for flexibility - this list will probably be the trickiest spot you'll deal with -->
+ <div id="linkList2">
+
+ <!-- If you're wondering about the extra &nbsp; at the end of the link, it's a hack to meet WCAG 1 Accessibility. -->
+ <!-- I don't like having to do it, but this is a visual exercise. It's a compromise. -->
+ <div id="lselect">
+ <h3 class="select"><span>Select a Design:</span></h3>
+ <!-- list of links begins here. There will be no more than 8 links per page -->
+ <ul>
+ <li><a href="/" title="AccessKey: a" accesskey="a">Sample #1</a> by <a href="http://www.mezzoblue.com/" class="c">Dave Shea</a>&nbsp;</li>
+ <li><a href="/" title="AccessKey: b" accesskey="b">Sample #2</a> by <a href="http://www.mezzoblue.com/" class="c">Dave Shea</a>&nbsp;</li>
+ <li><a href="/" title="AccessKey: c" accesskey="c">Sample #3</a> by <a href="http://www.mezzoblue.com/" class="c">Dave Shea</a>&nbsp;</li>
+ <li><a href="/" title="AccessKey: d" accesskey="d">Sample #4</a> by <a href="http://www.mezzoblue.com/" class="c">Dave Shea</a>&nbsp;</li>
+ <li><a href="/" title="AccessKey: e" accesskey="e">Sample #5</a> by <a href="http://www.mezzoblue.com/" class="c">Dave Shea</a>&nbsp;</li>
+ <li><a href="/" title="AccessKey: f" accesskey="f">Sample #6</a> by <a href="http://www.mezzoblue.com/" class="c">Dave Shea</a>&nbsp;</li>
+ <li><a href="/" title="AccessKey: g" accesskey="g">Sample #7</a> by <a href="http://www.mezzoblue.com/" class="c">Dave Shea</a>&nbsp;</li>
+ <li><a href="/" title="AccessKey: h" accesskey="h">Sample #8</a> by <a href="http://www.mezzoblue.com/" class="c">Dave Shea</a>&nbsp;</li>
+ </ul>
+ </div>
+
+ <div id="larchives">
+ <h3 class="archives"><span>Archives:</span></h3>
+ <ul>
+ <li><a href="/" title="View next set of designs. AccessKey: n" accesskey="n"><span class="accesskey">n</span>ext designs &raquo;</a>&nbsp;</li>
+ <li><a href="/" title="View previous set of designs. AccessKey: p" accesskey="p">&laquo; <span class="accesskey">p</span>revious designs</a></li>
+ <li><a href="http://www.mezzoblue.com/zengarden/alldesigns/" title="View every submission to the Zen Garden. AccessKey: w" accesskey="w">Vie<span class="accesskey">w</span> All Designs</a></li>
+ </ul>
+ </div>
+
+ <div id="lresources">
+ <h3 class="resources"><span>Resources:</span></h3>
+ <ul>
+ <li><a href="http://www.csszengarden.com/001/001.css" title="View the source CSS file for the currently-viewed design, AccessKey: v" accesskey="v"><span class="accesskey">V</span>iew This Design&#8217;s <acronym title="Cascading Style Sheets">CSS</acronym></a></li>
+ <li><a href="http://www.mezzoblue.com/zengarden/resources/" title="Links to great sites with information on using CSS. AccessKey: r" accesskey="r"><acronym title="Cascading Style Sheets">CSS</acronym> <span class="accesskey">R</span>esources</a></li>
+ <li><a href="http://www.mezzoblue.com/zengarden/faq/" title="A list of Frequently Asked Questions about the Zen Garden. AccessKey: q" accesskey="q"><acronym title="Frequently Asked Questions">FA<span class="accesskey">Q</span></acronym></a>&nbsp;</li>
+ <li><a href="http://www.mezzoblue.com/zengarden/submit/" title="Send in your own CSS file. AccessKey: s" accesskey="s"><span class="accesskey">S</span>ubmit a Design</a></li>
+ <li><a href="http://www.mezzoblue.com/zengarden/translations/" title="View translated versions of this page. AccessKey: t" accesskey="t"><span class="accesskey">T</span>ranslations</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+
+
+</div>
+
+<!-- These extra divs/spans may be used as catch-alls to add extra imagery. -->
+<!-- Add a background image to each and use width and height to control sizing, place with absolute positioning -->
+<div id="extraDiv1"><span></span></div><div id="extraDiv2"><span></span></div><div id="extraDiv3"><span></span></div>
+<div id="extraDiv4"><span></span></div><div id="extraDiv5"><span></span></div><div id="extraDiv6"><span></span></div>
+
+</body>
+</html>
37 tests/test.css
@@ -0,0 +1,37 @@
+p {margin-top: 0;text-align: justify;}
+h3 {letter-spacing: 1px;margin-bottom: 0;}
+a:link {font-weight: bold;text-decoration: none;}
+a:visited {font-weight: bold;text-decoration: none;}
+a:hover, a:active {text-decoration: underline;}
+acronym {border-bottom: none;}
+#container {padding: 0 175px 0 110px;margin: 0;position: relative;}
+#intro {min-width: 470px;}
+#pageHeader h1 {margin-top: 10px;width: 219px;height: 87px;float: left;}
+#pageHeader h1 span {display: none;}
+#pageHeader h2 {margin-top: 58px;margin-bottom: 40px;width: 200px;height: 18px;float: right;}
+#pageHeader h2 span {display: none;}
+#pageHeader {padding-top: 20px;}
+#quickSummary {clear: both;margin: 20px 20px 20px 10px;width: 160px;float: left;}
+#quickSummary p {text-align: center;}
+#preamble {clear: right;padding: 0px 10px 0 10px;}
+#supportingText {padding-left: 10px;margin-bottom: 40px;}
+#footer {text-align: center;}
+#footer a:link, #footer a:visited {margin-right: 20px;}
+#linkList {margin-left: 600px;position: absolute;top: 0;right: 0;}
+#linkList2 {padding: 10px;margin-top: 150px;width: 130px;}
+#linkList h3.select {margin: 10px 0 5px 0;width: 97px;height: 16px;}
+#linkList h3.select span {display: none;}
+#linkList h3.favorites {margin: 25px 0 5px 0;width: 60px;height: 18px;}
+#linkList h3.favorites span {display: none;}
+#linkList h3.archives {margin: 25px 0 5px 0;width: 57px;height: 14px;}
+#linkList h3.archives span {display: none;}
+#linkList h3.resources {margin: 25px 0 5px 0;width: 63px;height: 10px;}
+#linkList h3.resources span {display: none;}
+#linkList ul {margin: 0;padding: 0;}
+#linkList li {line-height: 2.5ex;display: block;padding-top: 5px;margin-bottom: 5px;list-style-type: none;}
+#linkList li a:link {}
+#linkList li a:visited {}
+#extraDiv1 {position: absolute;top: 40px;right: 0;width: 148px;height: 110px;}
+.accesskey {text-decoration: underline;}
+body {color: blue;}
+html {color: red;}
1  vendor/Symfony/Component/ClassLoader
@@ -0,0 +1 @@
+Subproject commit 5cd07e40f6894c084cfc1eb02fd25d6005e6646c
1  vendor/Symfony/Component/Finder
@@ -0,0 +1 @@
+Subproject commit 8f0f77cf1e850f956415b0f36a59670cc21ded42
1  vendor/css-parser
@@ -0,0 +1 @@
+Subproject commit 51e12982a03b127af85ca13326eadd0d1d45e622
Please sign in to comment.
Something went wrong with that request. Please try again.