stapler-stapler-parent-1.218/0000775000175000017500000000000012206724733016620 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/0000775000175000017500000000000012206724733017737 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/0000775000175000017500000000000012206724733020526 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/main/0000775000175000017500000000000012206724733021452 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/main/java/0000775000175000017500000000000012206724733022373 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/main/java/org/0000775000175000017500000000000012206724733023162 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/0000775000175000017500000000000012206724733024633 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/0000775000175000017500000000000012206724733026305 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/0000775000175000017500000000000012206724733027424 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/FindAncestorTag.java0000664000175000017500000000621012206724733033301 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.NamespaceAwareTag; import org.apache.commons.jelly.Tag; import org.apache.commons.jelly.XMLOutput; import org.jvnet.maven.jellydoc.annotation.NoContent; import java.util.Map; /** * Finds the nearest tag (in the call stack) that has the given tag name, * and sets that as a variable. * * @author Kohsuke Kawaguchi */ @NoContent public class FindAncestorTag extends AbstractStaplerTag implements NamespaceAwareTag { private String tag; private String var; private Map nsMap; /** * Variable name to set the discovered {@link Tag} object. */ public void setVar(String var) { this.var = var; } /** * QName of the tag to look for. */ public void setTag(String tag) { this.tag = tag; } public void doTag(XMLOutput output) throws JellyTagException { // I don't think anyone is using this, but if we need to resurrect this, // we need to tweak CustomTagLibrary class and build up the stack of elements being processed. throw new UnsupportedOperationException(); // int idx = tag.indexOf(':'); // String prefix = tag.substring(0,idx); // String localName = tag.substring(idx+1); // // String uri = (String) nsMap.get(prefix); // // Tag tag = this; // while((tag=findAncestorWithClass(tag,StaplerDynamicTag.class))!=null) { // StaplerDynamicTag t = (StaplerDynamicTag)tag; // if(t.getLocalName().equals(localName) && t.getNsUri().equals(uri)) // break; // } // getContext().setVariable(var,tag); } public void setNamespaceContext(Map prefixToUriMap) { this.nsMap = prefixToUriMap; } } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/AdjunctTag.java0000664000175000017500000000662512206724733032324 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.XMLOutput; import org.kohsuke.stapler.framework.adjunct.AdjunctManager; import org.kohsuke.stapler.framework.adjunct.AdjunctsInPage; import org.xml.sax.SAXException; import org.jvnet.maven.jellydoc.annotation.NoContent; import org.jvnet.maven.jellydoc.annotation.Required; import java.io.IOException; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * Writes out links to adjunct CSS and JavaScript, if not done so already. * * @author Kohsuke Kawaguchi */ @NoContent public class AdjunctTag extends AbstractStaplerTag { private String[] includes; private String[] assumes; /** * Comma-separated adjunct names. */ public void setIncludes(String _includes) { includes = parse(_includes); } /** * Comma-separated adjunct names that are externally included in the page * and should be suppressed. */ public void setAssumes(String _assumes) { assumes = parse(_assumes); } private String[] parse(String s) { String[] r = s.split(","); for (int i = 0; i < r.length; i++) r[i] = r[i].trim(); return r; } public void doTag(XMLOutput out) throws JellyTagException { AdjunctManager m = AdjunctManager.get(getServletContext()); if(m==null) { LOGGER.log(Level.WARNING,"AdjunctManager is not installed for this application. Skipping tags", new Exception()); return; } try { AdjunctsInPage a = AdjunctsInPage.get(); if (assumes!=null) a.assumeIncluded(assumes); if (includes!=null) a.generate(out, includes); } catch (IOException e) { throw new JellyTagException(e); } catch (SAXException e) { throw new JellyTagException(e); } } private static final Logger LOGGER = Logger.getLogger(AdjunctTag.class.getName()); } ././@LongLink0000644000000000000000000000015012255653646011654 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/AnnotationProcessorImpl.javastapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/AnnotationProcessorImpl.j0000664000175000017500000000743012206724733034437 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.kohsuke.MetaInfServices; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Processor; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import javax.tools.Diagnostic.Kind; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * @author Kohsuke Kawaguchi */ @SuppressWarnings({"Since15"}) //@MetaInfServices(Processor.class) public class AnnotationProcessorImpl extends AbstractProcessor { private final Map missingViews = new HashMap(); private static class MissingViews extends HashSet {} @Override public Set getSupportedAnnotationTypes() { return Collections.singleton("*"); } @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if (roundEnv.processingOver()) return false; missingViews.clear(); for (TypeElement t : ElementFilter.typesIn(roundEnv.getRootElements())) { check(t); } missingViews.clear(); return false; } private MissingViews check(TypeElement t) { MissingViews r = missingViews.get(t); if (r==null) { r = new MissingViews(); missingViews.put(t,r); r.addAll(check(t.getSuperclass())); for (TypeMirror i : t.getInterfaces()) r.addAll(check(i)); RequiresView a = t.getAnnotation(RequiresView.class); if (a!=null) r.addAll(Arrays.asList(a.value())); if (!r.isEmpty() && !t.getModifiers().contains(Modifier.ABSTRACT)) { processingEnv.getMessager().printMessage(Kind.ERROR, t.getQualifiedName()+" is missing views: "+r,t); } } return r; } private MissingViews check(TypeMirror t) { if (t.getKind()== TypeKind.DECLARED) return check((TypeElement)((DeclaredType)t).asElement()); return EMPTY; } private static final MissingViews EMPTY = new MissingViews(); } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/CallTagLibScript.java0000664000175000017500000001321112206724733033410 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.JellyException; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.Script; import org.apache.commons.jelly.XMLOutput; import org.apache.commons.jelly.expression.Expression; import org.apache.commons.jelly.impl.DynamicTag; import org.apache.commons.jelly.impl.ExpressionAttribute; import org.apache.commons.jelly.impl.TagScript; import org.xml.sax.SAXException; import java.util.HashMap; import java.util.Map; /** * {@link TagScript} that invokes a {@link Script} as a tag. * * @author Kohsuke Kawaguchi */ public abstract class CallTagLibScript extends TagScript { /** * Resolves to the definition of the script to call to. */ protected abstract Script resolveDefinition(JellyContext context) throws JellyTagException; @Override public void run(final JellyContext context, XMLOutput output) throws JellyTagException { // evaluated values of the attributes Map args = new HashMap(attributes.size()); for (Map.Entry e : attributes.entrySet()) { Expression expression = e.getValue().exp; args.put(e.getKey(),expression.evaluate(context)); } // create new context based on current attributes JellyContext newJellyContext = context.newJellyContext(args); newJellyContext.setVariable( "attrs", args ); // uses this to discover what to invoke newJellyContext.setVariable("org.apache.commons.jelly.body", new Script() { public Script compile() throws JellyException { return this; } /** * When <d:invokeBody/> is used to call back into the calling script, * the Jelly name resolution rule is in such that the body is evaluated with * the variable scope of the <d:invokeBody/> caller. This is very different * from a typical closure name resolution mechanism, where the body is evaluated * with the variable scope of where the body was created. * *

* More concretely, in Jelly, this often shows up as a problem as inability to * access the "attrs" variable from inside a body, because every {@link DynamicTag} * invocation sets this variable in a new scope. * *

* To counter this effect, this class temporarily restores the original "attrs" * when the body is evaluated. This makes the name resolution of 'attrs' work * like what programmers normally expect. * *

* The same problem also shows up as a lack of local variables — when a tag * calls into the body via <d:invokeBody/>, the invoked body will see all the * variables that are defined in the caller, which is again not what a normal programming language * does. But unfortunately, changing this is too pervasive. */ public void run(JellyContext nestedContext, XMLOutput output) throws JellyTagException { Map m = nestedContext.getVariables(); Object oldAttrs = m.put("attrs",context.getVariable("attrs")); try { getTagBody().run(nestedContext,output); } finally { m.put("attrs",oldAttrs); } } }); newJellyContext.setVariable("org.apache.commons.jelly.body.scope", context); final Script def = resolveDefinition(newJellyContext); if(JellyFacet.TRACE) { try { String source = getSource(); String msg = "<" + source+">"; output.comment(msg.toCharArray(),0,msg.length()); def.run(newJellyContext, output); msg = ""; output.comment(msg.toCharArray(),0,msg.length()); } catch (SAXException e) { throw new JellyTagException(e); } } else { def.run(newJellyContext, output); } } protected String getSource() { return "{jelly:"+getNsUri()+"}:"+getLocalName(); } } ././@LongLink0000644000000000000000000000014712255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/JellyRequestDispatcher.javastapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/JellyRequestDispatcher.ja0000664000175000017500000000544312206724733034405 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.Script; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.WebApp; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.io.IOException; /** * @author Kohsuke Kawaguchi */ public final class JellyRequestDispatcher implements RequestDispatcher { private final Object it; private final Script script; private final JellyFacet facet; public JellyRequestDispatcher(Object it, Script script) { this.it = it; this.script = script; facet = WebApp.getCurrent().getFacet(JellyFacet.class); } public void forward(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { try { facet.scriptInvoker.invokeScript( (StaplerRequest)servletRequest, (StaplerResponse)servletResponse, script, it); } catch (JellyTagException e) { throw new ServletException(e); } } public void include(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { forward(servletRequest,servletResponse); } } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/IsUserInRoleTag.java0000664000175000017500000000436712206724733033260 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.MissingAttributeException; import org.apache.commons.jelly.XMLOutput; import org.jvnet.maven.jellydoc.annotation.Required; import javax.servlet.http.HttpServletRequest; /** * @author Kohsuke Kawaguchi */ public class IsUserInRoleTag extends AbstractStaplerTag { private String role; /** * The name of the role against which the user is checked. */ @Required public void setRole(String role) { this.role = role; } public void doTag(XMLOutput output) throws MissingAttributeException, JellyTagException { HttpServletRequest req = getRequest(); // work around http://jira.codehaus.org/browse/JETTY-234 req.getUserPrincipal(); if(req.isUserInRole(role)) getBody().run(getContext(),output); } } ././@LongLink0000644000000000000000000000015512255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/StructuredMessageArgumentTag.javastapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/StructuredMessageArgument0000664000175000017500000000431612206724733034527 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.XMLOutput; import java.io.StringWriter; /** * Body is evaluated and is used as an argument for the surrounding <structuredMessageFormat> element. * * @author Kohsuke Kawaguchi */ public class StructuredMessageArgumentTag extends AbstractStaplerTag { public void doTag(XMLOutput output) throws JellyTagException { StructuredMessageFormatTag tag = (StructuredMessageFormatTag)findAncestorWithClass(StructuredMessageFormatTag.class); if(tag == null) throw new JellyTagException("This tag must be enclosed inside a tag" ); StringWriter sw = new StringWriter(); XMLOutput o = XMLOutput.createXMLOutput(sw); invokeBody(o); tag.addArgument(sw); } } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/ThisTagLibrary.java0000664000175000017500000001033612206724733033162 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.JellyException; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.Script; import org.apache.commons.jelly.Tag; import org.apache.commons.jelly.TagLibrary; import org.apache.commons.jelly.expression.Expression; import org.apache.commons.jelly.expression.ExpressionSupport; import org.apache.commons.jelly.impl.TagScript; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.lang.Klass; import org.xml.sax.Attributes; /** * Loads Jelly views associated with "it" as if it were taglibs. * * @author Kohsuke Kawaguchi */ public class ThisTagLibrary extends TagLibrary { private final Expression expr; /** * @param expr * Expression that evaluates to {@link Class} to resolve scripts from. */ public ThisTagLibrary(Expression expr) { this.expr = expr; } /** * IIUC, this method will never be invoked. */ @Override public Tag createTag(final String name, Attributes attributes) throws JellyException { return null; } @Override public TagScript createTagScript(final String tagName, Attributes atts) throws JellyException { return new CallTagLibScript() { @Override protected Script resolveDefinition(JellyContext context) throws JellyTagException { Object it = expr.evaluate(context); if (it==null) throw new JellyTagException("'"+ expr.getExpressionText() +"' evaluated to null"); try { WebApp webApp = WebApp.getCurrent(); MetaClass c = webApp.getMetaClass(it instanceof Class ? Klass.java((Class)it): webApp.getKlass(it)); // prefer 'foo.jellytag' to avoid tags from showing up as views, // but for backward compatibility, support the plain .jelly extention as well. Script tag = c.loadTearOff(JellyClassTearOff.class).findScript(tagName+".jellytag"); if (tag==null) tag = c.loadTearOff(JellyClassTearOff.class).findScript(tagName+".jelly"); if (tag ==null) throw new JellyTagException("No such tag file "+tagName+".jellytag in "+c); return tag; } catch (JellyException e) { throw new JellyTagException("Failed to load "+tagName+".jellytag from "+it,e); } } }; } public static final ThisTagLibrary INSTANCE = new ThisTagLibrary(new ExpressionSupport() { public String getExpressionText() { return "it"; } public Object evaluate(JellyContext context) { return context.getVariable("it"); } }); } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/JellyClassTearOff.java0000664000175000017500000001335212206724733033607 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyException; import org.apache.commons.jelly.Script; import org.kohsuke.stapler.AbstractTearOff; import static org.kohsuke.stapler.Dispatcher.trace; import static org.kohsuke.stapler.Dispatcher.traceable; import org.kohsuke.stapler.Facet; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.WebApp; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import java.io.IOException; import java.net.URL; import java.util.logging.Logger; /** * @author Kohsuke Kawaguchi */ public class JellyClassTearOff extends AbstractTearOff { private JellyFacet facet; public JellyClassTearOff(MetaClass owner) { super(owner,JellyClassLoaderTearOff.class); facet = WebApp.getCurrent().getFacet(JellyFacet.class); } protected Script parseScript(URL res) throws JellyException { return new JellyViewScript(owner.klass, res, classLoader.createContext().compileScript(res)); } @Override protected String getDefaultScriptExtension() { return ".jelly"; } @Override protected boolean hasAllowedExtension(String name) { return name.endsWith(".jelly") || name.endsWith(".jellytag"); } /** * Aside from looking into our own, consult other facets that can handle Jelly-compatible scripts. */ @Override public Script resolveScript(String name) throws JellyException { // cut off the extension so that we can search all the extensions String shortName; int dot = name.lastIndexOf('.'); if (dot>name.lastIndexOf('/')) shortName = name.substring(0, dot); else shortName = name; for (Facet f : owner.webApp.facets) { if (f instanceof JellyCompatibleFacet && !(f instanceof JellyFacet)) { JellyCompatibleFacet jcf = (JellyCompatibleFacet) f; for (Class> ct : jcf.getClassTearOffTypes()) { try { Script s = owner.loadTearOff(ct).resolveScript(shortName); if (s!=null) return s; } catch (Exception e) { throw new JellyException("Failed to load "+shortName+" from "+jcf,e); } } } } return super.resolveScript(name); } /** * Serves index.jelly if it's available, and returns true. */ public boolean serveIndexJelly(StaplerRequest req, StaplerResponse rsp, Object node) throws ServletException, IOException { try { Script script = findScript("index.jelly"); if(script!=null) { if(traceable()) { String src = "index.jelly"; if (script instanceof JellyViewScript) { JellyViewScript jvs = (JellyViewScript) script; src = jvs.getName(); } trace(req,rsp,"-> %s on <%s>",src,node); } facet.scriptInvoker.invokeScript(req, rsp, script, node); return true; } return false; } catch (JellyException e) { throw new ServletException(e); } } /** * Creates a {@link RequestDispatcher} that forwards to the jelly view, if available. */ public RequestDispatcher createDispatcher(Object it, String viewName) throws IOException { try { // backward compatible behavior that expects full file name including ".jelly" Script script = findScript(viewName); if(script!=null) return new JellyRequestDispatcher(it,script); // this is what the look up was really supposed to be. script = findScript(viewName+".jelly"); if(script!=null) return new JellyRequestDispatcher(it,script); return null; } catch (JellyException e) { IOException io = new IOException(e.getMessage()); io.initCause(e); throw io; } } private static final Logger LOGGER = Logger.getLogger(JellyClassTearOff.class.getName()); } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/ResourceBundle.java0000664000175000017500000001600712206724733033214 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.WebApp; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.net.URL; import java.text.MessageFormat; import java.util.Collections; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; /** * Cache of localization strings. * * @author Kohsuke Kawaguchi */ public class ResourceBundle { /** * URL to load message resources from, except the ".properties" suffix. *

* This is normally something like file://path/to/somewhere/org/acme/Foo. */ private final String baseName; /** * Loaded messages. */ private final Map resources = new ConcurrentHashMap(); public ResourceBundle(String baseName) { this.baseName = baseName; } public String getBaseName() { return baseName; } public String format(Locale locale, String key, Object... args) { String str = getFormatString(locale, key); if(str==null) // see http://www.nabble.com/i18n-and-l10n-problems-td16004047.html for more discussion // return MessageFormat.format(key,args); return key; return MessageFormat.format(str,args); } /** * Gets the format string for the given key. *

* This method performs a search so that a look up for "pt_BR" would delegate * to "pt" then "" (the no-locale locale.) */ public String getFormatString(Locale locale, String key) { String[] suffixes = toStrings(locale); while(true) { for (int i=0; i0) // ignore a definition without value, because stapler:i18n generates // value-less definitions return msg; int idx = suffix.lastIndexOf('_'); if(idx<0) // failed to find return null; suffixes[i] = suffix.substring(0,idx); } } } /** * Works like {@link #getFormatString(Locale, String)} except there's no * searching up the delegation chain. */ public String getFormatStringWithoutDefaulting(Locale locale, String key) { for (String s : toStrings(locale)) { String msg = get(s).getProperty(key); if(msg!=null && msg.length()>0) return msg; } return null; } /** * Some language codes have changed over time, such as Hebrew from iw to he. * This method returns all such variations in an array. * * @see Locale#getLanguage() */ private String[] toStrings(Locale l) { String v = ISO639_MAP.get(l.getLanguage()); if (v==null) return new String[]{'_'+l.toString()}; else return new String[]{'_'+l.toString(), '_'+v+l.toString().substring(2)}; } protected void clearCache() { resources.clear(); } protected Properties get(String key) { Properties props; if(!MetaClass.NO_CACHE) { props = resources.get(key); if(props!=null) return props; } // attempt to load props = new Properties(); String url = baseName + key + ".properties"; InputStream in=null; try { in = new URL(url).openStream(); // an user reported that on IBM JDK, URL.openStream // returns null instead of IOException. // see http://www.nabble.com/WAS---Hudson-tt16026561.html } catch (IOException e) { // failed. } if(in!=null) { try { try { props.load(in); } finally { in.close(); } } catch (IOException e) { throw new Error("Failed to load "+url,e); } } resources.put(key,wrapUp(key.length()>0 ? key.substring(1) : "",props)); return props; } /** * Interception point for property loading. */ protected Properties wrapUp(String locale, Properties props) { return props; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ResourceBundle that = (ResourceBundle) o; return baseName.equals(that.baseName); } @Override public int hashCode() { return baseName.hashCode(); } public static ResourceBundle load(URL jellyUrl) { return load(jellyUrl.toExternalForm()); } /** * Loads the resource bundle associated with the Jelly script. */ public static ResourceBundle load(String jellyUrl) { if(jellyUrl.endsWith(".jelly")) // cut the trailing .jelly jellyUrl = jellyUrl.substring(0,jellyUrl.length()-".jelly".length()); JellyFacet facet = WebApp.getCurrent().getFacet(JellyFacet.class); return facet.resourceBundleFactory.create(jellyUrl); } /** * JDK internally converts new ISO-639 code back to old code. This table provides reverse mapping. */ private static final Map ISO639_MAP = new HashMap(); static { ISO639_MAP.put("iw","he"); ISO639_MAP.put("ji","yi"); ISO639_MAP.put("in","id"); } } ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/InternationalizedStringExpression.javastapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/InternationalizedStringEx0000664000175000017500000002024012206724733034514 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.expression.Expression; import org.apache.commons.jelly.expression.ExpressionSupport; import org.apache.commons.jelly.JellyException; import org.apache.commons.jelly.JellyContext; import org.jvnet.localizer.LocaleProvider; import org.kohsuke.stapler.Stapler; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.ArrayList; import java.util.Collections; import java.util.Arrays; /** * Expression of the form "%messageName(arg1,arg2,...)" that represents * internationalized text. * *

* The "(arg1,...)" portion is optional and can be ommitted. Each argument * is assumed to be a parenthesis-balanced expression and passed to * {@link JellyClassLoaderTearOff#EXPRESSION_FACTORY} to be parsed. * *

* The message resource is loaded from files like "xyz.properties" and * "xyz_ja.properties" when the expression is placed in "xyz.jelly". * * * @author Kohsuke Kawaguchi */ public class InternationalizedStringExpression extends ExpressionSupport { public final ResourceBundle resourceBundle; private final Expression[] arguments; public final String key; public final String expressionText; public InternationalizedStringExpression(ResourceBundle resourceBundle, String text) throws JellyException { this.resourceBundle = resourceBundle; this.expressionText = text; if(!text.startsWith("%")) throw new JellyException(text+" doesn't start with %"); text = text.substring(1); int idx = text.indexOf('('); if(idx<0) { // no arguments key = text; arguments = EMPTY_ARGUMENTS; return; } List args = new ArrayList(); key = text.substring(0,idx); text = text.substring(idx+1); // at this point text="arg,arg)" while(text.length()>0) { String token = tokenize(text); args.add(JellyClassLoaderTearOff.EXPRESSION_FACTORY.createExpression(token)); text = text.substring(token.length()+1); } this.arguments = args.toArray(new Expression[args.size()]); } public List getArguments() { return Collections.unmodifiableList(Arrays.asList(arguments)); } /** * Takes a string like "arg)" or "arg,arg,...)", then * find "arg" and returns it. * * Note: this code is also copied into idea-stapler-plugin, * so don't forget to update that when this code changes. */ private String tokenize(String text) throws JellyException { int parenthesis=0; for(int idx=0;idx"); } catch (IOException e) { throw new JellyTagException(e); } } } ././@LongLink0000644000000000000000000000017212255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/InternationalizedStringExpressionListener.javastapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/InternationalizedStringEx0000664000175000017500000000322112206724733034514 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; /** * Receives a notification of the {@link InternationalizedStringExpression} usage. * * @author Kohsuke Kawaguchi */ public interface InternationalizedStringExpressionListener { void onUsed(InternationalizedStringExpression exp, Object[] args); } ././@LongLink0000644000000000000000000000014612255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/ResourceBundleFactory.javastapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/ResourceBundleFactory.jav0000664000175000017500000000330512206724733034400 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; /** * Factory for {@link ResourceBundle}s. * * @author Kohsuke Kawaguchi */ public class ResourceBundleFactory { public ResourceBundle create(String baseName) { return new ResourceBundle(baseName); } public static final ResourceBundleFactory INSTANCE = new ResourceBundleFactory(); } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/ContentTypeTag.java0000664000175000017500000000462312206724733033204 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.MissingAttributeException; import org.apache.commons.jelly.XMLOutput; import org.jvnet.maven.jellydoc.annotation.Required; import org.jvnet.maven.jellydoc.annotation.NoContent; import javax.servlet.http.HttpServletResponse; /** * Set the HTTP Content-Type header of the page. * * @author Kohsuke Kawaguchi */ @NoContent public class ContentTypeTag extends AbstractStaplerTag { private String contentType; /** * The content-type value, such as "text/html". */ @Required public void setValue(String contentType) { this.contentType = contentType; } public void doTag(XMLOutput output) throws MissingAttributeException, JellyTagException { HttpServletResponse rsp = getResponse(); if (rsp!=null) rsp.setContentType(contentType); if (output instanceof HTMLWriterOutput) ((HTMLWriterOutput)output).useHTML(contentType.startsWith("text/html")); } } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/NbspTag.java0000664000175000017500000000403712206724733031631 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.MissingAttributeException; import org.apache.commons.jelly.TagSupport; import org.apache.commons.jelly.XMLOutput; import org.xml.sax.SAXException; import org.jvnet.maven.jellydoc.annotation.NoContent; /** * Writes out '&nbsp;'. * * @author Kohsuke Kawaguchi */ @NoContent public class NbspTag extends TagSupport { public void doTag(XMLOutput output) throws MissingAttributeException, JellyTagException { try { output.write("\u00A0"); // nbsp } catch (SAXException e) { throw new JellyTagException(e); } } } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/DefaultScriptInvoker.java0000664000175000017500000001632312206724733034403 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.kohsuke.stapler.Stapler; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.apache.commons.jelly.Script; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.XMLOutput; import org.apache.commons.jelly.XMLOutputFactory; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.impl.TagScript; import javax.servlet.ServletContext; import java.io.IOException; import java.io.OutputStream; import java.io.BufferedOutputStream; import java.io.FilterOutputStream; import java.io.Writer; import java.util.Enumeration; /** * Standard implementation of {@link ScriptInvoker}. * * @author Kohsuke Kawaguchi */ public class DefaultScriptInvoker implements ScriptInvoker, XMLOutputFactory { public void invokeScript(StaplerRequest req, StaplerResponse rsp, Script script, Object it) throws IOException, JellyTagException { XMLOutput xmlOutput = createXMLOutput(req, rsp, script, it); invokeScript(req,rsp,script,it,xmlOutput); xmlOutput.flush(); xmlOutput.close(); } public void invokeScript(StaplerRequest req, StaplerResponse rsp, Script script, Object it, XMLOutput out) throws IOException, JellyTagException { JellyContext context = createContext(req,rsp,script,it); exportVariables(req, rsp, script, it, context); script.run(context,out); } protected XMLOutput createXMLOutput(StaplerRequest req, StaplerResponse rsp, Script script, Object it) throws IOException { // TODO: make XMLOutput auto-close OutputStream to avoid leak HTMLWriterOutput hwo = HTMLWriterOutput.create(createOutputStream(req, rsp, script, it)); String ct = rsp.getContentType(); if (ct != null && !ct.startsWith("text/html")) hwo.useHTML(false); return hwo; } private boolean doCompression(Script script) { if (COMPRESS_BY_DEFAULT) return true; if (script instanceof TagScript) { TagScript ts = (TagScript) script; if(ts.getLocalName().equals("compress")) return true; } return false; } protected OutputStream createOutputStream(StaplerRequest req, StaplerResponse rsp, Script script, Object it) throws IOException { // do we want to do compression? OutputStream output=null; if (doCompression(script)) output = rsp.getCompressedOutputStream(req); if(output==null) // nope output = new BufferedOutputStream(rsp.getOutputStream()); output = new FilterOutputStream(output) { public void flush() { // flushing ServletOutputStream causes Tomcat to // send out headers, making it impossible to set contentType from the script. // so don't let Jelly flush. } public void write(byte b[], int off, int len) throws IOException { out.write(b, off, len); } }; return output; } protected void exportVariables(StaplerRequest req, StaplerResponse rsp, Script script, Object it, JellyContext context) { Enumeration en = req.getAttributeNames(); // expose request attributes, just like JSP while (en.hasMoreElements()) { String name = (String) en.nextElement(); context.setVariable(name,req.getAttribute(name)); } context.setVariable("request",req); context.setVariable("response",rsp); context.setVariable("it",it); ServletContext servletContext = req.getServletContext(); context.setVariable("servletContext",servletContext); context.setVariable("app",servletContext.getAttribute("app")); // property bag to store request scope variables context.setVariable("requestScope",context.getVariables()); // this variable is needed to make "jelly:fmt" taglib work correctly context.setVariable("org.apache.commons.jelly.tags.fmt.locale",req.getLocale()); } protected JellyContext createContext(final StaplerRequest req, StaplerResponse rsp, Script script, Object it) { CustomJellyContext context = new CustomJellyContext(); // let Jelly see the whole classes context.setClassLoader(req.getWebApp().getClassLoader()); // so TagScript.getBodyText() will use HTMLWriterOutput context.setVariable(XMLOutputFactory.class.getName(), this); return context; } public XMLOutput createXMLOutput(Writer writer, boolean escapeText) { StaplerResponse rsp = Stapler.getCurrentResponse(); String ct = rsp!=null ? rsp.getContentType() : "?"; if (ct != null && !ct.startsWith("text/html")) return XMLOutput.createXMLOutput(writer, escapeText); return HTMLWriterOutput.create(writer, escapeText); } /** * Whether gzip compression of the dynamic content is enabled by default or not. * *

* For non-trivial web applications, where the performance matters, it is normally a good trade-off to spend * a bit of CPU cycles to compress data. This is because: * *

    *
  • CPU is already 1 or 2 order of magnitude faster than RAM and network. *
  • CPU is getting faster than any other components, such as RAM and network. *
  • Because of the TCP window slow start, on a large latency network, compression makes difference in * the order of 100ms to 1sec to the completion of a request by saving multiple roundtrips. *
* * Stuff rendered by Jelly is predominantly text, so the compression would work well. * * @see http://www.slideshare.net/guest22d4179/latency-trumps-all */ public static boolean COMPRESS_BY_DEFAULT = Boolean.parseBoolean(System.getProperty(DefaultScriptInvoker.class.getName()+".compress","true")); } ././@LongLink0000644000000000000000000000015012255653646011654 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/AttributeConstraintsTag.javastapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/AttributeConstraintsTag.j0000664000175000017500000000402612206724733034430 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.TagSupport; import org.apache.commons.jelly.XMLOutput; import org.jvnet.maven.jellydoc.annotation.Required; /** * DTD-like expression that specifies the consraints on attribute appearances. * *

* This tag should be placed right inside {@link DocumentationTag} * to describe attributes of a tag. * * @author Kohsuke Kawaguchi */ public class AttributeConstraintsTag extends TagSupport { public void doTag(XMLOutput output) { // noop } /** * Constraint expression. */ @Required public void setExpr(String v) {} } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/JellyTagFileLoader.java0000664000175000017500000000423512206724733033735 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.kohsuke.stapler.Facet; import org.apache.commons.jelly.Script; import org.apache.commons.jelly.JellyException; import java.util.List; /** * Extension point that lets Jelly scripts written in other languages. * * @author Kohsuke Kawaguchi */ public abstract class JellyTagFileLoader { /** * Loads a tag file for the given tag library. * * @return null * if this loader didn't find the script. */ public abstract Script load(CustomTagLibrary taglib, String name, ClassLoader classLoader) throws JellyException; /** * Discovers all the facets in the classloader. */ public static List discover(ClassLoader cl) { return Facet.discoverExtensions(JellyTagFileLoader.class,cl); } } stapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/jelly/BindTag.java0000664000175000017500000001215012206724733031576 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.XMLOutput; import org.jvnet.maven.jellydoc.annotation.NoContent; import org.jvnet.maven.jellydoc.annotation.Required; import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.bind.Bound; import org.kohsuke.stapler.framework.adjunct.AdjunctsInPage; import org.xml.sax.SAXException; /** * Binds a server-side object to client side so that JavaScript can call into server. * This tag evaluates to a <script> tag. * * @author Kohsuke Kawaguchi */ @NoContent public class BindTag extends AbstractStaplerTag { private String varName; private Object javaObject; /** * JavaScript variable name to set the proxy to. *

* This name can be arbitrary left hand side expression, * such as "a[0]" or "a.b.c". * * If this value is unspecified, the tag generates a JavaScript expression to create a proxy. */ public void setVar(String varName) { this.varName = varName; } @Required public void setValue(Object o) { this.javaObject = o; } public void doTag(XMLOutput out) throws JellyTagException { // make sure we get the supporting script in place ensureDependencies(out); AdjunctTag a = new AdjunctTag(); a.setContext(getContext()); a.setIncludes("org.kohsuke.stapler.bind"); a.doTag(out); try { String expr; if (javaObject==null) { expr = "null"; } else { Bound h = WebApp.getCurrent().boundObjectTable.bind(javaObject); expr = h.getProxyScript(); } if (varName==null) { // this mode (of writing just the expression) needs to be used with caution because // the adjunct tag above might produce "); } public enum Kind { CSS, JS } /** * "@include fully.qualified.name" in a block or line comment. */ private static final Pattern INCLUDE = Pattern.compile("/[/*]\\s*@include (\\S+)"); /** * <@include fully.qualified.name> */ private static final Pattern HTML_INCLUDE = Pattern.compile("<@include (\\S+)>"); private static final Charset UTF8 = Charset.forName("UTF-8"); } ././@LongLink0000644000000000000000000000015312255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctsInPage.javastapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctsInPag0000664000175000017500000001436512206724733034360 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.framework.adjunct; import org.apache.commons.jelly.XMLOutput; import org.kohsuke.stapler.Stapler; import org.kohsuke.stapler.StaplerRequest; import org.xml.sax.SAXException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; /** * This request-scope object keeps track of which {@link Adjunct}s are already included. * * @author Kohsuke Kawaguchi */ public class AdjunctsInPage { private final AdjunctManager manager; /** * All adjuncts that are already included in the page. */ private final Set included = new HashSet(); /** * {@link Adjunct}s that haven't written to HTML yet because <head> * tag hasn't been written yet. */ private final List pending = new ArrayList(); private final StaplerRequest request; /** * Obtains the instance associated with the current request of the given {@link StaplerRequest}. */ public static AdjunctsInPage get() { return get(Stapler.getCurrentRequest()); } /** * Obtains the instance associated with the current request of the given {@link StaplerRequest}. * *

* This method is handy when the caller already have the request object around, * so that we can save {@link Stapler#getCurrentRequest()} call. */ public static AdjunctsInPage get(StaplerRequest request) { AdjunctsInPage aip = (AdjunctsInPage) request.getAttribute(KEY); if(aip==null) request.setAttribute(KEY,aip=new AdjunctsInPage(AdjunctManager.get(request.getServletContext()),request)); return aip; } private AdjunctsInPage(AdjunctManager manager,StaplerRequest request) { this.manager = manager; this.request = request; } /** * Gets what has been already included/assumed. * * This method returns a live unmodifiable view of what's included. * So if at some later point more adjuncts are loaded, the view * obtained earlier will reflect that. */ public Set getIncluded() { return Collections.unmodifiableSet(included); } /** * Checks if something has already been included/assumed. */ public boolean isIncluded(String include) { return included.contains(include); } /** * Generates the script tag and CSS link tag to include necessary adjuncts, * and records the fact that those adjuncts are already included in the page, * so that it won't be loaded again. */ public void generate(XMLOutput out, String... includes) throws IOException, SAXException { List needed = new ArrayList(); for (String include : includes) findNeeded(include,needed); for (Adjunct adj : needed) adj.write(request,out); } /** * When you include your version of the adjunct externally, you can use * this method to inform {@link AdjunctsInPage} that those adjuncts are * already included in the page. */ public void assumeIncluded(String... includes) throws IOException, SAXException { assumeIncluded(Arrays.asList(includes)); } public void assumeIncluded(Collection includes) throws IOException, SAXException { List needed = new ArrayList(); for (String include : includes) findNeeded(include,needed); } /** * Works like the {@link #generate(XMLOutput, String...)} method * but just put the adjuncts to {@link #pending} without writing it. */ public void spool(String... includes) throws IOException, SAXException { for (String include : includes) findNeeded(include,pending); } /** * Writes out what's spooled by {@link #spool(String...)} method. */ public void writeSpooled(XMLOutput out) throws SAXException, IOException { for (Adjunct adj : pending) adj.write(request,out); pending.clear(); } /** * Builds up the needed adjuncts into the 'needed' list. */ private void findNeeded(String include, List needed) throws IOException { if(!included.add(include)) return; // already sent // list dependencies first try { Adjunct a = manager.get(include); for (String req : a.required) findNeeded(req,needed); needed.add(a); } catch (NoSuchAdjunctException e) { LOGGER.log(Level.WARNING, "No such adjunct found: "+include,e); } } private static final String KEY = AdjunctsInPage.class.getName(); private static final Logger LOGGER = Logger.getLogger(AdjunctsInPage.class.getName()); } ././@LongLink0000644000000000000000000000015112255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/package-info.javastapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/package-info.0000664000175000017500000001145212206724733034262 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ /** * JavaScript/CSS packaging mechanism. * *

* A part of writing a web application involves reusing JavaScript libraries that are developed by 3rd parties. * Such JavaScript libraries often come in a package of js files, CSS, images, and so on. To integrate those * libraries to your application, you often need to do: * *

    *
  • Copy files into the webapp resource directories. *
  • If the JavaScript library depends on other JavaScript libraries, copy those, too. *
  • For each page where you use them, write script and link tags to load images and CSS, as well as their dependencies. *
* *

* This tediousness hurts the small-scale reusability of JavaScript libraries. * The adjunct framework in Stapler attempts to solve this by allowing libraries/components to express * dependencies among themselves, and grouping CSS and JavaScript together, so that a single "inclusion" * would include everything that a JavaScript library needs. * *

What packagers do

*
    *
  1. * Package JavaScript libraries as a jar file, including CSS and asset files, typically through Maven. * CSS (*.css), JavaScript (*.js), and HTML (*.html) that are only different by their extensions are grouped * into "adjunct", which becomes the unit of dependency management. All three aspects of an adjunct is optional. * More about what these files do later. * *
  2. * If this library depends on other libraries, use Maven's dependency management to have the resulting jars * express dependencies. * *
  3. * Express dependencies among adjuncts. * *
* * *

What webapp developers do

*
    *
  1. * Include adjunct jar files into WEB-INF/libs either directly or indirectly, typically via Maven. * *
  2. * Bind {@link AdjunctManager} to URL by using Stapler. This object serves adjunct JavaScript, CSS, images, and so on. * *
  3. * Use <st:adjunct> tag to load adjunct into the page. This tag expands to the <script> and <link> tags * for the adjunct itself and all the dependencies. It also remembers what adjuncts are already loaded into the page, * so when multiple <st:adjunt> tags are used to load different libraries, it won't repeatedly load the same script. * *
* * *

Adjunct

*

Name

*

* Adjuncts are identified by their fully qualified names, which is the package name + base name of the file name * (this is just like how a Java class gets its FQCN.) * *

Expressing dependencies

*

* Lines of the following form in JavaScript and CSS are interpreted by the adjunct framework to express * dependencies to other adjuncts. They have to start at the beginning of the line, without a leading whitespace. *

 * // @include fully.qualified.adjunct.name
 * /* @include fully.qualified.adjunct.name
 * 
*

* HTML file can have the following line to indicate a dependency. *

 * <@include fully.qualified.adjunct.name>
 * 
* *

Page injection

*

* Stapler loads an adjunct into a page by generating a link tag and a script tag to load the JS and CSS files, * respectively. The URLs these tags point to are served by {@link AdjunctManager}. If an HTML file is a part of an adjunct, * its content is just included inline along with script and link tags. This is useful to write a glue to load a large * 3rd party JavaScript libraries without modifying them or changing their names. */ package org.kohsuke.stapler.framework.adjunct; ././@LongLink0000644000000000000000000000015312255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctManager.javastapler-stapler-parent-1.218/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctManage0000664000175000017500000002007712206724733034364 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.framework.adjunct; import org.kohsuke.stapler.*; import javax.servlet.ServletException; import javax.servlet.ServletContext; import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; import java.io.IOException; import java.net.URL; import java.util.concurrent.ConcurrentHashMap; /** * This application-scoped object that exposes djuncts to URL. * *

* Adjuncts are packaging of JavaScript, CSS, and other static assets in jar files with dependency * information between them. This allows JavaScript libraries and other static assets to be reused * across different projects through Maven/Ivy. * *

* To use {@link AdjunctManager} in your application, create one instance, and bind it to URL * (like you do any other objects.) The most typical way of doing this is to define it as a * field in your top-level object. * *

 * public class MyApplication {
 *     public final AdjunctManager adjuncts = new AdjunctManager(context,getClass().getClassLoader(),"/adjuncts");
 * }
 * 
* *

* How you include an adjunct will depend on your template language, but for example in Jelly you do: *

 * <st:adjunct includes="org.kohsuke.stapler.bootstrap"/>
 * 
* * Or from Groovy you do: *
 * adjunct "org.kohsuke.stapler.bootstrap"
 * 
* *

* ... and this produces a series of style and script tags that include all the * necessary JavaScript, CSS, and their dependencies. * *

* Internally, this class provides caching for {@link Adjunct}s. * * @author Kohsuke Kawaguchi * @see Adjunct */ public class AdjunctManager { private final ConcurrentHashMap adjuncts = new ConcurrentHashMap(); /** * Map used as a set to remember which resources can be served. */ private final ConcurrentHashMap allowedResources = new ConcurrentHashMap(); private final ClassLoader classLoader; /** * Absolute URL of the {@link AdjunctManager} in the calling application where it is bound to. * *

* The path is treated relative from the context path of the application, and it * needs to end without '/'. So it needs to be something like "foo/adjuncts" or * just "adjuncts". Can be e.g. {@code adjuncts/uNiQuEhAsH} to improve caching behavior. */ public final String rootURL; /** * Hint instructing adjuncts to load a debuggable non-minified version of the script, * as opposed to the production version. * * This is only a hint, and so the semantics of it isn't very well defined. The intention * is to assist JavaScript debugging. */ public boolean debug = Boolean.getBoolean(AdjunctManager.class.getName()+".debug"); public final WebApp webApp; private final long expiration; @Deprecated public AdjunctManager(ServletContext context,ClassLoader classLoader, String rootURL) { this(context, classLoader, rootURL, /* one day */24L * 60 * 60 * 1000); } /** * @param classLoader * ClassLoader to load adjuncts from. * @param rootURL * See {@link #rootURL} for the meaning of this parameter. * @param expiration milliseconds from service time until expiration, for {@link #doDynamic} * (as in {@link StaplerResponse#serveFile(StaplerRequest, URL, long)}); * if {@link #rootURL} is unique per session then this can be very long; * otherwise a day might be reasonable */ public AdjunctManager(ServletContext context, ClassLoader classLoader, String rootURL, long expiration) { this.classLoader = classLoader; this.rootURL = rootURL; this.webApp = WebApp.get(context); this.expiration = expiration; // register this globally context.setAttribute(KEY,this); } public static AdjunctManager get(ServletContext context) { return (AdjunctManager) context.getAttribute(KEY); } /** * Obtains the adjunct. * * @return * always non-null. * @throws IOException * if failed to locate {@link Adjunct}. */ public Adjunct get(String name) throws IOException { Adjunct a = adjuncts.get(name); if(a!=null) return a; // found it synchronized (this) { a = adjuncts.get(name); if(a!=null) return a; // one more check before we start loading a = new Adjunct(this,name,classLoader); adjuncts.put(name,a); return a; } } /** * Serves resources in the class loader. */ public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { String path = req.getRestOfPath(); if (path.charAt(0)=='/') path = path.substring(1); if(!allowedResources.containsKey(path)) { if(!allowResourceToBeServed(path)) { rsp.sendError(SC_FORBIDDEN); return; } // remember URLs that we can serve. but don't remember error ones, as it might be unbounded allowedResources.put(path,path); } URL res = classLoader.getResource(path); if(res==null) { throw HttpResponses.error(SC_NOT_FOUND,new IllegalArgumentException("No such adjunct found: "+path)); } else { long expires = MetaClass.NO_CACHE ? 0 : expiration; rsp.serveFile(req,res,expires); } } /** * Controls whether the given resource can be served to browsers. * *

* This method can be overridden by the sub classes to change the access control behavior. * *

* {@link AdjunctManager} is capable of serving all the resources visible * in the classloader by default. If the resource files need to be kept private, * return false, which causes the request to fail with 401. * * Otherwise return true, in which case the resource will be served. */ protected boolean allowResourceToBeServed(String absolutePath) { // does it have an adjunct directory marker? int idx = absolutePath.lastIndexOf('/'); if (idx>0 && classLoader.getResource(absolutePath.substring(0,idx)+"/.adjunct")!=null) return true; // backward compatible behaviour return absolutePath.endsWith(".gif") || absolutePath.endsWith(".png") || absolutePath.endsWith(".css") || absolutePath.endsWith(".js"); } /** * Key in {@link ServletContext} to look up {@link AdjunctManager}. */ private static final String KEY = AdjunctManager.class.getName(); } stapler-stapler-parent-1.218/jelly/src/test/0000775000175000017500000000000012206724733021505 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/java/0000775000175000017500000000000012206724733022426 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/java/org/0000775000175000017500000000000012206724733023215 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/java/org/kohsuke/0000775000175000017500000000000012206724733024666 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/java/org/kohsuke/stapler/0000775000175000017500000000000012206724733026340 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/java/org/kohsuke/stapler/jelly/0000775000175000017500000000000012206724733027457 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/java/org/kohsuke/stapler/jelly/BindTagTest.java0000664000175000017500000000221312206724733032470 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlPage; import org.kohsuke.stapler.framework.adjunct.AdjunctManager; import org.kohsuke.stapler.test.JettyTestCase; import java.net.URL; /** * @author Kohsuke Kawaguchi */ public class BindTagTest extends JettyTestCase { private String value; public AdjunctManager am; @Override protected void setUp() throws Exception { super.setUp(); this.am = new AdjunctManager(servletContext,getClass().getClassLoader(),"am"); } public void test1() throws Exception { WebClient wc = new WebClient(); HtmlPage page = wc.getPage(new URL(url, "/")); String content = page.getWebResponse().getContentAsString(); System.out.println(content); //Check that prototype is included in the page assertTrue(content.contains("/am/org/kohsuke/stapler/framework/prototype/prototype.js")); page.executeJavaScript("v.foo('hello world');"); assertEquals("hello world",value); } public void jsFoo(String arg) { this.value = arg; } } stapler-stapler-parent-1.218/jelly/src/test/java/org/kohsuke/stapler/jelly/BindTagJQueryTest.java0000664000175000017500000000244412206724733033636 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlPage; import org.kohsuke.stapler.framework.adjunct.AdjunctManager; import org.kohsuke.stapler.test.JettyTestCase; import java.net.URL; /** * Description * * @author Robert Sandell <sandell.robert@gmail.com> */ public class BindTagJQueryTest extends JettyTestCase { private String value; public AdjunctManager am; private int number; @Override protected void setUp() throws Exception { super.setUp(); this.am = new AdjunctManager(servletContext,getClass().getClassLoader(),"am"); } public void test1() throws Exception { WebClient wc = new WebClient(); HtmlPage page = wc.getPage(new URL(url, "/")); String content = page.getWebResponse().getContentAsString(); System.out.println(content); //Check that prototype is included in the page assertFalse(content.contains("/am/org/kohsuke/stapler/framework/prototype/prototype.js")); page.executeJavaScript("v.foo('hello world', 2);"); assertEquals("hello world",value); assertEquals(2, number); } public void jsFoo(String arg, int arg2) { this.value = arg; this.number = arg2; } } stapler-stapler-parent-1.218/jelly/src/test/resources/0000775000175000017500000000000012206724733023517 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/resources/org/0000775000175000017500000000000012206724733024306 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/resources/org/kohsuke/0000775000175000017500000000000012206724733025757 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/resources/org/kohsuke/stapler/0000775000175000017500000000000012206724733027431 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/resources/org/kohsuke/stapler/jelly/0000775000175000017500000000000012206724733030550 5ustar jamespagejamespagestapler-stapler-parent-1.218/jelly/src/test/resources/org/kohsuke/stapler/jelly/BindTagJQueryTest/0000775000175000017500000000000012206724733034060 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/test/resources/org/kohsuke/stapler/jelly/BindTagJQueryTest/index.jellystapler-stapler-parent-1.218/jelly/src/test/resources/org/kohsuke/stapler/jelly/BindTagJQueryTest/in0000664000175000017500000000034412206724733034412 0ustar jamespagejamespage stapler-stapler-parent-1.218/jelly/src/test/resources/org/kohsuke/stapler/jelly/BindTagTest/0000775000175000017500000000000012206724733032720 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015012255653646011654 Lustar rootrootstapler-stapler-parent-1.218/jelly/src/test/resources/org/kohsuke/stapler/jelly/BindTagTest/index.jellystapler-stapler-parent-1.218/jelly/src/test/resources/org/kohsuke/stapler/jelly/BindTagTest/index.je0000664000175000017500000000022312206724733034344 0ustar jamespagejamespage stapler-stapler-parent-1.218/jelly/pom.xml0000664000175000017500000001131412206724733021254 0ustar jamespagejamespage 4.0.0 org.kohsuke.stapler stapler-parent 1.218 stapler-jelly Stapler Jelly module Jelly binding for Stapler ${project.groupId} stapler ${project.version} org.jenkins-ci commons-jelly 1.1-jenkins-20120928 dom4j dom4j org.jvnet.hudson.dom4j dom4j 1.6.1-hudson-3 org.jvnet.maven-jellydoc-plugin jellydoc-annotations 1.2 compile true javax.servlet servlet-api 2.4 provided ${project.groupId} stapler ${project.version} tests test junit junit org.jvnet.hudson htmlunit org.kohsuke.metainf-services metainf-services true org.kohsuke.stapler stapler-adjunct-jquery 1.8.3-0 test org.mortbay.jetty jetty org.jvnet.maven-jellydoc-plugin maven-jellydoc-plugin 1.2 com.sun tools system 1.6 ${toolsjar} release org.jvnet.maven-jellydoc-plugin maven-jellydoc-plugin jellydoc com.sun tools system 1.6 ${toolsjar} org.jvnet.maven-jellydoc-plugin maven-jellydoc-plugin 1.2 sane-jdk ${java.home}/../lib/tools.jar ${java.home}/../lib/tools.jar osx-jdk ${java.home}/../Classes/classes.jar ${java.home}/../Classes/classes.jar stapler-stapler-parent-1.218/.gitignore0000664000175000017500000000007712206724733020614 0ustar jamespagejamespage.idea/ *.ipr *.iml *.iws target .project .settings/ .classpathstapler-stapler-parent-1.218/groovy/0000775000175000017500000000000012206724733020145 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/0000775000175000017500000000000012206724733020734 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/main/0000775000175000017500000000000012206724733021660 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/main/java/0000775000175000017500000000000012206724733022601 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/main/java/org/0000775000175000017500000000000012206724733023370 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/0000775000175000017500000000000012206724733025041 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/0000775000175000017500000000000012206724733026513 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/0000775000175000017500000000000012206724733027632 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/0000775000175000017500000000000012206724733031157 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/JellyBuilder.java0000664000175000017500000005526012206724733034420 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly.groovy; import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; import groovy.lang.MissingMethodException; import groovy.lang.MissingPropertyException; import groovy.xml.QName; import org.apache.commons.beanutils.ConvertingWrapDynaBean; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.beanutils.DynaProperty; import org.apache.commons.jelly.DynaTag; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.JellyException; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.Script; import org.apache.commons.jelly.Tag; import org.apache.commons.jelly.TagLibrary; import org.apache.commons.jelly.XMLOutput; import org.apache.commons.jelly.expression.ConstantExpression; import org.apache.commons.jelly.expression.Expression; import org.apache.commons.jelly.impl.TagScript; import org.apache.commons.jelly.impl.TextScript; import org.codehaus.groovy.runtime.InvokerHelper; import org.dom4j.Element; import org.dom4j.io.SAXContentHandler; import org.kohsuke.stapler.MetaClassLoader; import org.kohsuke.stapler.Stapler; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.framework.adjunct.AdjunctManager; import org.kohsuke.stapler.framework.adjunct.AdjunctsInPage; import org.kohsuke.stapler.framework.adjunct.NoSuchAdjunctException; import org.kohsuke.stapler.jelly.CustomTagLibrary; import org.kohsuke.stapler.jelly.JellyClassLoaderTearOff; import org.kohsuke.stapler.jelly.JellyClassTearOff; import org.kohsuke.stapler.lang.Klass; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import javax.servlet.ServletContext; import java.io.IOException; import java.net.URL; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * Drive Jelly scripts from Groovy markup. * * @author Kohsuke Kawaguchi */ public final class JellyBuilder extends GroovyObjectSupport { /** * Current {@link XMLOutput}. */ private XMLOutput output; /** * Current {@link Tag} in which we are executing. */ private Tag current; private JellyContext context; private final Map taglibs = new HashMap(); private final StaplerRequest request; private StaplerResponse response; private String rootURL; private final AdjunctManager adjunctManager; /** * Cached {@Link AttributesImpl} instance. */ private final AttributesImpl attributes = new AttributesImpl(); public JellyBuilder(JellyContext context,XMLOutput output) { this.context = context; this.output = output; this.request = Stapler.getCurrentRequest(); this.adjunctManager = AdjunctManager.get(request.getServletContext()); } /** * This is used to allow QName to be used for the invocation. */ public Namespace namespace(String nsUri, String prefix) { return new Namespace(this,nsUri,prefix); } public Namespace namespace(String nsUri) { return namespace(nsUri,null); } public T namespace(Class type) { TagLibraryUri a = type.getAnnotation(TagLibraryUri.class); if (a==null) throw new IllegalArgumentException(type+" doesn't have @TagLibraryUri annotation"); return namespace(a.value(),null).createInvoker(type); } public XMLOutput getOutput() { return output; } public JellyContext getContext() { return context; } /** * Includes another view. */ public void include(Object it, String view) throws IOException, JellyException { _include(it,request.getWebApp().getKlass(it),view); } /** * Includes another view. */ public void include(Class clazz, String view) throws IOException, JellyException { _include(null,Klass.java(clazz),view); } private void _include(Object it, Klass clazz, String view) throws IOException, JellyException { JellyClassTearOff t = request.getWebApp().getMetaClass(clazz).getTearOff(JellyClassTearOff.class); Script s = t.findScript(view); if(s==null) throw new IllegalArgumentException("No such view: "+view+" for "+clazz); JellyContext context = new JellyContext(getContext()); if(it!=null) context.setVariable("it",it); context.setVariable("from", it); ClassLoader old = Thread.currentThread().getContextClassLoader(); if (clazz.clazz instanceof Class) Thread.currentThread().setContextClassLoader(((Class)clazz.clazz).getClassLoader()); try { s.run(context,output); } finally { Thread.currentThread().setContextClassLoader(old); } } public Object methodMissing(String name, Object args) { doInvokeMethod(new QName("",name), args); return null; } @SuppressWarnings({"ChainOfInstanceofChecks"}) protected void doInvokeMethod(QName name, Object args) { List list = InvokerHelper.asList(args); Map attributes = Collections.EMPTY_MAP; Closure closure = null; String innerText = null; // figure out what parameters are what switch (list.size()) { case 0: break; case 1: { Object object = list.get(0); if (object instanceof Map) { attributes = (Map) object; } else if (object instanceof Closure) { closure = (Closure) object; break; } else { if (object!=null) innerText = object.toString(); } break; } case 2: { Object object1 = list.get(0); Object object2 = list.get(1); if (object1 instanceof Map) { attributes = (Map) object1; if (object2 instanceof Closure) { closure = (Closure) object2; } else if(object2!=null) { innerText = object2.toString(); } } else { innerText = object1.toString(); if (object2 instanceof Closure) { closure = (Closure) object2; } else if (object2 instanceof Map) { attributes = (Map) object2; } else { throw new MissingMethodException(name.toString(), getClass(), list.toArray()); } } break; } case 3: { Object arg0 = list.get(0); Object arg1 = list.get(1); Object arg2 = list.get(2); if (arg0 instanceof Map && arg2 instanceof Closure) { closure = (Closure) arg2; attributes = (Map) arg0; innerText = arg1.toString(); } else if (arg1 instanceof Map && arg2 instanceof Closure) { closure = (Closure) arg2; attributes = (Map) arg1; innerText = arg0.toString(); } else { throw new MissingMethodException(name.toString(), getClass(), list.toArray()); } break; } default: throw new MissingMethodException(name.toString(), getClass(), list.toArray()); } if (isTag(name)) {// bridge to other Jelly tags try { TagScript tagScript = createTagScript(name, attributes); if (tagScript!=null) { Script body = NULL_SCRIPT; if(closure!=null) { final Closure theClosure = closure; body = new Script() { public Script compile() throws JellyException { return this; } public void run(JellyContext context, XMLOutput output) throws JellyTagException { JellyContext oldc = setContext(context); XMLOutput oldo = setOutput(output); try { theClosure.setDelegate(JellyBuilder.this); theClosure.call(); } finally { setContext(oldc); setOutput(oldo); } } }; } else if(innerText!=null) body = new TextScript(innerText); tagScript.setTagBody(body); tagScript.run(context,output); return; } } catch(JellyException e) { throw new RuntimeException(e); } } // static tag this.attributes.clear(); for (Entry e : ((Map)attributes).entrySet()) { Object v = e.getValue(); if(v==null) continue; String attName = e.getKey().toString(); this.attributes.addAttribute("",attName,attName,"CDATA", v.toString()); } try { output.startElement(name.getNamespaceURI(),name.getLocalPart(),name.getQualifiedName(),this.attributes); if(closure!=null) { closure.setDelegate(this); closure.call(); } if(innerText!=null) text(innerText); output.endElement(name.getNamespaceURI(),name.getLocalPart(),name.getQualifiedName()); } catch (SAXException e) { throw new RuntimeException(e); // what's the proper way to handle exceptions in Groovy? } } /** * Is this a static XML tag that we just generate, or * a jelly tag that needs evaluation? */ private boolean isTag(QName name) { return name.getNamespaceURI().length()>0; } /** * Create a tag script if the given QName is a taglib invocation, or return null * to handle it like a literal static tag. */ private TagScript createTagScript(QName n, Map attributes) throws JellyException { TagLibrary lib = context.getTagLibrary(n.getNamespaceURI()); if(lib!=null) { String localName = n.getLocalPart(); TagScript tagScript = lib.createTagScript(localName, null/*this parameter appears to be unused.*/); if (tagScript==null) tagScript = lib.createTagScript(localName.replace('_','-'), null); if (tagScript!=null) { if (attributes != null) { for (Entry e : attributes.entrySet()) { Object v = e.getValue(); if (v!=null) tagScript.addAttribute(e.getKey().toString(), new ConstantExpression(v)); } } return tagScript; } } // otherwise treat it as a literal. return null; } /* * Copyright 2002,2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ private void configureTag(Tag tag, Map attributes) throws JellyException { if ( tag instanceof DynaTag ) { DynaTag dynaTag = (DynaTag) tag; for (Object o : attributes.entrySet()) { Entry entry = (Entry) o; String name = (String) entry.getKey(); if(name.equals("xmlns")) continue; // we'll process this by ourselves Object value = getValue(entry, dynaTag.getAttributeType(name)); dynaTag.setAttribute(name, value); } } else { // treat the tag as a bean DynaBean dynaBean = new ConvertingWrapDynaBean( tag ); for (Object o : attributes.entrySet()) { Entry entry = (Entry) o; String name = (String) entry.getKey(); if(name.equals("xmlns")) continue; // we'll process this by ourselves DynaProperty property = dynaBean.getDynaClass().getDynaProperty(name); if (property == null) { throw new JellyException("This tag does not understand the '" + name + "' attribute"); } dynaBean.set(name, getValue(entry,property.getType())); } } } /** * Obtains the value from the map entry in the right type. */ private Object getValue(Entry entry, Class type) { Object value = entry.getValue(); if (type== Expression.class) value = new ConstantExpression(entry.getValue()); return value; } private Attributes toAttributes(Map attributes) { AttributesImpl atts = new AttributesImpl(); for (Object o : attributes.entrySet()) { Entry e = (Entry) o; if(e.getKey().toString().equals("xmlns")) continue; // we'll process them outside attributes atts.addAttribute("", e.getKey().toString(), e.getKey().toString(), null, e.getValue().toString()); } return atts; } JellyContext setContext(JellyContext newValue) { JellyContext old = context; context = newValue; return old; } public XMLOutput setOutput(XMLOutput newValue) { XMLOutput old = output; output = newValue; return old; } /** * Executes the closure with the specified {@link XMLOutput}. */ public Object with(XMLOutput out, Closure c) { XMLOutput old = setOutput(out); try { c.setDelegate(this); return c.call(); } finally { setOutput(old); } } /** * Captures the XML fragment generated by the given closure into dom4j DOM tree * and return the root element. * * @return null * if nothing was generated. */ public Element redirectToDom(Closure c) { SAXContentHandler sc = new SAXContentHandler(); with(new XMLOutput(sc),c); return sc.getDocument().getRootElement(); } /** * Allows values from {@link JellyContext} to be read * like global variables. These includes 'request', 'response', etc. * * @see JellyClassTearOff */ public Object getProperty(String property) { try { return super.getProperty(property); } catch (MissingPropertyException e) { Object r = context.getVariableWithDefaultValue(property,MISSING); if (r==MISSING) throw e; return r; } } /** * Sets the value to {@link JellyContext} (typically as a pre-cursor to calling into Jelly tags.) */ public void set(String var, Object value) { context.setVariable(var,value); } /** * Gets the "it" object. * * In Groovy "it" is reserved word with a specific meaning, * so instead use "my" as the word. */ public Object getMy() { return context.getVariable("it"); } /** * Writes PCDATA. * *

* Any HTML unsafe characters in the string representation of the given object is * properly escaped. * * @see #raw(Object) */ public void text(Object o) throws SAXException { if (o!=null) output.write(escape(o.toString())); } /** * Generates HTML fragment from string. * *

* The string representation of the object is assumed to produce proper HTML. * No further escaping is performed. * * @see #text(Object) */ public void raw(Object o) throws SAXException { if (o!=null) output.write(o.toString()); } private String escape(String v) { StringBuffer buf = new StringBuffer(v.length()+64); for( int i=0; i') buf.append(">"); else if(ch=='&') buf.append("&"); else buf.append(ch); } return buf.toString(); } /** * {@link Script} that does nothing. */ private static final Script NULL_SCRIPT = new Script() { public Script compile() { return this; } public void run(JellyContext context, XMLOutput output) { } }; /** * Loads a Groovy tag lib instance. * *

* A groovy tag library is really just a script class with bunch of method definitions, * without any explicit class definition. Such a class is loaded as a subtype of * {@link GroovyClosureScript} so that it can use this builder as the delegation target. * *

* This method instanciates the class (if not done so already for this request), * and return it. */ public Object taglib(Class type) throws IllegalAccessException, InstantiationException, IOException, SAXException { GroovyClosureScript o = taglibs.get(type); if(o==null) { o = (GroovyClosureScript) type.newInstance(); o.setDelegate(this); taglibs.put(type,o); adjunct(type.getName()); } return o; } /** * Includes the specified adjunct. * * This method is useful for including adjunct dynamically on demand. */ public void adjunct(String name) throws IOException, SAXException { try { AdjunctsInPage aip = AdjunctsInPage.get(); aip.generate(output,name); } catch (NoSuchAdjunctException e) { // that's OK. } } /** * Loads a jelly tag library. * * @param t * If this is a subtype of {@link TagLibrary}, then that tag library is loaded and bound to the * {@link Namespace} object, which you can later use to call tags. * Otherwise, t has to have 'taglib' file in the resource and sibling "*.jelly" files will be treated * as tag files. */ public Namespace jelly(Class t) { String n = t.getName(); if(TagLibrary.class.isAssignableFrom(t)) { // if the given class is a tag library itself, just record it context.registerTagLibrary(n,n); } else { String path = n.replace('.', '/'); URL res = t.getClassLoader().getResource(path+"/taglib"); if(res!=null) { // this class itself is not a tag library, but it contains Jelly side files that are tag files. // (some of them might be views, but some of them are tag files, anyway. JellyContext parseContext = MetaClassLoader.get(t.getClassLoader()).getTearOff(JellyClassLoaderTearOff.class).createContext(); context.registerTagLibrary(n, new CustomTagLibrary(parseContext, t.getClassLoader(), n, path)); } else { throw new IllegalArgumentException("Cannot find taglib from "+t); } } return new Namespace(this,n,"-"); // doesn't matter what the prefix is, since they are known to be taglibs } public ServletContext getServletContext() { return getRequest().getServletContext(); } public StaplerRequest getRequest() { return request; } public StaplerResponse getResponse() { if(response==null) response = Stapler.getCurrentResponse(); return response; } public JellyBuilder getBuilder() { return this; } /** * Gets the absolute URL to the top of the webapp. * * @see StaplerRequest#getContextPath() */ public String getRootURL() { if(rootURL==null) rootURL = getRequest().getContextPath(); return rootURL; } /** * Generates an <IMG> tag to the resource. */ public void img(Object base, String localName) throws SAXException { output.write( ""); } /** * Yields a URL to the given resource. * * @param base * The base class/object for which the 'localName' parameter * is resolved from. If this is class, 'localName' is assumed * to be a resource of this class. If it's other objects, * 'localName' is assumed to be a resource of the class of this object. */ public String res(Object base, String localName) { Class c; if (base instanceof Class) c = (Class) base; else c = base.getClass(); return adjunctManager.rootURL+'/'+c.getName().replace('.','/')+'/'+localName; } private static final Object MISSING = new Object(); } ././@LongLink0000644000000000000000000000015712255653646011663 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyServerPageScript.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyServerPageS0000664000175000017500000000107612206724733034502 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.groovy; import groovy.text.SimpleTemplateEngine; import java.io.Writer; /** * Base class for compiled GSP files. * * @author Kohsuke Kawaguchi */ public abstract class GroovyServerPageScript extends StaplerClosureScript { private Writer out; protected GroovyServerPageScript() { } /** * {@link SimpleTemplateEngine} expects 'out' variable */ public Writer getOut() { if (out==null) { out = ((JellyBuilder)getDelegate()).getOutput().asWriter(); } return out; } } ././@LongLink0000644000000000000000000000014612255653646011661 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/TagLibraryUri.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/TagLibraryUri.jav0000664000175000017500000000077212206724733034407 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.groovy; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; /** * Used on subtypes of {@link TypedTagLibrary} to associate the namespace URI to look up tags from. * * @author Kohsuke Kawaguchi */ @Retention(RUNTIME) @Documented @Target(TYPE) public @interface TagLibraryUri { String value(); } stapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyFacet.java0000664000175000017500000001252012206724733034252 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly.groovy; import org.apache.commons.jelly.Script; import org.kohsuke.MetaInfServices; import org.kohsuke.stapler.Dispatcher; import org.kohsuke.stapler.Facet; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.RequestImpl; import org.kohsuke.stapler.ResponseImpl; import org.kohsuke.stapler.TearOffSupport; import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.jelly.JellyCompatibleFacet; import org.kohsuke.stapler.jelly.JellyFacet; import org.kohsuke.stapler.lang.Klass; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; /** * {@link Facet} that brings in Groovy support on top of Jelly. * * @author Kohsuke Kawaguchi */ @MetaInfServices(Facet.class) public class GroovyFacet extends Facet implements JellyCompatibleFacet { public void buildViewDispatchers(final MetaClass owner, List dispatchers) { dispatchers.add(new Dispatcher() { final GroovyClassTearOff tearOff = owner.loadTearOff(GroovyClassTearOff.class); final GroovyServerPageTearOff gsp = owner.loadTearOff(GroovyServerPageTearOff.class); public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException { // check Groovy view String next = req.tokens.peek(); if(next==null) return false; // only match the end of the URL if (req.tokens.countRemainingTokens()>1) return false; // and avoid serving both "foo" and "foo/" as relative URL semantics are drastically different if (req.getRequestURI().endsWith("/")) return false; try { Script script = tearOff.findScript(next); if(script==null) script = gsp.findScript(next); if (script==null) return false; // no Groovy script found req.tokens.next(); if(traceable()) trace(req,rsp,"Invoking "+next+".groovy"+" on "+node+" for "+req.tokens); WebApp.getCurrent().getFacet(JellyFacet.class).scriptInvoker.invokeScript(req, rsp, script, node); return true; } catch (RuntimeException e) { throw e; } catch (IOException e) { throw e; } catch (Exception e) { throw new ServletException(e); } } public String toString() { return "TOKEN.groovy for url=/TOKEN"; } }); } public Collection> getClassTearOffTypes() { return TEAROFF_TYPES; } public Collection getScriptExtensions() { return EXTENSION; } public RequestDispatcher createRequestDispatcher(RequestImpl request, Klass type, Object it, String viewName) throws IOException { TearOffSupport mc = request.stapler.getWebApp().getMetaClass(type); return mc.loadTearOff(GroovyClassTearOff.class).createDispatcher(it,viewName); } public boolean handleIndexRequest(RequestImpl req, ResponseImpl rsp, Object node, MetaClass nodeMetaClass) throws IOException, ServletException { RequestDispatcher d = nodeMetaClass.loadTearOff(GroovyClassTearOff.class).createDispatcher(node, "index"); if (d==null) d = nodeMetaClass.loadTearOff(GroovyServerPageTearOff.class).createDispatcher(node, "index"); if (d!=null) { d.forward(req, rsp); return true; } return false; } private static final Set> TEAROFF_TYPES = Collections.singleton(GroovyClassTearOff.class); private static final Set EXTENSION = Collections.singleton(".groovy"); } ././@LongLink0000644000000000000000000000016012255653646011655 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyServerPageTearOff.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyServerPageT0000664000175000017500000000236712206724733034507 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.groovy; import org.kohsuke.stapler.AbstractTearOff; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.jelly.JellyRequestDispatcher; import javax.servlet.RequestDispatcher; import java.io.IOException; import java.net.URL; /** * @author Kohsuke Kawaguchi */ public class GroovyServerPageTearOff extends AbstractTearOff { public GroovyServerPageTearOff(MetaClass owner) { super(owner,GroovyClassLoaderTearOff.class); } @Override protected String getDefaultScriptExtension() { return ".gsp"; } public GroovierJellyScript parseScript(URL res) throws IOException { try { return classLoader.parseGSP(res); } catch (ClassNotFoundException e) { throw (IOException)new IOException("Failed to compile "+res).initCause(e); } } /** * Creates a {@link RequestDispatcher} that forwards to the jelly view, if available. */ public RequestDispatcher createDispatcher(Object it, String viewName) throws IOException { GroovierJellyScript s = findScript(viewName); if (s!=null) return new JellyRequestDispatcher(it,s); return null; } } ././@LongLink0000644000000000000000000000015512255653646011661 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/SimpleTemplateParser.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/SimpleTemplatePar0000664000175000017500000001333312206724733034475 0ustar jamespagejamespage/* * Copyright 2003-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kohsuke.stapler.jelly.groovy; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringWriter; import java.net.URL; /** * @author Kohsuke Kawaguchi */ class SimpleTemplateParser { protected String parse(URL res) throws IOException { return parse(new InputStreamReader(res.openStream(),"UTF-8")); } /** * Parse the text document looking for <% or <%= and then call out to the appropriate handler, otherwise copy the text directly * into the script while escaping quotes. * * @param reader a reader for the template text * @return the parsed text * @throws IOException if something goes wrong */ protected String parse(Reader reader) throws IOException { if (!reader.markSupported()) { reader = new BufferedReader(reader); } StringWriter sw = new StringWriter(); startScript(sw); int c; while ((c = reader.read()) != -1) { if (c == '<') { reader.mark(1); c = reader.read(); if (c != '%') { sw.write('<'); reader.reset(); } else { reader.mark(1); c = reader.read(); if (c == '=') { groovyExpression(reader, sw); } else { reader.reset(); groovySection(reader, sw); } } continue; // at least '<' is consumed ... read next chars. } if (c == '$') { reader.mark(1); c = reader.read(); if (c != '{') { sw.write('$'); reader.reset(); } else { reader.mark(1); sw.write("${"); processGSstring(reader, sw); } continue; // at least '$' is consumed ... read next chars. } if (c == '\"') { sw.write('\\'); } /* * Handle raw new line characters. */ if (c == '\n' || c == '\r') { if (c == '\r') { // on Windows, "\r\n" is a new line. reader.mark(1); c = reader.read(); if (c != '\n') { reader.reset(); } } sw.write("\n"); continue; } sw.write(c); } endScript(sw); return sw.toString(); } protected String printCommand() { return "out.print"; } private void startScript(StringWriter sw) { sw.write(printCommand()+"(\"\"\""); } private void endScript(StringWriter sw) { sw.write("\"\"\");\n"); sw.write("\n/* Generated by SimpleTemplateEngine */"); } private void processGSstring(Reader reader, StringWriter sw) throws IOException { int c; while ((c = reader.read()) != -1) { if (c != '\n' && c != '\r') { sw.write(c); } if (c == '}') { break; } } } /** * Closes the currently open write and writes out the following text as a GString expression until it reaches an end %>. * * @param reader a reader for the template text * @param sw a StringWriter to write expression content * @throws IOException if something goes wrong */ private void groovyExpression(Reader reader, StringWriter sw) throws IOException { sw.write("${"); int c; while ((c = reader.read()) != -1) { if (c == '%') { c = reader.read(); if (c != '>') { sw.write('%'); } else { break; } } if (c != '\n' && c != '\r') { sw.write(c); } } sw.write("}"); } /** * Closes the currently open write and writes the following text as normal Groovy script code until it reaches an end %>. * * @param reader a reader for the template text * @param sw a StringWriter to write expression content * @throws IOException if something goes wrong */ private void groovySection(Reader reader, StringWriter sw) throws IOException { sw.write("\"\"\");"); int c; while ((c = reader.read()) != -1) { if (c == '%') { c = reader.read(); if (c != '>') { sw.write('%'); } else { break; } } /* Don't eat EOL chars in sections - as they are valid instruction separators. * See http://jira.codehaus.org/browse/GROOVY-980 */ // if (c != '\n' && c != '\r') { sw.write(c); //} } sw.write(";\n"+printCommand()+"(\"\"\""); } } ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyClassLoaderTearOff.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyClassLoader0000664000175000017500000001010112206724733034475 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly.groovy; import groovy.lang.GroovyClassLoader; import groovy.lang.GroovyCodeSource; import org.apache.commons.jelly.XMLOutput; import org.codehaus.groovy.control.CompilerConfiguration; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.MetaClassLoader; import java.io.IOException; import java.net.URL; /** * @author Kohsuke Kawaguchi */ public class GroovyClassLoaderTearOff { private final MetaClassLoader owner; private final GroovyClassLoader gcl; private final SimpleTemplateParser parser = new SimpleTemplateParser() { /** * Sends the output via {@link XMLOutput#write(String)} */ @Override protected String printCommand() { return "output.write"; } }; public GroovyClassLoaderTearOff(MetaClassLoader owner) { this.owner = owner; gcl = createGroovyClassLoader(); } private GroovyClassLoader createGroovyClassLoader() { CompilerConfiguration cc = new CompilerConfiguration(); // use GroovyClosureScript class as the base class of the compiled script, // so that we can set a delegate. cc.setScriptBaseClass(StaplerClosureScript.class.getName()); // enable re-compilation support cc.setRecompileGroovySource(MetaClass.NO_CACHE); return new GroovyClassLoader(owner.loader,cc) { /** * Groovy calls this method to locate .groovy script files, * so during the development it's important to check the * resource path before target/classes. */ @Override public URL getResource(String name) { // allow the resource path to take precedence when loading script if(MetaClassLoader.debugLoader!=null) { URL res = MetaClassLoader.debugLoader.loader.getResource(name); if(res!=null) return res; } return super.getResource(name); } }; } public GroovierJellyScript parse(URL script) throws IOException { // we do the caching on our own, so don't let GroovyClassLoader cache this. Or else // dynamic reloading won't work GroovyCodeSource gcs = new GroovyCodeSource(script); gcs.setCachable(false); return new GroovierJellyScript(gcl.parseClass(gcs),script); } public GroovierJellyScript parseGSP(URL res) throws IOException, ClassNotFoundException { GroovyCodeSource gcs = new GroovyCodeSource(parser.parse(res), res.toExternalForm(), res.toExternalForm()); gcs.setCachable(false); return new GroovierJellyScript(gcl.parseClass(gcs),res); } } ././@LongLink0000644000000000000000000000015012255653646011654 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/TypedTagLibrary.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/TypedTagLibrary.j0000664000175000017500000000047212206724733034403 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.groovy; import groovy.lang.GroovyObject; /** * Typed interface to provide auto-completion for IDEs when invoking taglibs. * * Subtype must have the {@link TagLibraryUri} annotation * * @author Kohsuke Kawaguchi */ public interface TypedTagLibrary extends GroovyObject { } ././@LongLink0000644000000000000000000000015312255653646011657 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyClassTearOff.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyClassTearOf0000664000175000017500000000502212206724733034455 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly.groovy; import org.apache.commons.jelly.Script; import org.kohsuke.stapler.AbstractTearOff; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.jelly.JellyRequestDispatcher; import javax.servlet.RequestDispatcher; import java.io.IOException; import java.net.URL; import java.util.logging.Logger; /** * @author Kohsuke Kawaguchi */ public final class GroovyClassTearOff extends AbstractTearOff { public GroovyClassTearOff(MetaClass owner) { super(owner,GroovyClassLoaderTearOff.class); } @Override protected String getDefaultScriptExtension() { return ".groovy"; } public GroovierJellyScript parseScript(URL res) throws IOException { return classLoader.parse(res); } /** * Creates a {@link RequestDispatcher} that forwards to the jelly view, if available. */ public RequestDispatcher createDispatcher(Object it, String viewName) throws IOException { Script script = findScript(viewName); if(script!=null) return new JellyRequestDispatcher(it,script); return null; } } ././@LongLink0000644000000000000000000000015412255653646011660 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyClosureScript.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyClosureScri0000664000175000017500000000657212206724733034557 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly.groovy; import groovy.lang.Binding; import groovy.lang.Closure; import groovy.lang.GroovyObject; import groovy.lang.MissingMethodException; import groovy.lang.MissingPropertyException; import groovy.lang.Script; /** * {@link Script} that performs method invocations and property access like {@link Closure} does. * *

* For example, when the script is: * *

 * a = 1;
 * b(2);
 * 
 *
 * 

* Using {@link GroovyClosureScript} as the base class would run it as: * *

 * delegate.a = 1;
 * delegate.b(2);
 * 
* * ... whereas in plain {@link Script}, this will be run as: * *
 * binding.setProperty("a",1);
 * ((Closure)binding.getProperty("b")).call(2);
 * 
* * This is convenient for building DSL as you can use an external object to define * methods and properties. * * @author Kohsuke Kawaguchi */ public abstract class GroovyClosureScript extends Script { private GroovyObject delegate; protected GroovyClosureScript() { super(); } protected GroovyClosureScript(Binding binding) { super(binding); } /** * Sets the delegation target. */ public void setDelegate(GroovyObject delegate) { this.delegate = delegate; } public GroovyObject getDelegate() { return delegate; } public Object invokeMethod(String name, Object args) { try { return delegate.invokeMethod(name,args); } catch (MissingMethodException mme) { return super.invokeMethod(name, args); } } public Object getProperty(String property) { try { return delegate.getProperty(property); } catch (MissingPropertyException e) { return super.getProperty(property); } } public void setProperty(String property, Object newValue) { try { delegate.setProperty(property,newValue); } catch (MissingPropertyException e) { super.setProperty(property,newValue); } } } ././@LongLink0000644000000000000000000000015412255653646011660 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovierJellyScript.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovierJellyScri0000664000175000017500000000521012206724733034515 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly.groovy; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.Script; import org.apache.commons.jelly.XMLOutput; import org.codehaus.groovy.runtime.InvokerHelper; import groovy.lang.Binding; import java.net.URL; /** * Wraps a Groovy-driven Jelly script into {@link Script} * (so that it can be called from other Jelly scripts.) * * @author Kohsuke Kawaguchi */ public class GroovierJellyScript implements Script { /** * Compiled Groovy class. */ private final Class clazz; /** * Where was this script loaded from? Used for diagnostics. */ private final URL scriptURL; public GroovierJellyScript(Class clazz, URL scriptURL) { this.clazz = clazz; this.scriptURL = scriptURL; } public Script compile() { return this; } public void run(JellyContext context, XMLOutput output) throws JellyTagException { run(new JellyBuilder(context, output)); } public void run(JellyBuilder builder) { StaplerClosureScript gcs = (StaplerClosureScript) InvokerHelper.createScript(clazz, new Binding()); gcs.setDelegate(builder); gcs.scriptURL = scriptURL; gcs.run(); } } ././@LongLink0000644000000000000000000000015412255653646011660 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyTagFileLoader.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyTagFileLoad0000664000175000017500000000440712206724733034430 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly.groovy; import org.kohsuke.stapler.jelly.JellyTagFileLoader; import org.kohsuke.stapler.jelly.CustomTagLibrary; import org.kohsuke.MetaInfServices; import org.apache.commons.jelly.Script; import org.apache.commons.jelly.JellyException; import java.io.IOException; import java.net.URL; /** * @author Kohsuke Kawaguchi */ @MetaInfServices public class GroovyTagFileLoader extends JellyTagFileLoader { public Script load(CustomTagLibrary taglib, String name, ClassLoader classLoader) throws JellyException { URL res = classLoader.getResource(taglib.basePath + '/' + name + ".groovy"); if(res==null) return null; try { GroovyClassLoaderTearOff gcl = taglib.metaClassLoader.getTearOff(GroovyClassLoaderTearOff.class); return gcl.parse(res); } catch (IOException e) { throw new JellyException(e); } } } stapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/TagFile.java0000664000175000017500000000107612206724733033341 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.groovy; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; /** * Used on methods of {@link TypedTagLibrary} to * indicate a real tag file name. * *

* This is used when the real tag file name is not * a valid Java identifier. * * @author Kohsuke Kawaguchi */ @Retention(RUNTIME) @Documented @Target(METHOD) public @interface TagFile { String value(); } stapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/Namespace.java0000664000175000017500000001006012206724733033713 0ustar jamespagejamespage/* * Copyright (c) 2004-2010, Kohsuke Kawaguchi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * 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 OWNER OR CONTRIBUTORS * 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. */ package org.kohsuke.stapler.jelly.groovy; import groovy.lang.GroovyObject; import groovy.lang.GroovyObjectSupport; import groovy.xml.QName; import org.apache.commons.jelly.XMLOutput; import org.codehaus.groovy.runtime.InvokerHelper; import org.xml.sax.SAXException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author Kohsuke Kawaguchi */ public class Namespace extends GroovyObjectSupport { private final JellyBuilder builder; private final String nsUri; private final String prefix; // note that the mapping from nsUri to TagLibrary // may change depending on the scope, so we can't cache TagLibrary Namespace(JellyBuilder builder, String nsUri, String prefix) { this.builder = builder; this.nsUri = nsUri; this.prefix = prefix==null ? "" : prefix; } public Object invokeMethod(String localName, Object args) { builder.doInvokeMethod(new QName(nsUri,localName,prefix),args); return null; } public void startPrefixMapping(XMLOutput output) throws SAXException { output.startPrefixMapping(prefix,nsUri); } public void endPrefixMapping(XMLOutput output) throws SAXException { output.endPrefixMapping(prefix); } /** * Creates a type-safe invoker for calling taglibs. */ public T createInvoker(Class type) { ProxyImpl handler = new ProxyImpl(); Object proxy = Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, handler); handler.setMetaClass(InvokerHelper.getMetaClass(proxy.getClass())); return type.cast(proxy); } private class ProxyImpl extends GroovyObjectSupport implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Class decl = method.getDeclaringClass(); if (decl==Object.class || decl==GroovyObject.class) try { return method.invoke(this,args); } catch (InvocationTargetException e) { throw e.getCause(); } TagFile a = method.getAnnotation(TagFile.class); String tagName = a!=null ? a.value() : method.getName(); // invoke methods builder.doInvokeMethod(new QName(nsUri,tagName,prefix),args); return null; } /** * Also accepts arbitrary type-unsafe invocations. */ @Override public Object invokeMethod(String name, Object args) { return Namespace.this.invokeMethod(name,args); } } } ././@LongLink0000644000000000000000000000015512255653646011661 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/StaplerClosureScript.javastapler-stapler-parent-1.218/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/StaplerClosureScr0000664000175000017500000000362312206724733034525 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.groovy; import org.jvnet.localizer.LocaleProvider; import org.kohsuke.stapler.jelly.ResourceBundle; import java.net.URL; /** * @author Kohsuke Kawaguchi */ public abstract class StaplerClosureScript extends GroovyClosureScript { /** * Where was this script loaded from? */ protected URL scriptURL; /** * Resource bundle for messages in this page. * Lazily loaded on demand. */ private volatile ResourceBundle resourceBundle; /** * Looks up the resource bundle with the given key, and returns that string, * or otherwise return 'text' as-is. */ public String _(String text) { return _(text, EMPTY_ARRAY); } /** * Looks up the resource bundle with the given key, formats with arguments, * then return that formatted string. */ public String _(String key, Object... args) { // JellyBuilder b = (JellyBuilder)getDelegate(); ResourceBundle resourceBundle = getResourceBundle(); // notify the listener if set // InternationalizedStringExpressionListener listener = (InternationalizedStringExpressionListener) Stapler.getCurrentRequest().getAttribute(LISTENER_NAME); // if(listener!=null) // listener.onUsed(this, args); // TODO: XSS prevention return resourceBundle.format(LocaleProvider.getLocale(), key, args); } private ResourceBundle getResourceBundle() { if (resourceBundle==null) { synchronized (this) { if (resourceBundle==null) { String baseURL = scriptURL.toExternalForm(); baseURL = baseURL.substring(0,baseURL.lastIndexOf('.')); resourceBundle = ResourceBundle.load(baseURL); } } } return resourceBundle; } private static final Object[] EMPTY_ARRAY = new Object[0]; } stapler-stapler-parent-1.218/groovy/src/test/0000775000175000017500000000000012206724733021713 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/test/java/0000775000175000017500000000000012206724733022634 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/test/java/org/0000775000175000017500000000000012206724733023423 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/test/java/org/kohsuke/0000775000175000017500000000000012206724733025074 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/test/java/org/kohsuke/stapler/0000775000175000017500000000000012206724733026546 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/test/java/org/kohsuke/stapler/jelly/0000775000175000017500000000000012206724733027665 5ustar jamespagejamespagestapler-stapler-parent-1.218/groovy/src/test/java/org/kohsuke/stapler/jelly/groovy/0000775000175000017500000000000012206724733031212 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/groovy/src/test/java/org/kohsuke/stapler/jelly/groovy/GroovyClassLoaderTearOffTest.javastapler-stapler-parent-1.218/groovy/src/test/java/org/kohsuke/stapler/jelly/groovy/GroovyClassLoader0000664000175000017500000000266212206724733034545 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.groovy; import org.apache.commons.io.FileUtils; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.XMLOutput; import org.kohsuke.stapler.MetaClassLoader; import org.kohsuke.stapler.test.AbstractStaplerTest; import java.io.File; import java.io.IOException; /** * @author Kohsuke Kawaguchi */ public class GroovyClassLoaderTearOffTest extends AbstractStaplerTest { public void testFoo() throws IOException, JellyTagException { File f = File.createTempFile("groovy","groovy"); try { MetaClassLoader mcl = webApp.getMetaClass(Foo.class).classLoader; GroovyClassLoaderTearOff t = mcl.getTearOff(GroovyClassLoaderTearOff.class); FileUtils.writeStringToFile(f,"context.setVariable('x',1)"); JellyContext context = new JellyContext(); XMLOutput w = XMLOutput.createXMLOutput(System.out); t.parse(f.toURL()).run(context, w); assertEquals(1,context.getVariable("x")); // reload different content in the same URL, make sure new class gets loaded FileUtils.writeStringToFile(f,"context.setVariable('x',2)"); t.parse(f.toURL()).run(context, w); assertEquals(2, context.getVariable("x")); } finally { f.delete(); } } public static class Foo {} } stapler-stapler-parent-1.218/groovy/pom.xml0000664000175000017500000000321412206724733021462 0ustar jamespagejamespage 4.0.0 org.kohsuke.stapler stapler-parent 1.218 stapler-groovy Stapler Groovy module Groovy binding for Stapler ${project.groupId} stapler-jelly ${project.version} org.codehaus.groovy groovy-all 1.8.3 javax.servlet servlet-api 2.3 provided ${project.groupId} stapler ${project.version} tests test junit junit org.kohsuke.metainf-services metainf-services true org.mockito mockito-all stapler-stapler-parent-1.218/jruby/0000775000175000017500000000000012206724733017753 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/0000775000175000017500000000000012206724733020542 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/0000775000175000017500000000000012206724733021466 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/java/0000775000175000017500000000000012206724733022407 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/java/org/0000775000175000017500000000000012206724733023176 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/0000775000175000017500000000000012206724733024647 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/0000775000175000017500000000000012206724733026321 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/0000775000175000017500000000000012206724733027440 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/0000775000175000017500000000000012206724733030573 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015212255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/AbstractRubyTearOff.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/AbstractRubyTearOff0000664000175000017500000000245712206724733034402 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby; import org.apache.commons.jelly.Script; import org.kohsuke.stapler.AbstractTearOff; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.jelly.JellyRequestDispatcher; import javax.servlet.RequestDispatcher; import java.io.IOException; import java.net.URL; /** * * * @author Kohsuke Kawaguchi */ public abstract class AbstractRubyTearOff extends AbstractTearOff { protected AbstractRubyTearOff(MetaClass owner) { super(owner, JRubyClassLoaderTearOff.class); } /** * Defines the file extension, like ".erb", that designates this kind of view type. */ @Override protected abstract String getDefaultScriptExtension(); public Script parseScript(URL res) throws IOException { return WebApp.getCurrent().getFacet(JRubyFacet.class).parseScript(res); } /** * Creates a {@link RequestDispatcher} that forwards to the jelly view, if available. */ public RequestDispatcher createDispatcher(Object it, String viewName) throws IOException { Script script = findScript(viewName+getDefaultScriptExtension()); if(script!=null) return new JellyRequestDispatcher(it,script); return null; } } ././@LongLink0000644000000000000000000000015312255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/RubyTemplateLanguage.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/RubyTemplateLanguag0000664000175000017500000000132712206724733034435 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby; import org.jruby.embed.ScriptingContainer; /** * Ruby template language binding. * *

* Implementations of this is discovered via service-loader mechanism. * * @author Kohsuke Kawaguchi */ public abstract class RubyTemplateLanguage { /** * Defines the file extension, like ".erb", that designates this kind of view type. */ protected abstract String getScriptExtension(); protected abstract Class getTearOffClass(); /** * Called to set up this template language binding on the specified scripting container. */ protected abstract RubyTemplateContainer createContainer(ScriptingContainer container); } stapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/erb/0000775000175000017500000000000012206724733031343 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015212255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/erb/ERbClassTearOff.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/erb/ERbClassTearOff0000664000175000017500000000075712206724733034204 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby.erb; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.jelly.jruby.AbstractRubyTearOff; /** * Tear off that manages Ruby ERB views of Java objects (and not ruby objects.) * * @author Kohsuke Kawaguchi */ public class ERbClassTearOff extends AbstractRubyTearOff { public ERbClassTearOff(MetaClass owner) { super(owner); } @Override protected String getDefaultScriptExtension() { return ".erb"; } } ././@LongLink0000644000000000000000000000014612255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/erb/ERbLanguage.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/erb/ERbLanguage.jav0000664000175000017500000000170112206724733034160 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby.erb; import org.jruby.RubyClass; import org.jruby.embed.ScriptingContainer; import org.kohsuke.MetaInfServices; import org.kohsuke.stapler.jelly.jruby.RubyTemplateContainer; import org.kohsuke.stapler.jelly.jruby.RubyTemplateLanguage; /** * @author Kohsuke Kawaguchi */ @MetaInfServices public class ERbLanguage extends RubyTemplateLanguage { @Override protected String getScriptExtension() { return ".erb"; } @Override protected Class getTearOffClass() { return ERbClassTearOff.class; } @Override protected RubyTemplateContainer createContainer(ScriptingContainer jruby) { return new RubyTemplateContainer( (RubyClass)jruby.runScriptlet( "require 'org/kohsuke/stapler/jelly/jruby/erb/JRubyJellyERbScript'\n"+ "JRubyJellyScriptImpl::JRubyJellyERbScript"), this, jruby); } } ././@LongLink0000644000000000000000000000015112255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/RubyKlassNavigator.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/RubyKlassNavigator.0000664000175000017500000000472512206724733034376 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby; import org.jruby.Ruby; import org.jruby.RubyClass; import org.jruby.RubyModule; import org.jruby.RubyObject; import org.kohsuke.stapler.MetaClassLoader; import org.kohsuke.stapler.lang.Klass; import org.kohsuke.stapler.lang.KlassNavigator; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Locale; /** * @author Kohsuke Kawaguchi */ public class RubyKlassNavigator extends KlassNavigator { private final Ruby ruby; /** * ClassLoader to load resources from. */ private final ClassLoader classLoader; public RubyKlassNavigator(Ruby ruby, ClassLoader cl) { this.ruby = ruby; this.classLoader = cl; } @Override public URL getResource(RubyModule clazz, String resourceName) { String fullName; if (resourceName.startsWith("/")) fullName = resourceName.substring(1); else fullName = decamelize(clazz.getName().replace("::","/")+'/'+resourceName); if (MetaClassLoader.debugLoader!=null) { URL res = MetaClassLoader.debugLoader.loader.getResource(fullName); if (res!=null) return res; } return classLoader.getResource(fullName); } @Override public Iterable> getAncestors(RubyModule clazz) { List> r = new ArrayList>(); for (RubyModule anc : (List)(List)clazz.getAncestorList()) { r.add(wrap(anc)); } return r; } @Override public Klass getSuperClass(RubyModule clazz) { // TODO: what happens when a Ruby class extends from Java class? return wrap(clazz.getSuperClass()); } @Override public Class toJavaClass(RubyModule clazz) { if (clazz instanceof RubyClass) { RubyClass rc = (RubyClass) clazz; Class c = rc.getReifiedClass(); if (c!=null) return c; // is this right? } return RubyObject.class; } public Klass wrap(RubyModule m) { return m==null ? null : new Klass(m,this); } /** * Converts "FooBarZot" to "foo_bar_zot" */ static String decamelize(String s) { return s.replaceAll("(\\p{javaLetterOrDigit})(\\p{javaUpperCase}\\p{javaLowerCase})","$1_$2") .replaceAll("(\\p{javaLowerCase})(\\p{javaUpperCase})","$1_$2") .toLowerCase(Locale.ENGLISH); } } stapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/haml/0000775000175000017500000000000012206724733031514 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015412255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/haml/HamlClassTearOff.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/haml/HamlClassTearO0000664000175000017500000000064312206724733034244 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby.haml; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.jelly.jruby.AbstractRubyTearOff; /** * * @author Kohsuke Kawaguchi */ public class HamlClassTearOff extends AbstractRubyTearOff { public HamlClassTearOff(MetaClass owner) { super(owner); } @Override protected String getDefaultScriptExtension() { return ".haml"; } } ././@LongLink0000644000000000000000000000015012255653646011654 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/haml/HamlLanguage.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/haml/HamlLanguage.j0000664000175000017500000000226412206724733034220 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby.haml; import org.jruby.RubyClass; import org.jruby.embed.ScriptingContainer; import org.kohsuke.MetaInfServices; import org.kohsuke.stapler.jelly.jruby.RubyTemplateContainer; import org.kohsuke.stapler.jelly.jruby.RubyTemplateLanguage; /** * @author Hiroshi Nakamura */ @MetaInfServices public class HamlLanguage extends RubyTemplateLanguage { @Override protected String getScriptExtension() { return ".haml"; } @Override protected Class getTearOffClass() { return HamlClassTearOff.class; } @Override protected RubyTemplateContainer createContainer(ScriptingContainer jruby) { jruby.put("gem_path", getClass().getResource("/gem").getPath()); return new RubyTemplateContainer( (RubyClass)jruby.runScriptlet("ENV['GEM_PATH'] = gem_path\n" + "require 'rubygems'\n" + "require 'org/kohsuke/stapler/jelly/jruby/JRubyJellyScriptImpl'\n"+ "require 'org/kohsuke/stapler/jelly/jruby/haml/JRubyJellyHamlScript'\n"+ "JRubyJellyScriptImpl::JRubyJellyHamlScript" ), this, jruby); } } ././@LongLink0000644000000000000000000000014712255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/JRubyJellyScript.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/JRubyJellyScript.ja0000664000175000017500000000626612206724733034341 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.JellyException; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.Script; import org.apache.commons.jelly.TagLibrary; import org.apache.commons.jelly.XMLOutput; import org.apache.commons.jelly.expression.ConstantExpression; import org.apache.commons.jelly.impl.TagScript; import org.jruby.Ruby; import org.jruby.RubyProc; import org.jruby.RubySymbol; import org.jruby.runtime.builtin.IRubyObject; import java.util.Map; import java.util.Map.Entry; /** * Exposes ERb/Haml scripts as {@link Script}. * *

* This abstract class defines the Java half of it, and it is further subtyped in Ruby for different languages. * * @author Kohsuke Kawaguchi */ public abstract class JRubyJellyScript implements Script { protected JRubyJellyScript() { } public Script compile() throws JellyException { return this; } // this method is implemented in Ruby public abstract void run(JellyContext context, XMLOutput output) throws JellyTagException; /** * Invokes other Jelly tag libaries. */ public void invokeTaglib(final IJRubyContext rcon, JellyContext context, XMLOutput output, String uri, String localName, Map attributes, final RubyProc proc) throws JellyException { TagScript tagScript = createTagScript(context, uri, localName); if (attributes!=null) { for (Entry e : attributes.entrySet()) { tagScript.addAttribute(e.getKey().asJavaString(), new ConstantExpression(e.getValue())); } } if (proc!=null) { final Ruby runtime = ((IRubyObject)rcon).getRuntime(); tagScript.setTagBody(new Script() { public Script compile() throws JellyException { return this; } public void run(JellyContext context, XMLOutput output) throws JellyTagException { JellyContext oc = rcon.getJellyContext(); XMLOutput oo = rcon.getOutput(); try { rcon.setJellyContext(context); rcon.setOutput(output); proc.getBlock().yield(runtime.getCurrentContext(),null); } finally { rcon.setJellyContext(oc); rcon.setOutput(oo); } } }); } tagScript.run(context, output); } private TagScript createTagScript(JellyContext context, String uri, String name) throws JellyException { TagLibrary lib = context.getTagLibrary(uri); if (lib==null) throw new JellyException("Undefined tag library namespace URI: "+uri); TagScript tagScript = lib.createTagScript(name, null/*this parameter appears to be unused.*/); if (tagScript!=null) return tagScript; tagScript = lib.createTagScript(name.replace('_','-'), null); if (tagScript!=null) return tagScript; throw new JellyException(String.format("name '%s' not found for '%s'", name, uri)); } } ././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/JRubyClassLoaderTearOff.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/JRubyClassLoaderTea0000664000175000017500000000045512206724733034324 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby; import org.kohsuke.stapler.MetaClassLoader; /** * @author Kohsuke Kawaguchi */ public class JRubyClassLoaderTearOff { private final MetaClassLoader owner; public JRubyClassLoaderTearOff(MetaClassLoader owner) { this.owner = owner; } } stapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/RackDispatcher.java0000664000175000017500000000454312206724733034333 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby; import org.jruby.Ruby; import org.jruby.RubyModule; import org.jruby.RubyObject; import org.jruby.internal.runtime.methods.DynamicMethod; import org.jruby.rack.DefaultRackApplication; import org.jruby.rack.servlet.*; import org.jruby.runtime.builtin.IRubyObject; import org.kohsuke.stapler.Dispatcher; import org.kohsuke.stapler.RequestImpl; import org.kohsuke.stapler.ResponseImpl; import org.kohsuke.stapler.Stapler; import javax.servlet.ServletException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; /** * {@link Dispatcher} that looks for the Rack-compliant call method. * * @author Kohsuke Kawaguchi */ public class RackDispatcher extends Dispatcher { @Override public boolean dispatch(final RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException, IllegalAccessException, InvocationTargetException { RubyObject x = (RubyObject) node; Ruby runtime = x.getRuntime(); DynamicMethod m = x.getMetaClass().searchMethod("call"); if (m==null) // does this instance respond to the 'call' method? return false; // TODO: does the context need to live longer? ServletRackContext rackContext = new DefaultServletRackContext(new ServletRackConfig(req.getServletContext())); // we don't want the Rack app to consider the portion of the URL that was already consumed // to reach to the Rack app, so for PATH_INFO we use getRestOfPath(), not getPathInfo() ServletRackEnvironment env = new ServletRackEnvironment(req, rsp, rackContext) { @Override public String getPathInfo() { return req.getRestOfPath(); } }; // servletHandler = Rack::Handler::Servlet.new(node) runtime.getLoadService().require("rack/handler/servlet"); IRubyObject servletHandler = ((RubyModule)runtime.getModule("Rack").getConstantAt("Handler")).getClass("Servlet").callMethod("new", x); DefaultRackApplication dra = new DefaultRackApplication(); dra.setApplication(servletHandler); dra.call(env) .respond(new ServletRackResponseEnvironment(Stapler.getCurrentResponse())); return true; } public String toString() { return "call(env) to delegate to Rack-compatible Ruby objects"; } } ././@LongLink0000644000000000000000000000015412255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/RubyTemplateContainer.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/RubyTemplateContain0000664000175000017500000000335412206724733034454 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby; import org.apache.commons.io.IOUtils; import org.apache.commons.jelly.Script; import org.jruby.RubyClass; import org.jruby.embed.ScriptingContainer; import java.io.IOException; import java.net.URL; /** * Per-{@link ScriptingContainer} portion of {@link RubyTemplateLanguage}. * *

* One often needs to do some preparation work in every {@link ScriptingContainer} that it uses, * such as loading gem. Instance of this captures that context. * *

* Right now, we only use one {@link ScriptingContainer}, so this isn't serving any useful purpose, * but this is in anticipation of the future expansion to handle multiple {@link ScriptingContainer}s. * * @author Kohsuke Kawaguchi */ public class RubyTemplateContainer { /** * Subtype of {@link JRubyJellyScript} for this specific template language. */ private final RubyClass scriptClass; /** * Where we came from. */ public final RubyTemplateLanguage language; /** * This {@link RubyTemplateContainer} instance if scoped to this JRuby interpreter context. */ public final ScriptingContainer container; public RubyTemplateContainer(RubyClass scriptClass, RubyTemplateLanguage language, ScriptingContainer container) { this.scriptClass = scriptClass; this.language = language; this.container = container; } public Script parseScript(URL path) throws IOException { try { String template = IOUtils.toString(path.openStream(), "UTF-8"); return (Script) container.callMethod(scriptClass, "new", template); } catch (Exception e) { throw (IOException) new IOException("Failed to parse "+path).initCause(e); } } } ././@LongLink0000644000000000000000000000015712255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/ScriptInvokingDispatcher.javastapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/ScriptInvokingDispa0000664000175000017500000000237312206724733034455 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby; import org.apache.commons.jelly.Script; import org.kohsuke.stapler.Dispatcher; import org.kohsuke.stapler.RequestImpl; import org.kohsuke.stapler.ResponseImpl; import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.jelly.JellyFacet; import javax.servlet.ServletException; import java.io.IOException; /** * {@link Dispatcher} that invokes view script. * * @author Kohsuke Kawaguchi */ abstract class ScriptInvokingDispatcher extends Dispatcher { protected boolean invokeScript(RequestImpl req, ResponseImpl rsp, Object node, String next, Script script) throws IOException, ServletException { try { if(script==null) return false; req.tokens.next(); if(traceable()) trace(req,rsp,"Invoking "+next+" on "+node+" for "+req.tokens); WebApp.getCurrent().getFacet(JellyFacet.class).scriptInvoker.invokeScript(req, rsp, script, node); return true; } catch (RuntimeException e) { throw e; } catch (IOException e) { throw e; } catch (Exception e) { throw new ServletException(e); } } public String toString() { return "TOKEN for url=/TOKEN/..."; } } stapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/IJRubyContext.java0000664000175000017500000000054112206724733034147 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.XMLOutput; /** * @author Kohsuke Kawaguchi */ public interface IJRubyContext { JellyContext getJellyContext(); void setJellyContext(JellyContext context); XMLOutput getOutput(); void setOutput(XMLOutput output); } stapler-stapler-parent-1.218/jruby/src/main/java/org/kohsuke/stapler/jelly/jruby/JRubyFacet.java0000664000175000017500000001530112206724733033434 0ustar jamespagejamespagepackage org.kohsuke.stapler.jelly.jruby; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.Script; import org.jruby.RubyClass; import org.jruby.RubyModule; import org.jruby.RubyObject; import org.jruby.embed.LocalContextScope; import org.jruby.embed.ScriptingContainer; import org.kohsuke.MetaInfServices; import org.kohsuke.stapler.Dispatcher; import org.kohsuke.stapler.Facet; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.RequestImpl; import org.kohsuke.stapler.ResponseImpl; import org.kohsuke.stapler.TearOffSupport; import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.jelly.JellyCompatibleFacet; import org.kohsuke.stapler.jelly.JellyFacet; import org.kohsuke.stapler.jelly.jruby.erb.ERbClassTearOff; import org.kohsuke.stapler.lang.Klass; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import java.util.logging.Level; /** * {@link Facet} that adds Ruby-based view technologies. * * @author Kohsuke Kawaguchi * @author Hiroshi Nakamura */ @MetaInfServices(Facet.class) public class JRubyFacet extends Facet implements JellyCompatibleFacet { /*package*/ final List languages = new CopyOnWriteArrayList(); /** * There are all kinds of downsides in doing this, but for the time being we just use one scripting container. */ private final ScriptingContainer container; private final RubyKlassNavigator navigator; /** * {@link RubyTemplateContainer}s keyed by their {@linkplain RubyTemplateLanguage#getScriptExtension() extensions}. * (since {@link #container} is a singleton per {@link JRubyFacet}, this is also just one map. */ private final Map templateContainers = new HashMap(); private final Collection> tearOffTypes = new CopyOnWriteArrayList>(); public JRubyFacet() { // TODO: is this too early? Shall we allow registrations later? languages.addAll(Facet.discoverExtensions(RubyTemplateLanguage.class, Thread.currentThread().getContextClassLoader(), getClass().getClassLoader())); container = new ScriptingContainer(LocalContextScope.SINGLETHREAD); // we don't want any funny multiplexing from ScriptingContainer. container.runScriptlet("require 'org/kohsuke/stapler/jelly/jruby/JRubyJellyScriptImpl'"); navigator = new RubyKlassNavigator(container.getProvider().getRuntime(), getClass().getClassLoader()); for (RubyTemplateLanguage l : languages) { templateContainers.put(l.getScriptExtension(),l.createContainer(container)); tearOffTypes.add(l.getTearOffClass()); } } private RubyTemplateContainer selectTemplateContainer(String path) { int idx = path.lastIndexOf('.'); if (idx >= 0) { RubyTemplateContainer t = templateContainers.get(path.substring(idx)); if (t!=null) return t; } throw new IllegalArgumentException("Unrecognized file extension: "+path); } public Script parseScript(URL template) throws IOException { return selectTemplateContainer(template.getPath()).parseScript(template); } @Override public Klass getKlass(Object o) { if (o instanceof RubyObject) return makeKlass(((RubyObject) o).getMetaClass()); return null; } private Klass makeKlass(RubyModule o) { return new Klass(o,navigator); } public synchronized MetaClass getClassInfo(RubyClass r) { return WebApp.getCurrent().getMetaClass(makeKlass(r)); } private boolean isRuby(MetaClass mc) { return mc.klass.clazz instanceof RubyModule; } public void buildViewDispatchers(final MetaClass owner, List dispatchers) { for (final Class t : getClassTearOffTypes()) { dispatchers.add(new ScriptInvokingDispatcher() { final AbstractRubyTearOff tearOff = owner.loadTearOff(t); @Override public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, ServletException { String next = req.tokens.peek(); if(next==null) return false; // only match the end of the URL if (req.tokens.countRemainingTokens()>1) return false; // and avoid serving both "foo" and "foo/" as relative URL semantics are drastically different if (req.getRequestURI().endsWith("/")) return false; return invokeScript(req, rsp, node, next, tearOff.findScript(next)); } }); } } @Override public void buildFallbackDispatchers(MetaClass owner, List dispatchers) { if (isRuby(owner)) { dispatchers.add(new RackDispatcher()); } } public Collection> getClassTearOffTypes() { return tearOffTypes; } public Collection getScriptExtensions() { List r = new ArrayList(); for (RubyTemplateLanguage l : languages) r.add(l.getScriptExtension()); return r; } public RequestDispatcher createRequestDispatcher(RequestImpl request, Klass type, Object it, String viewName) throws IOException { TearOffSupport mc = request.stapler.getWebApp().getMetaClass(type); return mc.loadTearOff(ERbClassTearOff.class).createDispatcher(it,viewName); } public boolean handleIndexRequest(RequestImpl req, ResponseImpl rsp, Object node, MetaClass mc) throws IOException, ServletException { for (Class t : getClassTearOffTypes()) { AbstractRubyTearOff rt = mc.loadTearOff(t); Script script = rt.findScript("index"); if(script!=null) { try { if(LOGGER.isLoggable(Level.FINE)) LOGGER.fine("Invoking index"+rt.getDefaultScriptExtension()+" on " + node); WebApp.getCurrent().getFacet(JellyFacet.class).scriptInvoker.invokeScript(req, rsp, script, node); return true; } catch (JellyTagException e) { throw new ServletException(e); } } } return false; } } stapler-stapler-parent-1.218/jruby/src/main/resources/0000775000175000017500000000000012206724733023500 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/0000775000175000017500000000000012206724733024250 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/cache/0000775000175000017500000000000012206724733025313 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/cache/haml-3.1.1.gem0000664000175000017500000126400012206724733027367 0ustar jamespagejamespagedata.tar.gz0000644000000000000000000125021400000000000013324 0ustar00wheelwheel00000000000000M}(|֧XIH:eqҖ%VZ=u^~IVRښⲻeUb?3o]Jv{6 `0Kb3^~~}|W>}[J>byLV}8%$4&Y3IO7(~{烟so1-<$)HMbugm-OH$jښT3< ٭EfzLGYNxw>Q;[ןo$/l |>Ol$OIw݌@LI{4FT9 "g#0L`p#OT<S|A/f1[s?G2.s$b_$sP}%B3FBjky6rLf#զ+lk ֠E2i:ao1Q=ZnSl-b\Ŵ5|"~$y , @zcF4IFNi«QoEQ>c1ܖv56ێGq:ƪFLȝ/de`0qz X {|`"j+! Β CEš4\vx1P&i9vH!\m ^\&"Ml- 312X U+ A@v% vKn^>=xj_CfI:,Wak$!:s(%2?da$n¤o^y$_Q/wKbX7Ȱr۠v|ƿjS<ǿvmMq0\-mF6 ?~Oi ˙ŪoaS!6Vd\$8?$1O`3"/q/o be$,B SdBU:簗VY,N7RyAc=o-x8P؎ hpYvm%HV];jqX#[;~]VS!ղװ jXZ l7.Uުz \@2 ;CAO>`n@*]nL1Y)dgK0Gw[)V ~JOsKʆzn̼YYf]gޜˢÎ?gZ҄š)U`6˓"a=RͳZ'ڍ_jcLh\ i}pUQ_iy)@o!2-q^vWU"3}a=Ácw?i.*zU4bgAvOz4EVio 2?px> Pl5Y4nyb[xlR@X-㲩[38fx-J_qxXV5ZD!^ .,- wEME؉{~Kna5Q<)i8B8"Ճtq*1H``3$.ꞝG<&4G S xQ,.-K&kdAl*keBW7& \WbwˋM:M)PE)Z8C@PVg 3v2^rVa]8,d8L/_H;lq}u뿻Cn?2pbVz\G+i]{A>'nɴHER%"Gѹm;5z YV AJZiA?N%d/ט\R?; v%V@?f;z`o-z+.4Ev8<_$M|[lA>\2śqm{҄ v>ra㲆-̜jb8Y{Z12R.o ,錹3`H ځK=kxA%Z33)վ]>VLO|<6HڀBNXLAy 'Jfqlq 0&X8e2V4*f0CʦRVk 3J ݔas:qKD>Խzf!4ZtYx| x ,a{eU<}[u-&#0H*A>Ti$ؓotge\`\yr}rkHcx@:žչ-&;Vs0}{*R4m*N QFWI:E*v#UfNp]b#: }nA/ x"ռmMkIR ?eT%Z Vf5,>GIYv`*=d5u'27%8څJGu1iӁ{@{{AbPW@0KN}1f1qu7_J`~ ӛ˛^?ǂ]COчV~o١jzwW5H/wۓEd p,{TiN;S81q)J{jMP_]]fn{t uǽxz]o:y0'T4wU'G)U^~0!(!jݲUE<} v}IB,˧V{$%-Q1D=ЗnbOɼRY:~Ke?j d՝cj-iX3n,JNQ&.!.-SPa,00$86~|ݗnWoM;Zץ*_ ީq[E~MSAb }GNXy|.fU6TuK620i8dZ[((zoC'EzxZ;RN4eu?h' @tONLmV㙁sx ! ӑw<]l6av1nj~1%ҹkCNu -0YLnZ_={y2BܩhN~_=+p_<33Uw{@~A8x70a 028 ]ع nGea̠ bԣhN~ճjαQeuna2OrvQx҃ҿStl*mnlIZ+2z B׎ u`s򧇞W??;xbO_>}c|E8QQK[<7dK^oL%n~+ڴE<1=h^DZ X 1ЁG .`iF?x}}BO_q?>/_>/? RAGbVzJh&OsGc3 5DrM# V`QܦY%^E;4]~ v{sv󺪳u,;@ l p8Pn*b@"[d9:29K^9-e  jG#uhڇƿuÇn67I(p"*S'~q ˏu>׹i6Zǝv{wy|s`eoɊHQ߲ɀOxb=!mAbNHӑd##B6u(3htZM;tDtsV{tx(:͓MtO3ƈIj`D ,bCTvcND{48鷨?׼b!a;G;tʡs{(ÝU]4d F{/j;ol-m`I<#[k Q5zdz}OKsMq'YLMїіΊ`HkC<~-Y8mcE7jE? SaVP ~Wt/5 \/dt@Xw EKPڰ#]gQt+~@̀;? |ׁ]FXh%2\2>{QJrs o 9&k_e;4՘@6ٍQP q% -y6m8A<07 VlĀ(E/@$WY>mە \Yl,Y$=,!M<HapWb9@`c Q<xy5GtY,>NsD G~/HHt5}.nQ4[(}BN\!SyD8Q q2vߪ, iCJBjsC1 l^ˇ<85^oiTd Cܾ DNJJ|Txm[w .լ{hSz0 ^רUQR6j vʴAۿHt*z^:ĉ較s= d[G@B"^ x%Ի1+%4e-ȐNJ^q~ʲcRf~mP;T~r1' ^^^(;V(Fjh <Hʩ'si\&$uV>j+:ڢщIeҞQ~k,T{.c._1i] v5JyB]3қȄP]PǙ9@~(~0~r}}PĢ!]V!TJƫ^xo&Ȼ\\`e_.HpvM nWEJXAmcԈ$^/y'),'m"k XwY/"@o:̥€E5i}f!٨{˰u8Qe [,:5BϹ]*"]{y=r*QKjkd^ hɆ6EIԟ<wM6hC:Nu/Hq& G[ P"O:Blru\Ɇ{/Z('((HPɪ; ̵l="2)8>E|eeZV ML+*8ReHR BmL"f'z[ڇPZ=FsTK*0A22N`e5^*"MeZD?y M 6PtYEsܘ=qQ*з5$w(>@pcV[|˦I~谻vԂ eU5V n#kkt~.cXyxab1CVUBŽb` ݢri0n3W55K_yB|5; FY2eLI5Zs/iȼ%vY4y*xb%b}޼6rӒdĤ;񆤠U˼PZ"*X; `)u6p0Whܑ'^\RړPpc+ŘwgwQ<,eQ!^C8bpӄ?@<靠IS]Rpj0^+2r/e5\XQ<xFmm6w=X!kLoia̸^IO"+xojݾ 40\NH;`z@?nnil,{>ŻpC "jatBgkd 0:n}R;϶Ui˘¥IZ>UiKt$e9Q/Q=9Z]~5 ktW*P'ÝxA)/ܽfOk{)1&6hM& m3HCK]5#d3Stvot5[ӱzd}(PV `NdXG\fm.}) ļUzvo(̫LZXY\ꭌI>B=d kMzP Goq_Ƭ#WF;F ?FtnG7¨Mu'ֶwzjΝٍ5YV2l|+G F".}9ň-l g+c@[vC %`QAg~63)?OEIB%=d>iFT0ݎNZJXbEB.7ۇq}~7xegC1yG+mm}ªӞӚJu DUњiђ k1 l=j#_*]hvΞHTNT7퍺IEM'$+tX4 /MQ+٬+n9㷩f59xסP8Ol:0sd(|[-~*ڬ8K(yu|ܶs\GQy|݃u´;BV0va/1 9HŮrćGqwӼ9wJ /GhxH Q7J3o$nI>bgĝD(O*V^ugJ++t] boKڀ\7]?,uKcSϹO̍j! P-3G1窽v9oя暩LyTƬڊ4+rq]ݨD@TF)GY޾*UP)Y hG~+ F fVnX_J]`;DTaDq0pzbP>)B Ůi(͡P{}Wv6;QsNټbqY4/Uk}=@L!.V"O(݀Q~tݹ9G:8x7Mx)ͭyhqN-n QAߣV v 0؃\ ﷻVhjFn fNO>IW⮒bWV 2q̳fl[$ m}ѮhvdAyݼ~\6 FlxeYw]cۓ5[ -#Oy+a*grG:ٵmV M [ ׄmd 2ollz}pñX"{(F5տrM%{`O0س$oم< Oȇ)R 3:3`$' 1PZdH$HؘO)h ;ҝݶvQ|`zŬMӳIUD|chT,ylۺszk1-@ O!=@01ax?}>#_#zA Lb7 Ue#OfY>M~GČ_9㜎 ԏSڥ1J1z۔J}\w0db̻vC:WnH}\t 9t{EpO?)}##\Q$(+V~_o}]48Jo?l?܊m}ǯ`Bjb1-aF\`|8Wev $AcJrC:BM&Lfrǘ`|x9I};[Q;v4ǽIGZ' ol){ \L ٖ]Դ-c[=M% hIpQOM 5-lluN8᣶uc5'F|7`}apͧoYZ홐tE7q")]| Yqappg[=ɆZH;S*mALZbs6ZH.'ZP!wD$ZvI~`M ~rm0Hv`9堰بQZ㇝>d\ LkbI% 2âxhWzb fPw O=D!Kh!f}wȦp ^?xt{`RIb(4d*+4<(iH(#*Z)5] Iۊ3,.l N !#25`A(y,L9~]{0ס5%_]t~{"Cʒl e!rxBJ?剑il:pm/8~#lϥZaK#'fB=|O:՗,DE]º@gk?37e`cxm +^yy6]yF˄^`UTtȅ-k Qs`c: aߞ%Sr&x,l{gC;(4`b#K\6 nKC$ W:B^ܜ#Z\*xv- J~]<.}A l(E:bE,BN[u=e]vkl׮@M2l 訞WM[ \75K*pt<J/ު[n&4~k{V;J0ܹ+Բb(T2sN,48D1]q9Qpln[9IpE( BG zlΟdRziHtL^ȼ,%2iqNF(ӱvƧǛkI8:Oklj2^o3u9~zFּbKȪmY]o;u%ٶM5U ]Z9>- n~*XfZqfiuzZ[`^pB:P TBͫJ@jWsVÑjዻcy1jdN, LQn3XKX&sU;e뗛ԏ-`FQ㉎r}\ʗ( Yl2pxÿOցXPHʨ0x `wޯ3IiC)[~|WSMvO2l^)QuoKlm.c{ݗ/#jQ}y:lTi\Cg[tuAċ@~OzB6#Y1/'3@0_iuKcw%Ω3u+֩mN;P6?h]:܍I}yJla_ 'FsJޒlnBi}a::O xb-Q,&*3T㣨R4շՆjŽ.*P(MRD"r-\rSz_0[ $(G{ɧ^Hx" *_<‹ )ߤh&KCJV\./1V`AKD@}DX h% opf1VrjY=3`2EЪΏ^j^߯ hO,UY1zC_Nmo{D ?*vK'Ռ) F}*n baAd3fBc` I\~zODy{H:D5ZvE$1=O"1r(!$8f) ?8y*g5hx_\tzUF67ZjV3V`!. mi箮[.jy[uF|T}sUEa&A1ĦNw?֣7;FlbaS4kP}6hF,}΁ b|TϤmȪ/s>c90+ӚU bax+:=/Z1EhlShkH]h3^‹v"LeԶ6c{u7J&N86]}g$B d ]eSF9˝UqSL]n ƒ% 5SvCw ='_DT<(su@πbJc X+p=pt @PS"ŸNbN[#8e WMߜ(Ifs3SŭksG9gb΀QH[h;Y)b6BM!Iȡgˆ!UZف2ѥaV4 U==dY>'KnJ{P [(YSfL!ۇzId/xUM ) .n"ZO!,u]-evnQPXrek%H9ojX_ngnu^U=@5<0 q0H^&OkǑ*UzU}6v;GGa wB:ߍ:U 4w0 ɭ22,SVZm ֣k?')io7v4\4{ %r# ?0dC H/U.1 !3{R|->?ƒF/CEMWUDLCpj_& wd^IL謼7Zz2c|eoX!fz@ |{ҼVIY3) 8[+vgNÄ.v2ACDJ'\ \Ox}zqrBp6^{.KXDgY>~4 o sK&k,U=B J4Ku썎C˕sd`b$kӹ<;ة7-` 9iH\TRh5JʰA%Y>:9j]ojr8f}2Zrk4yxJ+}eQ8 Цg4u7 ߣt&[GT*CZp$ ^j%]6_33viQKXvitaȀb.F{% FAHmT!%^6tDIpۢ\1N4w.¥%QߺBo:,]W==D۞fs(aQGDck"ŧ@Ng[JDҕ9 Օ?߾[UL0uÛXGG<MEy *M'0aY'm˥)I?PLyO l#D,7ot1IDᎡN=Hkܦ }%RKH ׅUqRHtlD!`olo%m^<E' (85ɓƉ%(?F.13ϕ^ >t¥;#Ц[~i`h.6$}wj. 90BQkο{rNaqQʼzE\:[im=@d%iԩ_֪T\& ^L6ECKݚceCu34{J t2 _Mbl^ {kDsX:=SK?(|*{| _R@w`МB+-;FNy Ksu&GS ~\($-T4-)E/ f۷c?9 ?(=hi2N먈4]VeMLkqS>]2Oh@J9B;tXs ^߳ ǓmfٞTsׁ ?ۇ|557^\$>>y>Շ*-ୄ `-m2KE&jFDP7kV]_ZaIuoug$&b.b#َM(0MOȶ$*6ާMp\69IvU\w`e͖Vdl$w}Gqn:V"cL2hf!z&[f /\4刬q]"ڳ:ŷA6N`6ۨ0=7#ev4;i/GBVqB)}ꞩP{ټ免>qص=N0C춻7~6Ȁ? as#Z#1g7A@;im:5o-ݖ|LOgT6W 0L[VU 5UV#M"vz%I8~~^mc j4]!$ѳD`b+ˌ07W*HƧW1n 9 ᐍMgIGeY@G4 %fyD![1 &/yH䁨 Ke=ȞVz(K{Mz; oɓLu@I^r8[)Cyv<b*"B"%zܡh~9M<}ܙ`*+lRRb,M ci +f靍j|%.{5=6#m|oۛ mxY Ow'coeН;\ !IgOW-Dݷx.i O֜m+4NOGST_CzZ۝>"UK`q !g!7B"%U'btlϘXۈΉUک.<0N^t;ण"DA) D'AD dR_p- F@ݑM R3"mp(š'2>q8>o5 j/,_ܢiv@ʈ"tY8-ZQzəZ"bQU\o3`ulp|_?,GUaR Ҽv[(n/-8a'k!a!|^i+ qcq.aSW3"Q)1C(8(]B (J!)b`h|[tYnVm3LEh5P!{d®,TQG@'f Gޛ& $N/ڇO7=7}춎GUXW t]N?$+_6Cϯ>T."/^o$Inc8\#|s5ˮiƀej dC2 =&u &MG+1CgG1/=|Xi$ahSY6jSʇ((F>`4HS)y!SN&| Z&RCK7&pB [Rc#p1/.)117xG_}LIU89:T'c$.#&,Up !&?ql+y|h5JxX^FuHтnp;FJmW[idX9tËdG"D0?P CdOLӸH58h5r3jh}oV>pa': /}V!ф35{Qㄪ!#k DdNrQi0=*r$9h)F$f{̶$N =2(󫍧cYjre H0l/ L$=~CS@cg X:F)EdbUy]csTB_T"/M=\?uh/ ؅scՌ6Eq2-݊JG7Q~s4DõClK-`n̛CX9stH] _`|@gCrzVK(~Ml&2y  ЙyƼ0C= 5a[Ltβ8o%@:E[#vщ(<=}L6/ˁ/M4z^ЮX7AK  F2C/ mN9+T@:p,2ؖ^RP,:B G*ESdyjo C$V-sa56z](ç=X~-y۴ 0U7]f<;ij7pm6ƣ0cl3/IHQ2`gY1B߹čy2N!<}+śsCA|xWN_T}gCT}{.)I uK&Xd~cLhT(Z+(O80壞a\ƝH/YA#Y7c1q pkc*>IGH9NotŸUJ(eZ$ |燴UvagL8ou#aĴq$NG:a]389 ɖw+蹅*{o84'Zv2jLdY}\ b6.b@>f8%H.Z"?sTԴsSȼ+neU.C+64FFm?gލFǘ 1_P6M)4qdG a.PL>Wd8X%dB%nK$JuzHTȗ*D*խ؍ctu -*Qt4l݆H`SMy {!=0DN1O\¬i^$ܹ="9bƉ (Vu5AUmTF{(w{dD4'7%R;QmX!2F"n4v-xN y1# 1'N"2G(맴R%{D8?ILffdoO\Niuz(QMu6 4uz}(BAEH}up;Mk`?o-;|hA6?ܿm߿M-ݫ=V6AĪK0*z/cR=-N6J̸z7,4i{XDϽㆫ X:Qo/e{ 6}D:w}O̚eèUL܇Fw`6&> 32 o"pSUI56I$Hatݨh #UH]fQ"p@< K2mT 4&Xbѵ ec, Zx0/hwA3EIE=lS.*x>av½y 0S7<.dgI& om&;5I`iɽxF$E ?1?`K~ZŧjMP$ hiѿ K\CFd,>U-+iu$z&㞜EL3Gy q]%=i nP>5 q240z3Q)AF,R3N˲o1'}VG0F3DHʕ s}Ԕ9bƦŅm*9G0}_-t,LdU# M&%b"*X _unj)b̨ލU&\>HJC%G~+Ŝ++{2FQXfV4vosj1Y>0C gӃ.M6RBuRl8xZ[i"Y$F#@d/HrVNa)Qas:/+Ơ-i&Hq@x٣$k!䒇f 9c$4k}{6]0ߒeXN7FG NО4VW{TtϪc&͝Ч얟`rj %"s +ۘm:60e07+%ӼPI h#ՈZ:ܬӤJ 4M';¡SeWœ)5A,~s i4ZY" BJz%,]2Z4;~%auhRἽ|3@$;$>6ys'V IaV{%{R^&t{#NK6wLtof3 Pd6ؔ2쀳ȘU߽{5(U1>Kq/<,m2ٷ|Zht0җ `(2ŗ\aٌ cEw6cm<7}ޘ֨=O&ø/ 0)0s҉c47y Jc) x*\D\-q/=H8"#IʣexjI x 'x7c ^ ^S`Af/dVX={P# HYh7Cx *ȱn1) 01Tђ.*Ynf (تV.VA-۟K82ά'(JϦ^ɝD=^rwT.O݋ڦF!C*cb߰2fiY8A)G @,"Em8RK%z{V`zk$Gt\w0)l7>u"hWoƮ\g+gQi ,ܽ*iHnބG9  0);d$6٭vX^+'$2W%P4Gȍ|{?7TߋD*/wO:W/n:T~%y%[F.%2mHiZje*\x'[{Y9EFUq9DGsm O"2+>f!!AI@x><]6;U~_HHAdWnx#BЦ^2mpG+1V:hxEGHZލ/5,v$MԀ^˖i!luL21ܧq7[5Ck=K.(]ͅ*0g)~B9G?^LH11  9lRh4pG^%Ə,N@-r7hpc !3uX40i}>;*uwiй\!fYzAܟ=)[]+tJ70F D҇p_*(FiI}i^W-í-VBmn>^?8Y Z`Βj?Y{) =c~5I>.z3RE$pR{@PfA8f>UV_Ĺ,v:6vVh czMLWv6F0ET=MxBM!pN:(O:oŠ)Vh팒ÄO?!ݹ6G*LTϊt~6'ԆcHM(S(T!AD}tS&ቯ:11l9ga~DGlA0޸6L7ªk~Xf*J(oW!]Y1LhYR$Ǐ7;x^sG,I%^<-UIԇL:o^[>Hb̘؃O\^W< #zU|+w0-|^PȰT@wPyr2 8qǶ!b q|+Vn䦎loi:L6ʀ2\0Iٯ+m F R7p 3Bn(?Q =9m$%ߍ_&#[\tyKߏxL7LSGSBM1 1^mO_E]l77///{:-.z<&KYwhc_&g3PR"_$ty+u _.M_r=I7dl ^9rSn!?{{[nfO:(-^NGÜeT[t <9+\g=x'u Y:ĎW!l[?:Rx V 48KkȺ ѐom.8 dIhU١ݖn_7 ֏B owcLXw6ߧ~Czj}`2r0~1m|ߴjw)k+lGz2 ?nΘ0ڝh1sRĬsnOv{[ljA,Obh;] ׎`Β),afj,-aW5;p5ɖQSix 7 ?8dXV4)1RQU`FЋiRӹuT#;=U%Ŗxx y|NnZX"r;TqZZk:Txa):fp%eDD3= #>MHr ق]&X&ds?iLbzbTCqBv2a/ltʳq~#u;a uq&t݊8|qM15- >KU#=$!8!j#]Qp8.du@Qm`IONGl*J#dYy1qLl fǏy"ZߛO1;I@:{!.`Mni/~|z Տ]~T5rˬs4+UQv%NIݚjwo*:$jH%Զ =|5!25]M…# +k'Y̏ftANPՊ];ɕ=HǏy1hBb'xV _ȓ'D_*k&ߑ6:իwc<mw+d9yIV<[)uJL1< rxr[(2`9/qi\.Jvku%zKGo4vz1=[oݝtZ)9cB,gפn+v}V\=j~یA΀AOZ?Qʋz Njx;ўK޸c6{`-2x -;7.Sl#C7EO2m{XfxCM0mT >Lu!+pYJuYLȢQr8/_m˧d٨bJ$fB#\Q[+u.bE'<)˘t:ijD8IJvD$.r81M wV:LXm3T$r-K9:Bu˂  Aoj&S}KtGn{g9SzK( gP#Kr,ky R]# ݏtT-⣆端)|;OpatCT6Al SF)8~ʧ j.ēJI1SjeI;pQGAa(Fy2l阏O*(y,ESAu'9cn>`5"Z>bs1(1a6/Loa ~ph4Σ1H;mt+$upTpP帇݌ִ[rg!ޕ-@CGb0xSDBZ9|Ev%u(oYmr.Gll;A|lw_ג_Fm.4Mk{AS{1GS=UǗ'pc?:'4c =D~gK0kǨlE7(8뢉=sSC?jV0/G7.B5tlŔʼnU>s})U߾;֖BEQ|7>{FP]uV&ĬZW{RY~ZCpbP`ց밻u,n1:;4W7Se]EibZY`:fbuV]gm Of G722f0Z7$BZb8,] lr:Nix"~ N݆NqIQSx|`x4)G,;F I -In"Vs$cc"isRlW9*쩎0|IhG i&̷(l`I,f"Ar}$FhӱI"Z$pJYhH9ĩC@5s;B6@abnoOzGF=.w+=ڻ3'mjO ]n72.k3_}q(KHvE]d2u7dIYL!\PDio-o Zf-z](`O}7c4t͟MxAi?XPDX۾~. F R!Vo0p89A48deȱ Hi(Q#_v?G8C-*Hۀb?b;F%hl]yxQ2tEJ ?W +iÔxCP/m<\Pm5K-JM=39ؚ_8~!#T18xr%xs.Б|,cs in2cI?\+ Whޚ7«`v]Yg?>yv׾ ~rqT^Xav2!vb&xKP(87EbUR7E#i)|4T7// Lqi&{E NB9|y`Qӫqe3/9 v*An05E(}/އ*<:C4?p&=?A Fw7dU}pd{g\E*tF# %6#ƕv?٨"ke+be?UJ*LHɄo^a\ 0n9ȥ?KP\$\3MͬFΉѓ5+*bLTXaᯕi =,T[ l".^*]Հ_hZT.T0Lgʽ&Fl0v~=(;Ϗf[:`ayX:Pn2me:,:RM⢦AP֎T9xUZHqx-q]yPi55=׃5ˋ@H2KE:h8=U ~i3;Knnz;2rA@?]-wsȮ^!N'& ;Pux:V O!K@"!ԑ jm4©L81j1$~^8\)[ݕjM=j 9 4-ZC؈}BB*&mR0w/4-KN5sfK֞C;PBQ_vg(LJ8y%u;S7b~~o Y~W8l\ngZP3 N"T"m<L[CSm2۲9*i&Y eeجufk{>O)zuNSr`GKH}zNv0Il7sF#M^“8mi4٧{v~gr.E; vQXOm=1&ELPݘ"*Q*mnS D#JKg4s(ʏI, z(2Bi\on#S{ox`e4Lb8k-G|0i=I4%N\hT‹0Y$`>z٠pãF.H6TN\91Z?0cA$Md|L|m1xp01U,3{b&|t5_֔(N(%DK3/T8 T)$uU3VGAHD+'Ru>T3晎݇>8}6,gkQ2muEқ|CC f׵fW0Ob0ZEmds0Hz@[?z"=|Ze$D$ I@Z`ЌW0ݦCDzzK5o]9!*nE\RX L4 p!_'݁<9o`{}ѫok?4jف&7BmeCaYή> H]4J|=XU#:шi.p{&wrsXLk+q[)6\ԅ[G2(2U:ZE,>8w-Fːogn<2lIB[2 8UÄzmn(+!-JXҽ*6D1\Oy5dlm^KmJ'FpհnX)͡mλTvQYx2N66.IC򭐂LeZ>]0ނaUSܔ12rè4=138_#O8Û}ywJ)5SY N :X38Vi/{kZUpd(Ԧ$2):33؏AP}meg?N. S&2ppȱ-*M_b~ll\9Ń֡IR| -WANP3u( 2[=?6lC|-.ZG!GV0xCa=A۬a ԶQ|X"쏶9v =~DWyX*Ny7"W&(FȲ(S7EJ)bP߸CK|rnŐJau$bկEVVu!e;%Яp-~O<%wV6,!U³3NfK_PYT6slQ&'қR\ΫVo,e%F(WÉ7qja_>>zܷ]2w::avtN  hAqO0th|HQzd8U3P~nW|]6٢tO COY"Nw: z3=EUηE6anVwaaD> *=3Lѩ*?O'n6 ϶ir ]:Q5n ^1"h[.N1wL!CB)ctRik((c@$w" J lFF9՚)= 3]bV^8zUiY@˪xя>|>|,$U.9'ulIKiV{SX,]Lp)z0ᄋS@s{݌M ˩n# chQw0$3nZO tז8jt.3kvw;|ɳ5\$4))z%Tq.g-qZfAɡlc/ 6"-m *Ɠܻ: ˶w+mKv.r×?2

    ΃)><( y*ERmrXHEzY།+h.f|B,QS%̲1JB~S`P qjҀaqBxl1_&c"MM)6rl!d{t\rxq0Y`3{+$k`X&Its-H%bi ʏ_1 6 tT8 3'JbqLme-.-e+S񼲁1, DzJvtQ(¡8BN[ ICQYs=șZKi~wctPUQ]s},h=`(6yMUFF\O9J"h̢Auʯ [DD񪊺ŷ%.Go: zCA KlBRdY֌LvQp#Fg@]کe:LGH);UC|%Ns  0[D%ބ&NKgmː&3L=錣7׎Y 9Ao@[Ϗ?{f-UtQ+_="^g?<_9d%5 י&V2N̫Ne|8oZK AUv*};:3{Fw_3U,JYMCĜ^Uf4ݤo<to]f$(#te7[s@`hI$=3<Gg~4CT tj7\>KtޮMn|1E#3c#kӈz$}Tz/zAZmlWن أY7 J&s(7%6l!^,4йjrN(ח?e0I[+tx2ұ"\(4aW8e`X|`8 FvhVZoCgkmۉAXPNBOHڲ(-?2 <uPI.ܿdE?LcM+xa,st\:6rUDodBj;''o~8ybV~41[BlӃTGIB:"d#&:SM׷/ownEΙoՋ"x3giZ*L;i4ٚ`DP7)+Umip`=ϩ^|2=oOf~*c B(0c[yFŔ5Ul 9\ C!k6 %{kQrT X#[p%"?,Ya7-͒C(h w,R?ũusRt{r*bM8iIOɸ\yU=Y֍LmKBZ;BoQ.itx1 /%N@mC{J(qxxζZ(ZUT% !ꬴs"6QRۃT_ aygJ ~h-EE2׃E~KWUyOO6>UV9h:<~ E(Ctb,U"]0;h/<l+r[$E;K+EPu H69lԣp4*8mD]gvWج{ۋu‚b8+Cgm,h(LUo:Λ9TB{FKRdO6)Z~ݎX/-F-\HZыz͜wR<$4*b"*RꘗIN+˨/Cρ2bDU͞zfkLT0)[dz)=0ph>Qg?~c2yѣ^wgSh:O/^_x_)xWr $3e=2-!+`AXk|r[yq2ZBSUDZ@JA1kL15JH <âetlpM̶kUcT=6SJuubb^!.,=s|R. &E{M{; 8 "PTnNhU>`Xd?XvMiIv0 o#K=AC8qrtWj0m#J2Usvq^{-- `}[ |W7N|AЅX\K3\Qgtq~ɸȋQ(qU=Bߞ q"3;&(C6{-%Y<괡ȊzPEa]~7 G맇F?a]B|] 6\65-;*&ת (i)H$1|V5=?4A atkprt9ٖJ:,u6l$QxyF޹,.|o(gp/H(Xm=hX'pU:,M k9C:gH-(S9R0)[]cc&b~4:P'×T#h* Q6 23 mfcqgn9G~I`#eh8S4UhIH? oz>F8~BG=7 !.6(# /bsHws(f]OUB"(*Y&bH .dP"crhxUE>,O(g" Q-GiWf_Gt+cE/f@V,с-enK/=߿3,7KEMgD^>н!> ,^P B惮W(gڞGq,~y񣉄l;+ cT> >mEл5wzMFz8h*@i?M#R+s6׍ecYFJaKjM !zDUy~ċIZV6+U:|UZbס_&ps֦SfpF8gr3&oהH1fEUwy!e,kC2(uӳihJe'Q l@g _`e{N0k_(Sk2\Ђk>uVK?P!x sqCw 짺lSΠ15Q:3Fp@CM-i8x2`\Ql?lw**ٴ A =Ow9Dis9-WYQMF3{SO*!#pՋ`%"<#ȑB % }9 IJ4p39b '5T24R}*bRZ{+H+YF h0cKmh2yOeVtEK-fBTDgWY@UѸrΫst>4g2ܶ^b=i1fJ-b4J̠=EI423Q:IW?I-!զ-cr@&P LKkվY{Ԯ?j 4:aAÚ*s?0Yޮ pF:~%Uurt$!qcfh_o@$UzB`_A[mʠqOHpX) 81=(ݮ @G0]TFhҨ\ ߁?zM"s)>zL0‡:e7Ͽc|Xhۉ#UQ/fPHOmUnlI :Ž~HB5sb9x#`HNy-b3XлWl+ȑT=5Ubv E1Fpޥ9쎫_lM/kQ]TН,/3Ƞ/*~eҽڛW$Ko]^fZ~$GLJ?mUo= c&urv58LQ8hPfhM܂?, -9ю-UB0\1enuU54Sg p Zo8ז~-ؼAtgxiep#UM Nu&]@UH\>fv?DyʾK&9+JqGBllb 7>-[,{ B;[Hg{N;iNz)Ͷ Ώ^;r@:PWzUo248,+Fh abZ1I˔u#2[VqV}aczFq`hdt w>_‰`~e @N JQ7EgOԒ媍V[o#ƾtvu A2z̗E&XdpK^aʈD2H>2rqNz۪bCG[EF惔\x-@ ɲΨCck$ww3B簭DJj>\^כ7 Y3T4OX1yd{k8M_Ptyz]5b'-CX$4-1_<Ңs6YCR a;h&H{t`hVf[),2c4¢M*nz '*M7+)1)^&ˌC 3h" Bٍe|7D:+t>"3@+ceЮd8 [\ l2$Œ,02"P93؅v%VܵhR 0K RA~j@DA1xWgᅐ"wJkz]%28SR"a}AM.jϳ{JېVD#*%1j4l'N/ $fh4併@/8\k邏~ړ pqs " O>y58$Ŝ v"=ozzf99.BXck=`DڢR2%?^ ~<Yj^ M'dxw~X<"PY0:snmxcGAX-at^k L]'TDHVQ/b$)Dw2/VWڡ1F3z-Ӝ^Ip6Nݮ-qkpxrgσWm:p|τި 컗;/澚;̝N+Ǧ (\aKq$O!ʄJ}x5dUKWYݨ̜8eŅ2Q&`es#s-X|dc0q2ZpdstА:MraK7# X! 4w2KEҫd"(%1,Iw$2:`%y]w ԎNA)+$@Rc)xyf:2NYN=ZpF$ȝ"<穈<K^37aDIqjf{51;j_Io45OU}Zj2!O\AĿNݞ4,5NyR7o7=j'ҫj*0jMU'dc3d[Tǻ3n}ƏD-жֱjfx+{]4`DDy3GW3;L,8t7C2ws+3]>k#ߋ8(,s^E{u%ׅ,XCRlcHv>{%}A|A젍zU# UH9ʥZfNjxh?VF:̜8Iq kVr(ZV^`GRs`2]x1= ˬ'NJ|7.b Yg.)KBF9{GoxHX6+7:"`qq+ fKݎpS [._oXS)Elzxtss2ewtcZ=S5\ޞ'\Zf匰\Peӳ~"i-1U'?W] rr};E7fF![Y;5T 0FiFDj 0 .uWJxϹoN4?"8 K w`ǂ<aFn4 FNkgo' X|gá"UGR TM^KiuXE肱|y[EcOX^ dYso(ڞ.ÔN=pP ?]j,RV~u@Cd5t O+|wZI f17m?9E3bQW0 F$sT: rNBl}Lj5J <,w[C(YP 1z\f*c%H:$i=$U皢4m<}\\0aݩ+Q3z;zPT*ϝ;VŦLI&~n܏0a{ I&2bNwoСTdeyZCBOO-2z j%2s7X3<C2 )4;Ti1zHD֗7Qv/*wTgAi~93H[1wwmvAsbFk1+;y-UQV)gjդeV䕔QNvZunVO^ns&D q+%Ό՗hģyȣ߅CLSZGhP5NDD":h1J* '~#) "5N_Zº&6JgnNէʳ_K dAh˛J(Fk/eIňW0V;aT/b͖]t7f'-)Tߖ3) sM}ԣWNyD5xqDlY*!]R?bF*abI{RNi5əY I |yhLܴ>`h '- 06t9X;m-Gil|F/Y7'WMZ f8.-^p ]wэzs:1N /.Z^8]>K,7[N:.U>Iޝڝ+Cp)@C"C[y Z5Tvm9xD Pڦ},K8$ TeqE| JԻ,X(r@EZѲOHY)J@^gmz9ٶ̼TYySD{r%]i{]Bix*N)kV▬)6w"h" 2X3cbJbSrU1mġb Dxgx`|: %S:Qc֤e%ʴҺ(N2`^\Eh 2`ص4xyhTt04웻z"H$\.es(*R6H%Yh ]'Ip`%O!EX&oP 9`uYM´{%{Eew1dvÀ~WLZ.;hn9)Z¨ /¸A^,"*RM:*xpso)"-oGn*b_ |eB*6sV_=WI-iƶUppƖƋ6W~<7eLRlЙsMd̙(b/PbVq֠p2՜;t&:4SEnyZZ~V?S?_7xp[GeFY[TfԄ#:+}c/:_h5QEe]U2}O^:0g:5Ti8N|":ZkXof= 6tH}MS$v^9jT_h74'\듷5TTwIkeԎ8QW֜`AAWk¶e& F502(Iqy!ƼYWA>bh rl8Tdq~4vuо߸ 2_Wcr^SAׯI?Ԣn0  3a4*V s/Kn&S{wK7ܷӾh|cn[PC bp|!Bܧ[,@'OﷆK.BNRR(`Lz Z˥^[#%BWR1}{ tUPRniDJ7=ÆQ#goK6˻naٗSJmezY) a9Zb%M֟c *tz8_(q0B ʢMk )eC@}L:K=tfownsɮ8ęBԘ^ "{zF`U5'άԴL4T"' 9j[rAW 7VF|"[ :Tu9wkGۤ_/UWԂzusR}o0o\4`ȸx17538QM!K0""(.j> mY]ayx!ljI·~jyUӅ縻.0Dgt0[\H{ل9Q֗ybzBt|Esg\S ző8u `I:z(߃FTH g<%*c:Iz ̀4`sjbFY Kga3V.uFݹp@n~[?811xh8l`hNMRZwa/]-<GQZUi4{\ݺn[Wq=Xͮd֋WJ?Ϥ`C@恤xV-57FG!qB9sx2YgdSPza1'[vṔjر+'.sa+Ƣ5ɬY}ӪnI o8J#eZOhGF*\)|1Óy<t?E4{p}gj=q.Pu^FDzͶA{y&blԮ _=uj՛'ŌsuݣWc5{598\]|^Zv8٬޺s)ݹ)\Jºn2S}ٔgX|7e=Ckug)ݎ1`[[6]e a 3DCن2Kߐf=p(+ \nmN䙕2@ūVYsh6Q)`n=iYsdnB0;jĺ;? Z\c8Xmc;w[n LiD,ZV_'Z0t1QdN+nz)dz9zO/7 -v ZMۈ=7lG@KS^7 džٯaT>CAY࿄FA\>t$l͂=$K i@[6uǬ !ɛ^OQG~9|qѿ^#R}_ylɮ?y}H2uIU9cՕ8gZΚdv(2+޺q^}70/ݹsǃ8P+XwWFPC$)Ek8tWVo%'Xn~y=w)h A w+D o&%AI򀢡s$tz?s4T, 5AolH!Rh6CHe l:𾩮9$sF^U !ԾZ%I"؛{5TNg3AZT *U$ݲkiRϟԐy/iPi!VoxU]INIYVmƌVEyͫS &]Ҧ|kU4`{(u:'>Lɀ5v]G8V0w )v))RPth2YsYرWբ0,:wt<_@9PEYO]5\j^a~k_6)^ky*#N(*W͗` }.vWu$0@Y{칣A 4΁$+: mS b ?b//"l%N9S"zBҎyibSf/:y )W$hua7T[{Fꃀ&h ٲ!/yZ #*ؒ3Yqwj=f3T(fR}N`. m.mG]&[nQg n O#m;?Q8EiT;#*40NFxƺ-CnXƒ7_ʽMI-ۊwKr5IH4J0\fs܊ B4OlijU#g{-ղd=pgƚ-mf"JōW2ie1 Vly|IP H7֓¶>buISMBMC+~[,R,U6H؆}Z yQ%ꒉr T)Y᭶]qϝ#2D$yCDP;J[\P`)-hћ./<P82К֯=|ǁ_)@_ !u-}%@n%A$9 @Gg,M/;M/KeX1WsJF7߯2&+j:>d*Π-Ǟʾ1hxǥɋ/D8/*q͚[V(yI:Mv䘴#[jBkgGEpA# dSGҁpRhAi.U|f7Eܪ1O%Bq &-KyoxJ]7-X(f{w_!Y7ya€bvy Pe=+X`e)pb:@Em!&~"OyLhDJp"_sab?~ ^=((nh[{|Z\Mru:F( xgUl'䲜#W&,ˤ"ǬC}s4CxU?jл@Ǡ4l6\Cz%ec+[[:= _IaViqNR Lju fWFՀn@\N_SȱEv]Ĉ\5lH0s玷=$_ = A F8Sè0͎@ 6!9=+1uySP8!X94?T*))|*ҎuHG~kgKD|W~-\Dbإ?PЧ80ASSgz6d:%9`24ˠ߃|`0:%3v^j_-Z@MWC/mx'~%lm=68t5xε*n{kRMܕBv~Es-2x徃6X}tl@ ۞fƑw|w="(+9OֶfF>Mm#%pI{0!o;]8U;:^F{Y@8ą]]y'*TLl@d%jG6^uF5 5]c,ʳ,aV܉-GY?t]uT}{6xH@`4#lXbNȏ@N~yG/μԿ(z[ B"Doܳh(OB^1Z!0nз$Gjm*R\75 7j/y7YSV0A ig7{~HىyOv,F>>D&kU%&YAaQ!~GG7o׉n!sng>+`;ZM]PCM_4q eM{ ewr4mwv ӫRce]XjHS+5?homS&Ýl/v>(KA."ww%a|ѭ ,35c!jiUA9䘝mTYJ:Z.uG3΀[Rһ?uO|/?xiO>b^d{8IqZCJ9X"t٘z/bb S(K]I,>SL$hVȋqY2L.CE~W/?4?g*V etm8UEej xDed[ˍn<*H7eNJӜ8 `-:T·tow/?4?ƧzHbfꠐu &4E:JHM ?e~CM}_eW?S4kIV$ve倍OA^cNkn >𩢇1{$x"(<^6w>bU\Ool%܅O(p@W9w>-%Ύ3Ix$Z 2D?zIjAi*d6"`XM&A: %N{ଢ଼_z*HgxJ3ow_#. CzqpNTz|HG@l+]1{x I]/#XGGQXU`i+*̤t۾! d-4U>|xj|\Qxj]?ii>=..)}qNGsn7%FCwůxʿ$)MH*[+*c7#ɤ5q_o=E@w&(?yDjB+~72 gҡө>glt9W;Ys>SxG$I6`']hW CZ%՞8Yy)KyCOZ|8OfE,bEJ?Xd[Ŋ^^ۺwW6Bzca\L#m4b!7 /fuCEt$hY+Ctʥb/);-0k7=`* EM!^63ǰ#h#To4fĤSq8آ$ʉ#``\Qvt%vX/4gZu jl#Fz%hЙZoR@)/ѿUzzLSA^ z '%Do4S5I0%bҎkJU0jLJܻ$ն6oR v2jK8pAc0W>⸠(!RUWbbϲcC2KSJ%=!G\DBȭ`O7Ep+ |)HB]F[L +~>'J*'dj rB_Z~gSْp,9v*V P#J>N-$H*u+ze*NCk+)pˬ( XSq5ay</ }V}UwZd]MY>7_tU^qjQe2c8P~;HV^8;.B@Uj< (לZÐ{Kp NL5zI:(y?2meh(Ӷ 99 !\>F犐^\J: *ۂUY4oqeE)l ZQq}V5b2|R!g!%?/*#}p|Z[/U=dCu)o(+yeS;9y5FD##:d'a]UϤ#}8#$Q2a Xy|FP$5K`PxT*W<Q87Er I/k?:φ?.Uܹ ~tO&ļ{ w0P_XsӮoqGzgу pQߤE:ŝޟ\GTغ5u=z]Si+ȏ|>K& ;qB~`z:'a1^|n`t^ [wcx CYap ưgNcV#<{C},v+ӿ P:cNa@A%9-ulW6eށH}'wԤ-;^\)=o{Px4%Du=ߥ,(4~ymy2I+#y|e٠vE5) Dꔫth&զQ4pG̽I F6wEKi ivJ-@k#p*@_g- @7gK0Nz[-Q"T8(/hà E6QDT5W, NRX୎sOA9nD@taZ$a"3PףGiph`|,9F8[ ̦!^٪u)&eբ|>R5KZ/[:Fݵ#0XK\;g~Ws=vT?vDN+kEV>ru5K͡MװE K8" ;d&ecY<ҝ&5.t@(&QɺڒX86wRT,E̠I ]riNJ[H"TJ+s?m[&_gZ" cHzLsx7$,IMOjd+v!OU›GB.+dd~bj*z E'Q .$X{K s8ޫUҫ1~uݚmݕ by*gh|VYjE`\f?2u֥,n$Aչ/K%m0X\ry72i*^x$ݫռ$:h5]+HyӃ44gt2ЇV2e{U8`PnE=%5jK?tSW;yPI>D e|VhXL;ꐖl^8 P6)#/NlD0AV֥1,% `Y[t4C ⧇ 6AZn(#g6 OTq` )Y,aZyox)ZȠ)rhI$G"h,K>^v ̾G7-'"GuWuUwuzM% D~j1S66n7#oB̤5QʔInJR/)0Š#1% 9x~ȆU Z,+ki'yk* M\`0v ` Cʍkzm7 =UTGZtR-gFۣ_>RQ~; Zrf倶c}TSF 0]>pߧGvF[_~zg(|8 s9!L3\' 9Jibn|+j4n4 c[ӛOC)bHձ4Ԅc>,{敶|Lu u[tC<.I'~f^tz3y9NNi Bpe(^h}[TKI>&ڌ=`Xa98%r(4ɽm,piaO"V{4c͡Iܠ!3#-5HTPDŽ3aѱ` 5 j$5&/50۪t4F2U`ФI학)1RC>A<[wTN,C+am|+uZv1mB)p`@ L'؂  |0"Uoh2_=z6= @[*]0b1y2~) -:͖Li"%*6fJ)i ubK]Tʤvv)F'WRSPњ,g7)2JduK2PJ Edz_6]r e2@r gkϸ}q*Mj47)ɱp5OQ%9he*Wa_[r̫gx\+bbʂA9Frz}]4~iDNٔnn;Lb˙U\yd(wU!VR$mmr.*5kŽk3B ^2 ;E?6jHD{o凣w4ʊmRaM!Ď=uVg?<VZuZotRs6i=Vbewotǰk%z!^4X I!o?4 9F8?CӤyi \Y-LeN}?!4/}$O}[GJr:z35n51N BA ^Qˈ}-̃sت𗽘 @TF>oOe:Y-OYu.9ĥywrY0^ŷ~A)qPG 7o`]o"$$}ĵtu-ȻP$no*(q q\Ȗ-e C!4i+8(M꤈pcESqyJ)vTTሲ5IF;FeDwI>NQL8flNE+kUV ~ *@4>?5Gs,.ZAcRrZvN$goW~Yb"&D%4DLB+LS ,SO\VQPq} z|h)6 ;O q@n\%o_>6*bݒ;8> y"c^"` ]B+l r8y31{?u*!~R_2PA+saw|0ϫn螃 ]1|qfJ[W+l Ud)5sشv2\RֳVB8)Lȁ"XXgV5I(9YpEKs=x׈~lexHo_{y׎綻tw!xǮlԦl W!vݒPяuN/zl0H!G/ }9~t8 9z*yqJ~s/^FY`|>Y0ZAR5N`E]zIЉѷ~<Z iԌWx瀶 ^kYۆ Z ߘlyC׀GjcΩtU `v#Y0B7h I4W+.WzD (X' ^U5ި=a0i*m9s\U9~* ,0٩2%M+`Ⱦz;h줟cZ+B['}<-%wp)mPzcJeCiM߻Vu =0`D}bսTlWҴ/c$u6槺?[jwAqRmdʵyۅfK菡C+a՛jՓr T0M>Wλ瓝Ck|׮vo=T!hʹZɻNZb>Ͷ:@O穮~/ v1-VG0hZY<8Z^Hb4 tqդz[yh1MO4Q𲍣*u WOF5iESS\f\ G{[ꐊ䓪[3 . 50WT*J\>zY׍Q;Y͝g@ߕa+!hrw6NDG6`RF -LMA uXHg OInE6o[?o߽y_Vb$9ty P`lhP 8q 4I'W}{!%*zNQIcܺCl;s1kYDd]#X!cx.V\͝Z߫-k+{!œI(ÌpGeuE2t>VT1#l(1I@rlۢ o{sڇkڷVu:F05upM;0HRD`}H} ,}AB t! 4VS:zaEj͌DSF4EB8()bµM)Ik]B;5I' e@ {kEIJQ?;!ʓh|sq0fPju @%UչZhim_.,Jv8dm{*`5 ͐xΪdJ [FIhUݚ}k:Ήk։^FQ=^0q5i#l7N44wtơ;~̈́$*C& ѭyH5úYKLEau83J\Lvb/dZd@+f `' 1-X|2'6m1S#'SדedQ75 nKNgLB1D Ѳ7ƒ*VRd7da .`>HS΀g^0OGmxо] IwXJ,R9=aQS,˘~A%S^g"3/mYϥ鴪hx|lZ sJ9aIՐCu6'8{pa";S8,l9S}N k[Z8Fm QPU VMk)a1@k"Nj@KxQf([$Hd:גQhƤ?/j`̸Gw] ~.]#2JB${}O/Gng+s.$s{p6 I*ӅKVG]D,>ҧρƓ N1g1dd[hsbmu]w/*D. 1ƻc)G&9ш;)UTg;e*֨= 5$yCsՌ Sdƭ=\g6ٞ˝ xWd*hC.(Fiq!-DuCk}ꌇA+Les?;%ѿ]tF+<7<swBf"agpd[`=585f20W8ӔA댭J'ny1]e9"k]ߌ" пxyI")/tѽd7MCܒH(~n[&WX&`}uZET2Uw/A_7gy`!ǽB@lMM5vJ"1ˠ Q3KLG@ZJKI*mPG%N*"1 s؄gwg~>Va^{ObsayF ˮƤܟY]UQ~B)z'^='fr|q|PdW [4Ƣ$ATb]1=R02Gv}_>Cf̩J:D}};[sj4[x9TTf榨e tԴ"gp9fMw mV`-BEjq.]t݇"\cWB`6o.="gżQ;t!ߠ&: =*FQxJ ?HGD.7[|VY5FC#,d<0vc(5jMsF7"ȱj›"ɑDGO+{ E=XuCaz C'0yqڶKN˷Z/ HTF `//C1:Yf15GV^1[:˴h+x=_ܦ A;:-^@FU6CnG"g` ^)f@w0/HxzzPT1c)_}k W5=ljࠓw$(&PA '7 Y+PT̳a|oVsg:ي$% a?K!aBL.Cm^@\ ,~NE yƕ9BG6yЁ뱿`%Fa_X%ϖbg+Eq 'S&V\K OqڧLh (i1c25aXF.|(%c_̍Z9df=̝EcVF ќ*NQ+Īoi-JBO IL{=1N>'#–6ϙA>gCr6ȋ5YRͯИxm-g6ӴEl$g4ӡE3g|1tZDqîkౣ [Vm?HdCBOAz)>ex|mbagCtU:]sqR:CzcM imkRڸZh|\!y4lUsHS<[xVEj6^`4@8$W0z(W%-;߬suCNo7D`5d%fTYU]j-U_d62<5t6ylܮ)ƼYPn qƻ^oHJpثBBN%#,yPs%"#}WIh '7ĎCΰQm|@^qA5i LI5=v8@dcl<_ummBګ" GS7,l3aov?×O~oԾ;mcF^[[4Uۑ3xAeu0@}$C#Cvy 9۩9;>{LM =[?C/D2"{s%V߃ ˾[ZDA@S݋6h%LOq=;G o0Űw Lf82 ?t1hE[c za#$Ѐ4s9/)#u%2+izhU]q,JReiqC'&Y͚7%!ވVξ,'CU ;>h]ǡJ+_Q{{O `V,!kpMp߷T`-)ǠZ,mPW|@V~*unOjPڤ}/)Mā6ggJ{9#t)=v JUaz"ۊjF)eZR[M\RKBIK yv)د'GO&[ta,K?@|fz_1!Q+#b"ʘkY֒g_tփm5Y$,`( NlrYdNjˑ76N:_DPGCam.8Hi ^†o:!K8cqAu.Kd# oLUIrgWC ;>~ .%RVFXnMq~48}tk (3kяPS) 6t^Jk.cL va+첽!u;QU }^E+}e]ȔDx ew=(َJ/Xyں]/JbFC5B;4戯*A&% ڹA`M,k\MB38+_7΃Ǿ41C#oיv/<EFZd>9t 'Kϙhgτ`lcp]?+Ϣ5~OSJ^g&FO˽!,~Yibx22 \z`Oh9!XcZ^8V/\߁?g˽9!aX68Z휡 O|Y-eaj_Xk !Wک23=r#ޗȭF+;2) ~'8!^SzA(V67X)g U.=ו W*5[EQx 0u&fh-%Jh\VRKp"ڛ-K.{!O&OV\%-C >a CRZ 1?t{z%?٬MUlAQ,U'Z##d?J$LG`EJa"%g<1ЀÖIR̩*!enP\TݯJDGThu* bSqHsS`oJe7ۚⓟ t0u2ͬ< EDaǘQŭk9)DS%$ȕ*d'2 %NwWbK{v=,Y5ub?%G.o?%r-,IʛPam|g8x5d?c?Y^8Iֶ7I?JkRn[ xYiTfOY<Fq+I蹔6SڜՊq%mx).EP|& 9俭?H-DwI=\xHC17[p]GG.C=}#ԻmDQ9]ǣV>7y NFԶrG ˰6y{M@``\(8h*o-;PEGFeVߢz_~5>[j;Ko=߷;dIXF`)r[([lq ~Bht!:t/ݽhx%C'܎?#c RV.j)yQ\N?&zm$(۞?@߆nCht0sΗ[ʸSCIvTvn?yyč.#6qco 毘mյ oC67.i\k{?@/˳gpdJ]=5d~zc7rI 2iomfj;;K^UusT XҶ{H U7ڱ'[@^f$P(q>A}Lfˍ=ֶ1flc&kZ|!m$ _2+n9f6ĸ阼;#=όSY*U/*Yr~b6I'*&{"A)AtuNg=vK{yL?˭?v<y_iano,˃/r o6t@*.d5W!g6 އ֓B.!W!뤶"@DޢRI]V GK@yL?z55d3qz20io.{yث̇=,]|nJ5v''gnhRќ|!]B9kQXQ)0 z}㝇^-vjU$9%" ={~?4kY_QLC{0F|v2T^&Q6ӪW j &ҟs?][Ƥ[|ỿ~.PHO/UV:Vxۏ~IԜMo(份j+d3P2r:a:KSf8Ғ{ j/5`M46ʝhlc*E%*X.Zs&T M%ত&*76.b&8Ux\0!3wvA|pm4]Od 5.0IR荳^'c ߣɠ;zҬ6 L Z+Pld^9 zz h@o V za`pyukrZ s1JȉPP 6ןe":LBÿoQ^{΂L҃NW=\TGQXmH"d}+7/^\riWJ^ovŎ`Vѹ߷tGU]n<Nhn=^HsZ:#6"k4,FVި}FZxgR-#Ye{W"~|W,]ޏTH}2 8-slFְ2ЁRNN<ϯzyw?nzoiZ__wdpSE83x~;lKt]7nxM>+dCdhon{Q~Ap~Ng=GBKh%\}vq)О.۶L,M7ܦv@Lzf^%h}Ev tUX6'& p'o%XH#`rI>ֆ_`Bor[1v^u {z6z"zȓ$69Vn\zFĶy@h,=eI6+9mr,.`1RlXسuBiF-ZqmQqe&1pR﷧B/=1K,EЗ8K,[J99cGW'JfdxGCU."HL,e!`yǨ:5c#fz%9%/;AlkL=fWV*UR9@|l~2'v:t^:n2gT53eݰ.bm pyv?reUm `҇4xMM[ϠOQ,`10`D2gYI{ML= $|k69' NWX1ѵPyDj)xdPBPqG0'GӧeD]i5ݷ9}ηW$:r e>HyWi_ȼw}`&f=skT ȍ9|yjfkcD'֪}[t ߋUq[5Yʬݵ*zoǧ?,~,d;EP{|#ڦ w !/=c3.$ςΕ)`i;])q\P##ȥw+&0MEW1ʥ8WGdH*0UE˥Tne3hmK'w?8h %%Xwaz%2M] s) evGkOE5R,_e<Ua}zߟ?F*X/9s2C֦%pu -BٷhBXz-ԆH).&5{WHb[I،yAA:o|Cݠ_VLe> $Uok>)E@ KGVv 3by,70֝:Ta LxezF-B/quR(BF+N)Nی3/LjrGi,M4T.`AܢE <:l#,;3֧*6Q1uB-]jY6E4*6z=1ZɷX. Ny<̉hܡgF9ib\NJd~Ԍ,+q'@V#cC(Q=,J#CY3R+o[3?_g!8O'w Id2\hofҞa6%fC)$s×lߜk4 & :[!1ڰ4G'e,[o}Tsn)GcIm$A@SA1hKb"aĆnc̺!3^D<5bvォhj)͂ r0Ic jK*t.o߈t#׏J~B3Z5+ߐV7e"^6oܸ)aL?8f~OK/T`ƣ x5:m7x5jo\ˆ-P`\ OCHDL횥S" 4hz̄>e1!J& H ȆQOBvJ1*ssZnL)j$<&pB Ԇx3 :xEۤp|(4*|^( b`ιE$ink ]l%S@ĵɶ;hd ϸ W-PWvT! WumѝsQh[㓑mOX$p$fX_`gU^TYXGa=`:ȒȔ.˾43-(M .A8(Eܸ_AsAq*Ac0N;w;!6杭Q j։U JjV7dsyx4f!G|MĕVoffu2as}R#vڿ3`Ka'J(Du.G/ b֙5nٝY~>,4z愕Đ(TR72jHN45~z" i%L/eI|_N}rݢ +J^*1fָ&5[:iu7z:K=d'8F4fQq#yzY$U 1] 2| H^,0q_Š [s^LhyzFpR,u`xHaw]!z$  ANbYefn 4YO{UDv_1mE6LPrE4}Q w !dC T+IJ%HKV8*WZ.l(nMR4ȶ%עab0m鲌 ΍*i|I\{%]u7O5oŠ黧(P}IHF} R&@JT<(>[4hW`4ޫ2ksdWh )H*Bfy]b55˜TҢ6q|PsyJX3Jg<D!ec npnӠ$f2V,#bi'֕uhI-'va%;2hm f[FieD,+:y\-f\]un܏/XFGV!HZиj)'T3xy&F84)1+WBơGL@D xWRu#0XA6Tգ1A^*TbV]+sl3Xc ${cGQ7dfA՘]SM|%0P| g$S}4KS7)@-B ȸV,{rj. uc5Ŭ2؀F6V H,+ϋP9c btK~krrQ5#{|"LRgㄞy8xTj 4DT!-h6nȊs$ $)7(Ckb(=f`Y@3&]!uPR(Ȧcv[#yNIpZI5}6ˠ9 ڣ`8hxPHwgZrMBSr[~Y:zɇUqtށd]z+޹fnuuU<#YLb|%\בc1k2<D)=tezinM!qEKͅ~Qk/9/Ê4|ɜƮ$%ӱw@ZHY??!\=601pHKNO^OHZX$EXbIUϚzw#YB&262ZiUF]Q&Ɩઞ 8- e:%Vc), gr.7sb{]hK\bV&^ +;2 - T賣*EW:@KOf5 ?=ϞrZ9TsQ7UP.id]Dqx{z͔*i>ڳ6F++!imxJ,JQaxW?%])B8K&lߝ.4_pKmʊe)^}L%_I?۬Eu2lnַkiå{y)?͏-17NPΊB[?P.7%u~\=qX ?v`շw2󿶹[[xV~8:|ʩx ªTnV?A 5!D@|d^%,iҹrML 3Pt 70܎yP\bпI9#&[i2#%Scɖ~@Jp oi)(bn a艀9 z3(g#oGC!H ;RS݄g+Nvҟ^,y?o^"OAC3LFasL~J^?? E:+#r#Q_f?l&4DUYr%*ڢ,K ް6qGeT{B6-^E~oj1烶AZ^[m`~w?Of};G7.}<@#r ~m=ۈՍ2iRg'}|[xvA/ohxVyd'2MGAѣ*)k@%&V#IW{8[yJ{^Xޙ̥J Q ؎pʃ`%᪞_NO<9P(ŝVF0e?ta%}{˖-V,6(0C*v/Iv5EgCa&;:[UNhQ;Y/;;{yx •(h>vxL.bYzcJvK5G>g^GߒLt&~ɕ]̪jB%隂~8=氠rex lٲ\"_rmF#Ηն^4"W_Ru-}qSR r6$oY:㳅p̱| ׮w~ܑLwwgk9㉧dVUmNxDQ}jzg?=bRf,e`4Xht?RůP?CDپQLhLYG0Ջ*ɛm T r5H,I;7iԶ2O73HU֠/r- -f}ͦ*m#|,s>zdͼ?x8ѣG;*̻4?g=(RN('(f8:  ߆pG3 sl&qxtxd. K,R2d᱂`À7hc ˘3`٘0F 3\0mJohËhɅЎ\ЏvpQ}jYmj_`s@J )evxLs) Êo?/wspEP29 ly:+ =ZԡdBl4DZٓR54'qt^t|y* -3|qaJ-/4ZIڸB~gĐټq_W_O~~@$0_W_ 9i͕JReNͶt̜ 'z'MJM}̣!H#Ca!> w+QGwuNǫWv,W~嗷tkdxP+w1l5!{1}q{~_Ļ`|K]g2=EDp_^ZBL*އq>wWVJ X'^߃ھxǻ`yhcPP"\`xa݋6:s(yn?zxC?mhfwlFFW"o*)hˎT|M۳)YKIq Évw `0#q=[jO U"K8Ogx&0u QSEʱx{KRJ_PԞ ݭ /~zj= GQ#}Ąb+G#0R5w5酵G}]ꕾ[ϩk'zdOt>>|2,c,a!rRr$ϾiG:Н]$V@ߤ΅íwĽWÈS ZU'Jaob0Zf?v8?JG>Rdp4,Z|Kǿg]UlᏦrG FSHh8*|eDJTcxp AK;q/)7rp;~w+L#]x4!ɵ۫̋.[Yl<ڼ[ˮ'zoo?~\8oޝoPBVYc.T EE:O&7x䤣67̳>n5Ob}>i!s$ǰ<>{_A8J.XjTg^~~@{8ɜ!:qҜ"aPU_+xT^] #FBgp.闱KY2Y}QQk:}ihp [tqÑCcSs`J$jyqε'ЌЋpGP1Ш7U"xlUΘxY\V2Ui%sOZ\V27kug~InŪ_Pq~Dd:{eT ~ʅP9^"&xQj‰z7s&{u'g,{~gdSWs~z^8Vp8]{w., ZT$y#<.߫W(Yj('bMf/XFU]*Nl;Sv(tgw)C1 wY~#$a7[!`n?ί<&vc"ijMC/J!j5 ,G7Cq<; 7jgG,5)yP}ǗE=w)G ݱ]#%w8y6ppA~6LW>`:0uNpRJ^dʾ4T*F^,΋QcfLxJY|gp6H'L5?@o=s#J0ڷSg"9 zjSiQi4KC-T!eM˫pGu\B{ A:>y`]<]hj[pK<աݰק#^{jAuB@w:]01yq@2G*0W0ZX] 惡3'?vW?{ |Mz0@:ap1 p + .) v$)_txҳɲfK]^S{ӿ!;dlI{үi7a~6 k0) \UkϘ"nF뛣LF `ѮΒFTUL]/C.q{qq)h3CZ jvgS|韃<`\J5|0y xK3Vl0\|L+Ϟ4?w@nc T PuQȊ>V4+G,`@@{i7UX%/:JdM$ѓi睸g~[?g=od4oe҃lcuk> Ր5$ކoHV_gpZLQ%ޡBZ($xMJ6[1Пh4Ô4ҟ ו? Iw0.~@d"rxZܯdeY<#Ap:i|hDVrF\K3ȋ.^1CjtUa"IY)R<լP>&Y]tĸ2%E$«x imuoB7+rn£{3U:Y(XJȄʄ: z>2eԄ^qCh wpVxpJ]IਪnnP?qDӐ?C`Xc)aXڷ d4ykd@QP\}wn=]sVXih͒ F -UOD;ʅ)4stA[2KsMy.stѦKxxي#slJY @^[3!CaNf_vGt^yJUXQ? GqUYkzS]:vU}l1LYWdm,M\aR3Ƹ8igB: ,^_?6tϬg1 c PL鹭%#W$ie6q4?#d]C/kUc: 7PN@Um˕ {`),G[#x,mqg.H:82Ar < h2VģC\+BW!  #a;>JWXg4I0oY| Zt,Co阤1?εH&ڊcwm 5fwK4/iDjE-v||uUgH.B)vwd)*Fizx &dONwAReܕ["yKЛ%!fXO`]]a/#E[q<-RyVjmj.pj=᫾,mȴ jZiJ7ǔ6{2y,+_[~q] 'PNMNl#X G,/;t|Ŋj^W˸ H9% Δt!L4ubV8a]ΒE}gy{k5`K.C KNImBE`upz'ՆZp c^N4 YGOg,3AS$kFJk?Hg]b6+-RWWuA+iD;]F_<-Ge35%7N+2c)b!#3滦7ӨB⽳0(}f@L& x`My:p"N!&dK?M[@ ǚ:~Y>e$mi³ҘEu+ʛ{x' *aՆXl` e ov-?s˟ 2fo;ܔUukaPnS)OHrX[ #tb[%{TuJt0,tR[]ZXS,:R}HrU,xqg=q7M“qgkYYTWXT @zƎa^çf/,pE]Ds7 @4*?`DpNCyFaeaU$)#J(Yt.XPJ.UCjz\ZTU rU<"bbəW ֌6-Ɔ#qTRwUZ֠GfYwa`NV(M'47#$L eig@Zh h(.ԴwQ7z'u*k{ٜ?Qqߠ ,G1ͻ_,:FX^:~N> 3y}+rp$wR!Z~}Q؛; ,YG[ow_ougFi$iĹwџ\V*BΕ論0Zl *$'z%3YÄgZ{?c-n%Ngf}0?h}=Zojڸ/HOpRY `\^5PD>-#uJEO"J 0%KY3ļFoz~Ʃp's ; u ZTf|$7!6*N5n f#ɹqAӰ[ ><pEz6mMh Su 1Bi5 cMЋQwG=1 D]TyԯФ !cq5lV@1?Tp*? bmXmҪ Hn >ϴ`GNL1ȯ4/eMAh'|AM.`ˆrM52X.= ~ '[^HRT?p7|/0Xh(7qR:R < Թ7FmLLD"FF$=ܴX5*E&*qRW*Ɲ%O%] ^W J@) AcCPbLfu8q>. H<>KIoi1g  SPNXlqZΉ*b%U@Nt]=Y0"oсyI-xJ VE) SLJNK>bCܰcJ.}C΃1 4ŘZ,ot2hgw|^^r@S3[s#( I]}aƪ!3,?Up4bt>ۋXrClBc("%q0"r?&iỤxhth+&Ȉ5OGZCmyy GLXs`d;ewD+Xқ[)YL1:^ ^ׄ$9}J6(Tx+WG`Ћϋ ۷3cIdNi瀒(Vr 1!fK ZIm[pA!MI&aåeAB%Of ݉10p:^o $!M\ҖѠrviBQDH G; oiQ/A4>NI$m{әNğ'U`?n2K3/yRXE?XpT.ܻw˔7^|>,bNlԔVNm [OjsD崢v(Ls)C4IP3\Vv }aګtC{)ޛ(k)\=~}cw M?qK5 iS%ڛ+L ;}|G 6I-jTmN,. {¢7_|~=Az?Qg}>4cpk?j_7{4yw.=_ҍt{}~jwķ*/4b:BqZ6%U썇-B>9>2\?7EXspھr`BC.`e:T4H|Mc:NڦUBksa050 ^^67o aêa88;q쌮kj3bBAYVyaH)t|[^U+GJ6@E9sbƳi{ mPgm C$HiB:;^Dfe>1j1\ƥ-?淈y;6F/9Jⴧ?7gsKߗ4g^Bk}wQkVҷОC_$- &^zLpjouZļ.u5r%-u4VkIVJKqήSa/ =t7RZWxwZ@Uk/-()Ks#`|`S !_2[↿lVص©*+82hc먄[ż;^Q>L1Cf5ߩ 6%J%)[B)TR/iGK2 W]VIU՘s|bZ 8fW,uM:_#9T}b+@|^}xPܞ:\Lcqy]c*=@#N\ZD\hWPcKb%TSMn{EuLq*$(\wU;_.hŻe͵k0GokćS?AIlxm̞{ ,|,4a];EcG6'1*a@z{}&rgVCa=Upwd +_cg^Gntwh Om9]BxNӫ}A[VKVVq%ҥu:/r k7avPO@#9HCzHW^rRJ'v%H/^b'Z!hU5IK#*kWbW)f!|%Os3gj:u1KFK8p~ ,b뫵{’ӂؾ[o<3qD֭Fpׁ`^~~UU _K?*CgTη.WErU#7$jaԅbwx?~W2%-9:^cR pxxT:Lyf`Etqz;2OԾکwU{vX sFs=fxʸ^Mz< Ӌ)5Ѹ.9Td-|}n-r. Ǟ}6*[~sb$ǹ:zJR*t||lؐ #Ak? Υ7c,B][x0FtIR*?+ iVpPqOq#RrK"[:^o6r z'pQB!MX\UFnwWpT=уHÔnflD]S?X!eLN)gO5!u?@Rn?(^A[q|RPv{^EK#臞:^BAҔ.{Gq]F^MCw1hن- V3]Ιf8N>u?Ѥ4˟L*$Y 4#^?_ gV&~&t9YuS=qῗnmo=+cMb~uv<;ɥڛ[ ( 8Rg-A }Rwv(~O~(ToM8!N܀Ty};Խ֫39.-jAĒlcΝ6ǙtMB1HeN~$ 'yL=6r[ԠjlCd;hN3>g{^C^x),]in Y(ܭ[`x6Ufuy}ԽAuOx~(X̍GwTN.qvvwFaLMa'700\_#NM[mm` k&"ሯ M O9I0(Ҧ S9rO?^乧GV?8B[/G)TǏ 8|f6Ê66I!p$.`5\Z\Ty/|o<`5&QCm>OG'0WgB0;3t~K0ԃ[[VPa RC1u 6M4]f ΋t{<_}IBp^IG.-įo$@7KfpI? (4'w5@뀒}&o>,yxƇk=e,,_0~Nͬ+ʹ/fbcUEɰ< nRRZy*ǯ @!?<\.obbcĹH"*-Y4S\ı*!h>VT`"]f1cɛQώ"F1|%;Ƌ 7I(}y֧ȫ "{GzsX" {>n`5'3E{C?vqgs+5~SiDV#MVc`:7鲎i=n8%EM~͒Guz4<6SwΗl6T84fp8\A:wBďB,^8?"vٷLZ0l+l(!#N~ޫw{o_ܚnu-NrА4q NBñV!KB]dO[lW4(,u]qT$!jBQud/5z[t~Wp؅wDΚ10L@(.}ފ妧qY%]bR PgҬ9nnIhWsWզ,|ӯОc΁k }[:g:$vuH=:0r~$Qrrđ %`5MlSM- 4L;2Kd`[<&-ƓRx΂ʁ9.r!/sC NJ].GlmL=XU&I4rFc){,Hu_Hhb؞ M\Q 9pLhQ]GҘ[a??45mi ̭~hʯ"Rwɴ- $ZVr$Ѿ<̘9! hj(aB8sD82 HܗaSf<X7AֶzaMwS.QQ7pz Fl!y6BA^5U{~=EC0e`-f3Uh&B q0}YoˑNmNfi,>,5CȃBpLbA! Xx[qj'aV kJ6F)LԊ Iaބi.AqHQj˖]k+Sx{c40 . w |&- fg /#=ɜE&g,@Gjaɻc`ئ(50" .9 g +,%hj[ /Ҵ B9!ԹIm9CsYDۮ}%뚍AK6&晍<Ìɹ>CWRǂF:dڧŦtaYOq"N<kSŲ|>z04/NÍSqOΏtҵu^Z((T@&h)t0b *a&ZEu`N0N y1,:eQ ąW6DMG Pߤ,4~. =o]⟿y9=w61#xZ[<RRprZ26`룰 HR r3 NbOp"NF y To6\d߰ n n4BK:}2^3Ms|G[Vw?(2qSEEk J>M0AonBS"D 2SrOX Y_,@hՆ6q8)|t|O uT !v$7XF `l<`jS8XD S( Iq(Ħ"Xj2+CfeaRm(Fh+^N\!k}Iͳq10*+FP:`>T*Tj':p_!H2]ZWh@~9fE@}t=kaeD/|πb(p!=170P _rG]I<u/ h&H1QB.ꜹݮogt}w~}f&XbWE;[|>n}8o:Y~ngG_O?~e e!IV/GJcx4sʝxW؁JE>_ܣ=1Q$} mtl(}2<4@a/.a8Tf̽N~m]슘[z$t1{(IkuOg3ltJa#U֠u׏{r2'HÒd! h4̥tlP|yc7=S4UQ}`E_U52@IaEaDaY1 aY@vjĂ1fu .^j%*v:9=d@7+K+'\F,ʳot3LbH`>bikA ?ltO:rۥ>}Qs׼Tֵ$a MDڴgS%2 Y$]!ҳ6,Ѐ/Dw2x5Fۑ_DG+ b͆EID.ivI <4)8˱Rh8Uwc:.Lx4"sO^ڂS?pQY 9& n0LϧC1QOHV{9F.3 @FMт.wEzf('쓩%ӌrC_>m\qBeYc CV)3aY``=ۧw'^7NЏ?606>2#뇰Xcq?Mطl(^bfR](8q[x ^uX)7a Z5'e9FUxI,3 Dui*7mgg.eeB6giB=지iOk3n08Z{aWE;Ƒrl=QYW=X:#:4( UFm+Z6_Tw}g, dEkHVڴT S4 2E~LHyde?`YjR[v߆Q"m-ٶ1Ѭ*@ yJT4ϠZcy]FPeՐ zl5Y_l7fx6|0g1%GN9c5-gcљ +c.0\#4Г kԏ dD^eBIX8P2^Z-'y1{)ry!H "oI ڛ#NfXqe )?F#M$DPrnoJʢY.<@chq2eKA53_2X*)vj$.'D8K lnMp`WW,zl½0_i#3N$KT7|$y! ^`ceEuKE6(NFs{"n+sVAp1j1qf6JUbE}n&֙paSƄu̕>8h`6Y,".,^5%IeQx05Y+ [$„Jy[H~.ZhJ*UA%?"#5u#A)`tM)E4njZpҎvI/}8`؉ Ydž3*7Z kB>_-Ou5=zIoݣN|w0(ZÉ(I[%ok8m>Z#VE0d *7UmY'kTOM4FŪqssf^,L1QM)ezSt90 P[kH-*aq73 r )Fs`dDccNJ]d`,-nRf1t_Qkb%J 0\[e![2&ƕFkls*7 |jty!WčI3~LC+yu]D.8-؏)v(t*M훬mHt8q왪U٢CDM؋j6RwpnbRRŤś*H W"X0MVtO컁'y֖X]k kr0¶7.JirB}4I#|Cю $nlX؆vIKmHH)x흱N`!$7y0biXgnO0p8fomF<~BDץx:)6 Ǽ*7L*N1Hz["ZF?wA떞Dh֋1b3`#v`r]́9%v>q{% /qĬ,$|)d Tu< #4+"4+mSܲEIT$[;WVbvk-lYSx]l-#Z"+TZ&3#&:9PV? @˝_>{xen1߾˯  i0e'0!B,*LW96dY  (JBkS,$+-΋m@*ZϿ"Q%su<Y߭ݞnD{ɕn&_z %!<[’:v(v|u_h)9V),VӃEj.+\ J| VTfMҾb4Hq=#,fD\L)c,Nn]|+G9҆3+6-SKw;v^?葓%ӟcc:,?B9:$vlFŰдt:5 hֻhwBe$#t.1!kL8hRK4֨MS?ʹcz) EV%E9e:\gN'5tWEx]hM8dNǏ]CQ]ğW:AMvy)|HһXPK7y߭| hx;t=C}]1n)E5?<@KY|c80os)BV;# HtC'^sj SIŪoBZW`g;j7l Զ CPhLW{o>O!Кt[[ V}.?Cυv Z_7 {3--Mv}v2r*i;vq*@L ٟ*eOW2uayT┙4u5*10~|^ STK DoNLY=.{WT%ufa^%v(w0xCYW#ΥddWnꦚBn=t0dŖAv\l$$Wg>F6ӌK w:=2;dE}V>XKy7Q6wywq9@'doyc ”KĀwMYo{Sxm.:GB╰O|+"t($e m{]e ]XWf0?c_Ƴ1h?MԣD@29wI(o,^^54j0`؅ζP E "Á)Ztwe}@z~^Q{L+T-e lxROmjZF 3%Q3rҐtN8|t#cdYd]dI˵|'tNlD~@A19!l{]Ob_1*=#FnSBE#RRZ3Ħ$A`4IƹηZgAwN25c6>œnP ;nk*El<Υu4[q!UEgf#Qc/p~>չL@G$ВDZy[/(8h$ J}yb 5P}n oeɭjIS{]Ņ)Ӌ]@ѽР/JwݞE|3/s/C6HҚ #/YBZ/:'dM"<%b`¹\,=XtXyl/!3̀%g&B=&Oϻk k0ہ?NavvV C z`cg@(0'sEGQ@so{kkTd,s}a%\ FiWBi3)KK_Jm>xf [T%\#S཯u0>pM!0rDX Žd>cUz-%0QK%HPu,"krN5+ϣr-#y{rƜtDcnv7Z.P'5Cך/7%א𷫦\7lǜINjh"Nx*ˌ!b2;v-/HG #_.[ho;6>v__p DnWp!QZC<Sr/S.t (w &RyXa?~FR2~!^!ׁh+u(k4[pT5 e9jd3J וAΔop2αɅWmRMʟ㢱ӣJp:ok;S\x?7*BIXC6W ޏc1jJ-tL6U"cB文(Սra+M:7KKD-xSfb{X~MوPdkV(ݖXEI1z6R@QE:$EŤN3N(/lr2/m%|"W匃nQ>52U={2C}okiŪN*.~("D\N7M5^=72 {df\ Jy4%g_! ,n3W;r4 fB/TX_&2lWda*|,3y !.81vhy}OGͰ. k٩_Yh‰etNC(`|z2W2 7]JLrOBvYD#8njYsG8^8+Glr&:yi'{H44q%/t66 ߛmH J-ۀɫG'}ȥ D?6Q:l,V[ڜ?]:_j dz懳x,A]#.4%)KqFCWjerT[&TX|@C9޺[@,?E] #]X\9u*J79ѩe` Ge+qJ$u ?`SXw,,aZæUPsXD YBGLKIPYk帜1]:d2̤ -3.B3 a,EBY)c=%P¼L#_P V^f0yiH*MXTGb:} -,|8Cxp1ȧ]O/ab %o·M`W1E:]ܣH\MsI?誠z(RsL+A3jv%ٕFI N8_&)"$kU"Rbb/+cG9@|r8/2mP(Pe2_fJ⇽{^,X]d[vu+>ys~yQ=sEr): g (ۏ7[ cJ=2XcOяdf)Ȍ)f&UCO{ǹ rf׃keH#ۊgc:"B$ċ_sLNbȕ.58OB:4D(˨2\ImHn*4z=Է$p m80{=4-bkL>G:=Y071B6!~.ct鴝 GG[lUs^$А*%zO| cɦ>yn͇o~6OCHMl6h7Sذ\e#7 QJq|{v*)fS2aJՓ;45#8VҚDgqUς <,c$(avYNJKf_;lsH)JîgJge,W+reJsU3/N\9Tx\=LMi[RS3C$=FV)Y8bZyvZ̯doXwq_j"6I `$͡h"|ʃ@d&H; GNYE1 p9^#2;찀ih5L/{g?0v3`cJq WI 7d;.kJٞ4jPh;qPl' ]l)/٪Vb"#*%s>vW,A\ĞG1 :` yNYmՏ FxEίB((ghkhY<.+8nO<C.dX77|VrÁƜXX\ =ɳ}cxpFP.LkgS3 al Ɣ8jnpS@##倀"@FQxhb"*@oLm@ wA0%j0L e?D]4TZ5_e^u'@Sє%o2M.p/\ 2[:ARTx %{#lJL44SF $L~5\[fє}pl:qI+c$([,nw7™^[@uS}F{=*ۡ=:7"gty4`?"9b͛Y,Ao}Ÿdͦ99'L~~(o-z ,Ta?vCeiËIQh7g7,8`FޘнpCpvYn?)J; J3F͌s1 aۺRKYF\.domo?|վ[9?S3eIty:ha"Y\ì{%6YʖC~N,Zv@aS`<8w-mWJ%0E3wI#b di~zKcWkjԫkHRSc?àv0_(+Uf^fB:Fclc?MbhDneNتۓ^g0x=?7 /Kh@7 pRtYjRY;RjEJ)`ҝT2 `y.ϡ3%q4C⑧&J4o˽t䦩|?N<]KkaM M݄rRף,!7U_\a?f>gy'gU/Pn6g($pQ`HƤo[|gH4GhnYz*I*KGGH5͘Nx?`asҵՐ"xkY؁Z!8Ωz-8!bdbd;65ވI2s:0=j-Mm`,-jkԞGMܕ-U|C`gbc#Ni%Ƌ2k#JJC*_YMBNs. )UYU07^Nb61|v9 3ÝI3N*UNgD)ƍء+S:/4M )zl`jOC, Wж=K{PKݓ#Zw2tlʄ)?T+$ģ&X){\'( r2 RuAut-S1&^v@H<9FFqR%͝}d!FU] h5' .ؕ;4ps ǔ ʉN ӀШ/rZ ^J>4'oACc#Ml?*O)dQֻ}@P&Џ@mJР ezGg籼W&r7#hmC'@9KNĤP2OE[;* UlsI΃ to$!'C=wa$ d%ϔatm@ &\fA5|Jʸ>b: f!)܄8E ^5P߃:B1+BzlΉ,1)眲ZˆǍRw{F7USjWu$l$y`e]U]/v/=rshVV' ˝c: =\-$ ^@b"qN|+?h!&RI`(֚67_KY.~Ѧ6/Acu}/HI:yF./Vy!`7ЧQּMO]`ٚi k-!80|cxHi9F߯gՊOyi|04;ǃ5esޝssz4KTwXSsFTN6dY'1ޤ]h1z~}уGwߞ78t@EM"\H_-CEG6T ~3 l8P8IltuՕԽ*# ´qQ E~n<\A7PUlJ&SϜƀf\j!O/{zfyO=614@c|W@]]L6))A f>Eq#000g\[;GiTXn DlAal`@QGlڸއ#jV~FsOrX$\¢},8\#-x Ku z4ʑߢk0G+Wɷ(7 h{Xi'uBepH*N]gi Ml=6jD<#Lv62Nփ( |3fE88?!Xr0Nya뎛Inpº>ğČ07KQ{)KȤJ(Z4YT> XdP]lBpiwz=* ڀ@;_q)$͊9_> BRi:L?#V zq·]_ɻ >2p" E}à pho7ܡ.YTgG?Ta5u1N vHtim'3:c>7H P< ̔\ 5NoKiǾbeٚ`[c>3Ν-](]Mi]4M yOygӺ@<{NлMulaI+ Ae9=j>%HQ`61lXaDtT,~rf TFMDZ`g][~n|pРםQޛɧSi8\qqZdI.dG.NdFff hٲ\,t+? CCϵs-N^#=1_ᱜed7(T[@G|z]8zd>qOG#,K >8q ZC D43z;Ȁg7ɕq3 i:rd.Ov,k( 7.`^EH h`+iDU`&4tzlwhB;4Vj">ZXy6ͪ耙(~;՚;j:> {-S&0X_m_p|  <Gq=F[&Sf'n~1y46etaDFCiO{%fx,I0oFSRxwoMer 5i?mHҙ-Hh}/!>)բHm10_7:`Vv#i$bֆ82@b[0_^9gFbQMZp{ЗkE@FNƔī 'P-p8!rGh{c7YI4Cr=4nt4PCJg-0urޑ*˙Ew;c3NJb`rŒXVpq)CdB;ouI+ffsfQEa{}gu`%_ĵm'Ov^XZ_]2KO*csoV!07tiu}o;0q1 aj׎ғ|pia bl"{owasNV+-%+id}>#kyR3"ػj ܞerlQ[ܮ nqtd"?N4<ӝl$kjsp:ڵ֒a|p'Yg 0 Y^ȉb<YzޠL@_B&Hf'Vd:0fqxjRe PKX=p%9.6#]?e0muqOdχ (15]besp _L綨U;2j9sDNf%\Ƿ7pXgl֎S٩V^mV1l8s!Ddt V2 wL0( 4&hi|}A~=y@/ 5 FB}0SAtTzy5X1 JźJTPZJk ɦ9"޺QHWߣ.ceS߉ 7;6C\3=愗ɩ ,p:G֒ q#P.O0CEMz*J<AO1+ZI;BSlE"aGeo+s@.>V E;00G^DkfChڧLlU[5a/! G0ɏb1.s84fP=csVoO!έ#N6&CڝiLjzAhlS!Of9&dѷXSM &ԣFDr6cxrUoquثV;$HgEۤ?$!{"/7 ]k[/ %e# h/09.RIJ$sE8IɔUS8ٵjGE,h"Uàn'T6w9c:vo>Gn|Ӭ#F>V">ۜ/[Mn  Y['a9h+y˖ 5,RU _J5I1lB/Va'(%& r0&Zؔu.c.kʿЁ ݸ 2F+wW qDljN$=|EZE" "Rzx^\5ǎ.l8[ƥ){3Cwt=Pw-cVݏlyBDA]wtF&'_o&6m:2*xPh '3D=4;ey9"?9?11@sbDI!yUeQx- Re?gݦ)i6C;T6ޕCs( ;S*SR~mk>Hunx1i;)\*tmoi˿>^W)@9l3AqL8߂e܄7X 4}}"oLv*,f~M43IH[߮._u99lR=4mFoUT ]^!hN9+oN$M"} kE(mƯL l\l8qqqlgU{M7yzcܷ~2<mSaY\#WS zy]aQ ߟLrܢ@ۆaw4'%7 E#n *m- A,~ٴTV|Y7\iCԟtBW`RE.W+J Z!d *zPע<?FC8HFcdx]l֙9OȽJ1 99 8DFxV CནS |༐^r'$$ ,'bHh3 + آ' 5B!q*t!Q}*AZe==#f=F.r]kЂA 8'@nsl[S3fH?HߥaEգQch" LtUop[FV]x3rMyVG?D̽dMF{@儐K0fDq& #/0Oz6Xͳ;CoV@,lN"#p+t*Uax|1=XRlx6YCG61 IB 00MrrAz+,h⢐&݅08S)Ri p$)\Pmst^w|(67'';C,|-?p˪A jIrUF- XDOLV6+++G&Gw/ p_.8C:aW.r 83s5XnԿM2Κ4 Ȭt[r0ϔugF#KH υkbgib2xAOK\h0Џ7S5$RϷa7e1ܲvᏨ,/,vq- nϺ ǪmcZąޤm"5C6h*(9V>!*W}Iڄfa!0 ^l5Gu8S]LN˭fAwVA8+tp2؝U\i Ficz& ݡȓu>AZOGMajk=z\E|C>ƿ04uBDJut]Bħb&6g%BCu\8Y`KS]LSFo]qƠhg.0_!߈"E-GPϫ &Tr>mE, $K) 9 co\D+ھWǬK D!U bv vDу<}]OHaIQR*.F;JY؆${8VBǎ]檃:,ŴG!o~OuS`)FpwGQ o:ߐ xel8x/<4!fg}y4k 686Z6JWR-~|ǝhd@8ő(xJ$vtZ 2 Ab65B 0C͜Q|'D$(D7lYP)dQk.g"&@H ǨO@QﺲCFP`+{\?5y3T?>x| `)<{,Tew4áh\>jz&~e˵pzMk~?}{u3?ȺYZ]=SǛs_}* M99b: s0ܼtX~k)#&jhMQx( W*]AY@ :r.j\k+9)(9&Û?z M-p~U} :#T 9Q ;mzY!m?7uYbe׎aFآkJ6;@)y<rMeTJh5c؞a2Xl:Ar?U^?E*hz_ւW~9z65Z~ĠBM~R"҆@,z:ۑ,6zr v}o8}XI9=`w٘z[;zqj2OiZjS,CD<,H.{I]ەw|h)) Aw\|ĺz&&3߼Lv&At'g,8K&2#*}"g-|~`PPÓ',u,W M/Aypuϑay]%-<.TG4A{=mYсuM&|? 4=I@1syY wf﬊VV2q@fVTr'☃RU1seb)g4+Q$(ӑZϹdݼ.f3 ms9,d"FrD",j8ul+$+ HN ͕@ak| *_DҹN@Mv`y++F Q@pJuB`И)D8" ԸCX55c=Cpb^xJ`AN,#EdRs:/" ,q%~i>9~MvzPNB3C帞[ 0'Ư 1L=c'6+Z 3$ ^^:g1eq"+8W>{R!?2'vFBCP8x"~"T)G*jYc[.2 ,8h-nA0}GM1v1{Y:<=x=ddZA W5W]y:a8DΣB7eמgCvNΆ@uVuU@ѱ{c .ThMcu(ms[ȋNIwS٫Ja&}{>TsUa$6'-fHs8闳Fi(Q8&tx ` *pFZ7A~\!F@|$NZFBȧTBaЏP:c{ip[? /ףJǏnn?3ȸ27ZI`.6']\ KNG~.;a;ip1tx{P5@ >fgFuh,)x72pnuW8%lJ=R%۶mە-Mī Joq!^* 11%t$ ?ώ|S=LEMmBk‰HڎK#`\m""8"X=c ?'ޯo)GEVɞ%|1 ťDIP}!wH}>\)XpX iS?V/?f{|p[+,G6b^Yjd᮸$w,jF״˅@S@fY774 dO"Kg{D yp9 nvekSy8qUo@Os׹N Mlo-YgQm/"GShC{A3R֍\ÓlbuL8`#@7>3w g~#?Yv jڵ)&#D ߎz5 FچIWOjt9z[I_º%miBQa`#2ZoȈ@\=/>'P,fP^Vث]5Fd%͝h5CpaqE;6ėQIܞ^3{cu_I >1+~[}܄e؋TtPe0lķIEfeNcp{lMzGͮؓ ˚<΀z FN.OV:qO&(ȿyAqvr-RҔ#buc" ]_%Bb=2WmW 4!2t5۷#@7ݖr|L?F[Yn96wzc+3l/,_I $skLbϓCob8Do Ћ7w^Bnn9Xb '#l^@ݟq{ҀF ٨|=:U z;b' "PJ`Z-%>&ªhJiG# ,"ښ8 VeҤZ[}: A4톭w;t43a+f~f̋^|(JWwbd;lXC\1ӷ/6 ,4YE݆;-NP>99d*yNuݟOh  hy: ,=邀!ؗ<,]` {IPM2(S4T\mI D{X$$r\eip硻Vx^r^ȮQR>pw [S#MH%MUyL'JeDc9Q!.c#'Ѡ|-N[ңI{d.Q_xcYᚅɡ#fZoqMpuQzfx^:)M}9yl˙?g!,s<(u抠.{ z]bU+I $bC8?w5kokC:N ׊)7 KxIX4Zd80\_oEf2! lwd~<ɓ/vhp q"'Lfox(-^wrOx~7,j*[x叫8iF3 J3pCZqn ]ttɧ.-jǽF/'/gt&,N%8md١OPSRTT<¡VV=`dK028&aҀIdk|zIPXnQdhh"Ü$ȇ!"*)m{dD:H3W#oVW;-IF8,ƀn B&"OKsRm@'vNzVyl%P:r95 A= ?BT~6*51.2)- ȝ0AEvccCjPon4Eטi'q u$0Cʆ%ved<Rj >P0>pF\#Wy.uU +gm2);|fIBƪ/ ( }DI&+t^౥Ϣ;h  Y8hrx ϸy0d"8 pHXu8ڿ`D;BiZA xqf_kfBrV: *M~Hطͬugdi${&㣵ˇZ{o=W-\CŬQڔ֔՘7QH5K ɮ5ct ^ Bť Bp(=޴S)[mb*tbߠ:7r\Id5%V_}Xol`E_9&_z^Z_ovV[wϜݍ|ѿGkf |:{un!z{λwsgIK?뜺/)m,驱ʤ|t: =';sf2ek"㶧;P07J9,:oal*Ihݪjs~bm~bp yiqMNӊ}xmފpݦ޶a?tfvJВs,޲BhV`65a)B@;uDe;Bև1Vqݶ︇iS|'/ej1M0iA(stUFJZ/Tϛt#;w' 6f~f5'"8oD {v.{_8Ҥ֋[B)@0aYVNqt5p<&l/xgnv? {.܇:nsC6nnbŦtYh dsrپϡD4Wv `$Sh@ X2w0ֺt#!͕dxjx=?{Rˈ MTRk=ʌxE]V5]u^6jڴYG0۝z;Pxp?wƏ(%+ xQQGMʄK8=5іضOǂ}x-6eQYqz+QV@껲ډr~7L7ǦU|o/@́c p1Ɋ{Ⱦ{KH #l\.|Hi;5z`\- r_^?{ 3 ,K!c7 fn!eҔq>xcMNgŦ"=vtZr qu{E3#j⢠Ĩ(:Q|7?}WeG$:UiwjVL/1Y;`'R|S `-d vmub}%wr<ڡu1.i0E %) Vѝ0S@rpX)AvSa9|OћhZhgf# "p?АX'Ȃbcc!^Y+f"(O7o~GL5r |~ zc5k76)kҡs0l+0'$kQsV%O7˯dq$t0(^+%ՓsZf~EM 힘Yu(Ζt%pŲZ`+Al&tMQ씟x}Boz,'\jN>$(̶X%Pڔk09#ew\|Eޕn`w'R^6d%x݋w'2+OgCş{'Ӗ*eO6aW\BUNŽ5%!>LV4hNak?Ϻ/lWb1O3`֒m6n>LErDh`LѧNsfjdJ2 *~Yq`K5v1u20/g怍"G=s7,A ?E'#ӊ:S(w3Wɣ y|ĮETv|%XA K"9T(Tpz tsĎjk@Yߋ:'>GZ!J\u}Avɪ[}䁷qt08TV%@o,j s&vE\נ:8x eDM<jtwo=wɪڔBz]Cȡ>X J3LO1)vNδVoWgV)5Sw0¦Xl,I@XCTP^iqΜ9g@d',ggI(80pqV ŀ_e"v+ m.vbQ?eS{e׏<.G{IRz̛O\SNik`vζA.? 40gW !$aH@qfo{otMg璮kV.u EwmqEkLԘ$+JW*f ,ɋrf調Dz]6R"_i[ OrDY19[1f ;uϧ4=_i,UaQn$l!lsi.M<eԲcJ޽-W)*̩fMT6qjx'GZZ6nWh5 i Ȉ`//`< ŹuKUf/tr ̇$+ j'- F!ǒfƃ媸EIJA4v:k-JhG AYf4%STDRhl%guPqQY5bF!0o8z!p4nf p?U6B܈N* A٠ݭ6D6l2m+ )nNEl¦!Aq:N?rGlKTx?pAPc(> uks_L9N %c@1/(2S4,N͉g@?QRAHABڧ71W6ES%ɕNx̄ Rrna6ʮBO/"&T@M|qo{};.aj'*r}v PV;nBЌ̂f/~?$WfhZy1C{E'gX+SƮ&R\ɨ Ԣx9/H sGd?%yY9f`U”U{/k_YnE/xkR_YɐT9336Wqw.C8r(ZH'| 1 Uj,ȱފ};T#>INW;ݷ;; *l)p.yr#α7؊ j*py#my/7qH:{麡g2ݾ/Ά=9)b*$VjF[49kC fr\h0q6Og~JHJ;C,pA7$w~B=ߔ_36VBoK0`bqJ<ö@* &r? G^W;SMr>weAr}"у' Uର(ٻ;,kE[*Hd j[IP/KIS ²0x"氵E|tbӟ,P+fL8 KPS7 U%$;<ȥL?UJ9f0OkЖkXЫɩo./ GsZY^Up:6ύm)ʼ#i`TPaNr?ڦr4c-?6Ds:Mrܮ5KFm̄;hοӦ`ݧFѨm((K?jKPԥsMeJ4S֯h+*[??A_s6?s3?J7b}Ƶ #:*Ҿů}/ U9pri֗{tjDtH䁇Aݺor@Ncm%c9BF:]?ϵ$/`6G5q\~#H xX=YX'[(|JO< H'f;He7O:X+4A ϓi#T!RaFo`<ƻj.wUݧZ.=g:=2,DAk! ʌ 3W@n1,\xWoZ %e줏U\R;"Gyر-ze9ZLn)Ӝ&&Rw1Nuzt覈i6U O\oܨ&i mKwR yrùҟvYelQu0O#LɅtH _ LߞPN5">:=LeIZ;h3,~YNÛX\V N"XCsf$K4/ uө2vۈ9jLL`H*#=0aT2-'":.0}xoTVuZ=HT9e4GoU"<-U ~[ `HVN|ëJ1T~z+v _Py>mc ^F*r@CH0TehCU6TLa*ʐQ6(f lP$\f0@6PO &4cIJ&>b8m.L>$,?8J3ᙛ*:IN{o6W/L那h4{`V۞:,7[l1 g22^M2W҄2Mq(*!|n緤atD64}g6oooG纲dcW??z!e\zwK#}feNED^@q턥[-`o-f}đ Hkx" q$QqP>9ѹb4㻆(f̾u.85$RL͠ rdvS.DY攡| ikNCerVxS>*PTCڏ RCpUJN1~ ')#)B &rNr2fr@r>ܬH3z:Au6U7t᢬#mAb` 2An<9PMjy;)Ms bȢ, NN-$츇S50UO)8ïU>`aAu~2E70.0. 旽T!|s1bEZ,7F&e11A-"HJhx=ȃ4|NH&u~l~ݭG :(~smz6% c瘌c4jHB6`ҪQz[f|lSKrCFQ~tHg3r 7V:ْ$j2C } 03]]!~=d,Q,|:h J}m xTF{>0P+?t\zBvWbU;YdQ| $jfl|И7Bmxv߱-nK/tχpRb:7\3Aۋ>4Gt֜/2'?צ`Hz_/_w_/~m;%zIKoNh+ o,Ԏ3-I:63I] 3nDtb- |܀ۃ` @u^ؿׂO7{w[jˣFeCI.47g ђ엟w~2lrl$)vM+fJxYٷ!ڕlzbZ%}s`IWPRn ?rXs92"ؿ29q?x.nl3aIN%taOe_'{o=bwSLpX?C)\gn}iCQp~pNr< ,~UdG6e>m10ȏR>tyJ JWCg))@q~rVMWS~8g򚫣 m\ҁ-H(z'ͩT ձ\^ }:L8=O16*1޲#N!8Gv\)oh]jiA S?=$5 kk]+.C7DEHɳ !ugk:Pj]{QNb)>#`̡O}ƛ C1eq!aWβ3bAU} `veth"v@{w=4tiz\ƛJnJZY vVo:PiPhW?k&d5,kSx_3''f0a_<2^7 .$ ^Ёpv^LVF*Gcדc.t, 7B|6}0#6}f016L&X Y156ȥ&\9tWeyMDu ɪz=W\56o'4g54G_ރnUmGSDR"DQ7~L.6l]q܋Ѷ˯U< buLk9Fv67\Jk:ZDr3 q/מoXFq~aq6tԉQn5 Y2 =\Ȥ:N^F`aq8dԠ2&ePѾ^P+-/!gFCGa%X%_6,E׆q p6_`FirK5BF[z(| J|p`(F/5+N 7j_P^ñ% gjj-3CUƥA;[ 7Q:,sPHLoNao {VmuZ}3F._A_g*PY]6&} p #'ҋd߲ءwPeC O G K1;mOS꡶ڳVg"iL $ .&eU @xYSOY`X%ƬoDL'vVreF/O4k{#(c3ne$QV.V'cթ mkC#,5_;$6&pץMt[0mkep𖆭!AA5 K>fښQ)Epsҋ $C#l%IprnW!7z;o6:vԪYCF>ey~+sX|Jǿb꣺)hz6}pPafD[(An:(8B@lLPa%mpUV(X`ET'ћDCN@2%!v+ZF_*Fݣ3C)P=!Wm =v;'λp'-b 5N]un^BȖ(ۻfLjYgm/wocs*b[Nn(ggNj GIybϊ>vM% iH۰gJ-vn\xvC.{#z;!fpgL W]ou'disBngz}oKH1I%5cvs)y-znINZFW$=?&!5;~V{hUoCݚWXD\qMb7F@v,Ak5T&ÑZWVq5 ni` "NuJsC ?gZF)iPB`ArRkӽmh~Vr'J3kOw[uߢuw/LsQZX6,z'RZGѝ\&(IDրN ܩݞleg f[E/AKsz{}9&}K];&'KKהLGKpQոe1UH?ӒdF6wLS8$mgޒ];Zs:L\&yDʂrDΚ5y ёMi ๡|ZֽLnc랤>-\I /^)FJ`StS?yV)4ZUj KS^LSϧְ!/mPf1V/=UA{wC43,LK]@TRF>X-yécbI%QV&=WhX5E/wgufwµ-M)Xdv-z9/a3lh~-MV Csiq !~DɎT7Ҳ`b֩v}YX~Ϣ}Y̋EȻx,τƄE.cHΪi6ЉJͭ:tfrkTl+ kEUF]^zNȌx1Bf>5ǘsC &a6/^y =C9ln{)7jJ81υULU'HrIǥ"{^du"ARtjMR8 2uϢpauZu.nK޺fmVջ|:#oCfz`dLYz򸋚-ͽսr靽ֺM$ +07 ⨣'\WK~dX~ȏM;9_KLM22)R rwsGֿ!aNG>qZ 앫]zy ^ǖϜ|T|֮AYZegf`S(w9?bN51l\=Hh#:tAuC=\CL% %dmmzE $ ={{EMo]蚧eM՝g7"ǛY d_={oJ. A6!F5a&>=3/1u5E:[` #tv$81AhG^eڻd9]a'&i_tEq"DCy:Zݼ`lx-N=^w\DLe2YTͽ^kº7FpSZU@-lbkžx;2a)A ے6S*-#Uy]JTLݹUU^s;Q9J5'h*W(^NJиwUy+βzC`TGCdךrc1@V*RC)Qmt^FEqukGJyOGYQF[[U "9,'1ys0sYQiRLo_V]jNF}I NaIp|`i_6±kܬ$d*Pu/.s2iMQZʳY͘5/yϻޠˋrM"3>ВNZ'l~Gdu5VWn¡!D)7ڤWFfEa.+C,I.mFF =%SCfORb.*$$,=/';4O6 ?a@&BTx-F"Eg6c7jqfï5f5H~/;^gnl\99ʋg9E)HbFP[tͿ۴KR(;MxsЯGkh~wCwuOj|ud'l&sWyeLМ*"oY[:!䣲hYfaC  `WB9N8*՗U\`HNXBfHIl'o "LtNPT0aQ^һ F(3IEnigu6S*U9vN|"L*%3?u5-4vJfoڦO,;.r%{b fy:lh ~{6w%UTR ;5\Bt3^﨎o/A؁$}Wp<*̕](To,qԂTFY["X5+q Q[_L q]y?ztV{?U-g#HdɁ&DG^*o$- ;}th-1BɁXHIzz'Ӝ(?[sa)@ARc+6nǗ?tVO&0go\Q5~, l{"kuKvHܦ#)!ĶY?DX{#JMd=1"Tr4fh/])Ͱ^@:> +=;L|Jk3(e޷n:,FRDvܦuDTc)c<DP(2i'^ w&`Wli3442MQ HjAVwu20v_Zy͵_O}6J[7+'^Nl=IO?|-Gٸb翬]LvJ;Ïұ(?GC>OA $k=IqQ-<5R<@oOuI6|$dK3:s,Q9bI8z2>~V>*EOwX教ZF2Ɉ #,!\b@OF].+KN[}w7 tCQy<MGP[WPXIw[mjMIIpcV,'ϑW3[6Goe̩p+PE*׈AYJ'm3q&u3.^^ey 裨&JCD'x P;vMБIDNy0i ԇ\K8K2"^$+]?`t]j^: Qj;9l/3`x c7TkI..:@*fP7$s;턭|L#oaro[u_ > fpp`OZGf8tC!@w~dNܢ;҆{$@V$oGmpq7]B\h[gZV\=$0źk%gX7o-NVOM-Сmb6=}aN[h899;:u&8~8H['̸ti ̿g8a0>?eoCe7K*l4{ӼaMaA oɳ!]g`u]O̱58Ya2"vu{ '^zw <x D[K5 JWO:R3}$j 죺t#!-TA~i[1gH5xy~v9?! h }q4Hc @ƻӴ7= OJsmpLnv"+VefQ^Jfy+IfpU$5_^L;v@.fu$WjR5;el/@f^S˧!j$O{|v , {jyt{_a >1avgp/@%f„ECެ=@%$I?=cYd/eE?KɹÙˊo3= َOr_'Z]]]]kl-( R()9@q x  !8ꆍQAo^!iuUPˏ3NG)S2 sB M=BuFNy%>^ qZFLa%CӌnrJR3 b[퀯bAjxΥpx6@o͓&pW8NϤ&d1Up^Az6@ gNcw;Ztlmkq<경YGW8T/)PI0qS\4(~#%Mg)UA>n6B (&kLD5> q ˲gѿԥ"ݮtm h"<GUtQ'83B|5^@{Sy{`a z[I< JpG\ɻǒ κ%0S U0GݶKAJuTnlZ+>j8/Uwo7+qndvr,8cw_/4J'Yr`Y@,fY]~:Ԗى`Rgh3y[-Ԙt dž(} Ъ.I?X=3,T8Ad Cd7ltG#<\$3m>HByp skOi2(x )TT8&VRgvMA`e`,OJ.Ą%, l[,`GP7]yg.*ay]: E6ɶZ(3QI `f2Lˈtg'vLK >['!'њEVRdxBl#k?X i5o=3$cRFzV1S)t]}uL[=ZDcI-dj2fraP|bdYFVtP_ƽ9dۂCŸoS&n(9O/Ǒ2ܲԃKzZ pR)1T|{'Z\+~:C]-af:v@on@[uxtv }Ӵ q}M:uQOz@5f&yKH~p.d#Y(_͍[;I' l0%kM˼L ,j7Ww:[ݹ/ělX"+pJB8 Up}uEsUP93;ӮM+IL>i@4-M9r`N6hۢt&! /[TQ1> xvT_ tB&("\(^;qұ;0q݀` tg P~"vd)M2. U0 qRn2D6ry>I*A~.2Q:55sj}[˥d:;0:/[o'0X~Š6P(Kr u.b M _Lp?jͺp;sхdPD]#mERh@oUVV\!'zxV$Cxυ 0e EXm-9²/ -]Hn>:MgV.[.Bwb)-Q\2ς`7YEx낞L(oJ.MVQ px|\ 7u z:89n>)6Ϥ =ƃ@z`/jr(>5L䙽e*]T Z*6YWE?arzkQk+6)xOGQ(HeFv-*g_x,qOp1nL+9cΒ-!](W>UwP궑7uiJڳR`c i /$Ql )$ ש]i|h! 3<5ăRG~^ Yj(]lY$yRacEMNJϊ"* .%l4 @+Jw58>/=^9QO:bB){9U.OqA 'mDO'QS"QLT6m~SorzrR`T@AO;I?q?40?@xx:#p8 0 z׆xiC0#E-l!!0J&mi$߯[. #KjKm_N]g{SgP'mʵp\W0 e' {|oGNPVnl`Z[>7b $%4XGF]T>mg<B缐Gti{Li|酨E*JQh 1_a4,"!R۝F]/Sƪ^TZחW; h;+feL&ݥk\{l ʤacyKW^\h#*Kjⱃ*[٫Fa* ֯4,?cR .h4 Z 4ZSC)@LGtZqC\*kȃsfi5-zX޶|^kocHPڄ@TMԳP 3F~h[Jl'[ 8v=ʖ|GՇRSk/X`("}yh6‹c^VYQ 80`^$ҷ49s'2- wD!F OкGbM*I: S5?fbM}MB}"\)m~:hCՀf꒢Ha{/L `2 I2pZj}J^olS?ISL81wt|bu\ؤ#] U@%8$u"^h"XYq eAYCXQXnۀ3' dݪ)O(Q7>n"ES/Q8Ե?plJ4 cWl  QŀK2XFjoۋGZ";nmJOB'0}B3EvGbW@Fw\/ioԙgf9C6k7gĽWEU-[c t84"i"5xh\!?X HA1k Y48.W48w[$t;9Hy-WsӦ|bY[A+ɢ/lQɿQzAKB"|ݢ8|T.++3coR 7g;v9W?z1&ݯo1,G6^JR֪;%a }ȲRNJBjobj3k3&4Rww &jRĔ!s< 6 wbUb2|3?E~g)fH o~7/Ao[jTx06TIln.pUƸR&AXfU䅟z7ۖU,r*(/hPsxg"3Bp^J1Hl!{g5^4(Dkk[pmPUnhXׇ9)? 礆>6tŗITB#}KT' vNdldRoNesR7pDPNU*ND$I=Dus۪QB49]_N~ϪhA$j #+Nو3,{O1 n9>aH2c뼏`>DnsMn˽ɨmMM~vp,Y4EQ* P<%=\f>4¿:_,fOOL,ロB_}o*qpI9msrNB:FgqdxNgi6 |9Df}3g ,k7 m!DJh\|n`Â/}~X[_~ɱ)AMMgVDp ar8PPfZdx|1/`6XC&g6 qZsqdi[ix* ;2FtÅ¿~%JO?|Ћƽ%>Nb89as!QzF~p$K>o2/N`bw!TS<6rwZ ^~ ypdO8inǪy5)S&T؜,4C6޾Tvp&0zS2}[KF$XҚ|;lG#PēʶI&JS5[OyWѾyDө^s]mVqDٖkm =H$,҆x'ԂHTЅ"_]& -9XW86k#uh=V X  y0b8.jbۊAfpH Gdzl^LsEă"6v:l

    V ooW/97wXτ"  i_^]~9@8KG4h찧ԮynV8٩>6ݹ˨hfмn] т>&CҽƤk( /H?!\ojiW_9=ܯ 6F]k 5Ñ{RbUYZ8X2&ouQU\=wOe9:o o[cRSa::4ɘRuo6=Kg2o1OSuKKl H^(Rz #c5>c^S=#- ,/dts=ӱcJw;$t6djy_Uq GU Վ6r]5?iU]75u-3?KADyV^Wߗ|6?K\k(=Yx@l1cʿ1eAvCդCH1h-Ǒ6~/ދ76wwj(2W;rF9L#W'xj}$$j0e!c67r,,! YDk"ȊeOi.~B,:xFgÀ(<)q:ȔlZ GQPdthi3;pv5pe~: aP4+y*Vܧ|DpU>Z1|hP#MKJRbzS|(`AF'q U>m/̵(@%:>#dE^Wy̹0hzi C#hnjՒ32 ~PBVM'r&ɾ<n?j>U:q#πjYw:=<??<Vuij@2} E?Y7I2q7a8yaT*'| Bl%RRZˊ3QpF`כfx)j&dzq 'i_ޝKQW &j\rxcx~۶Pm C$~̛ARWnt9 Hc?鞞zy]5P3SH{lřbADjq `B˅2$sđePr4ڵZԔlL rcbbWvq44xpdV&ꥪ>4J)8u8`gT}kEEO缋j- :EWj@^H<!&KBM˫7}uR"Ze4Nzskt-~ 釤 %Yǀ Dn{ɴH>_>nzq6g !ߍ!X*nsT(O5xf-k'e5/ `uu_x|j)_qHn\ ^Lt^ ăEw}c7&N:,DF,Ha!0,SD FweDg)f vZNs#m&6gaFNI2۔:!RM3lL4[en[ LV49 ͩGŕZ7>p 2>x^AYSg=,q/dRVJ0$V-m5)[i|^^0IPJǁg`V̞mlϽn=W)R8S" {6 nH+ʹ FhcXs)ۣH-\}lWAmΐ{>ert"$$CWplt@m8o؂ۯ˜JFEE&poLG!%YJoAh!}?0ID$ ofwKmڷ;VмjtߚViwW6mw:~VNj fsmO-I#_X[O8-Bʷtz.]pg6^-%d%t#ݾ}EqWEz_ś0@e?/M>7~i[E 8=;2EY/"'ow1(a+KrM`>S"r¾ X2&!]1*:7/C>gnTxsPk< ZxWM0XSV!z])C)v1hW|Xxca X9@qηr3N// ) Gp]FX^*΃eyō~ikٝAȡYqozBe"u+޳CkD^+)ph$UOaNUkv2jә\Imq^BV܆\0[.5ڻ&ݗ(C;eBnk+m\򄄣Q[m'e)*-Q:8@p+YE!yrV!5RC}?/&3^g>e(qf1X`\ +_cr}4x͛2wzgxA)wd-yw^]ۉ[WYu1"bfXMd,}}V٨lǬp08hZ2t4 (o~WZȴQi5vc1e6[r@8i '&XUNfyQNPrTi)~p`9, ӑX@\mT_:梊9W̵/ $|6.o໯ǜQz$Oh*~EQ2טO8':uF'8lh󞺨xu_4*[Vd87AMNhOE4 /`hh(h8L5L8h/?OCrDWxJR #syQ h%yMpF1C&gU IoDdmFNJ|Ln,)H0ީ4d.p3V@"DLDi8 GtOd>~%6Y8VS+R4Cg@15)+: 7o{^4[g E5W SRdD#"+Qs$mEA_9 J[Gs|RH:ƜP@y?U }Hޅ>[`l {?b8J=nA}*V)xqzXh#$rD<'MR[*xILy VT݊Q)#HՈXtA 6q%O ƌ*SWXЦ%2EB~ŮɚhcJ_b(NڵrXj&+a렌{D--CÏ2ͻ m 881KKh<0RHrJtiӇj۽9`yAD0Px^"b 'q.[#t[%ӳIrƬSP\vk(pUpղAEZJBwirBh@ ̠Pl'W^ 3җ G<kk"x:0-~ 1m[S;WHi"7 5`%־VE+& !5A0ZiwQ%nJccV bv⬠HCU2fL^ !h0' ܀Y;V ߅v5ͥ&!w)F~`y+B'~,"w^u&.~ȭKu$C6?+hq;}}IQC^E4Hu^b˨ Ἐe:i>qg/&;"Qp1n9P3FoIT^lC"L9pdE>18 2t#MfEvLD>I ay=NW;v(cS+[A9<{w^4}*dr4jk|?mh#X3م~F໺ˋGpj+v`zJQ5:N~~aM Mgb%3RcjEc &_x:SO2,aspk0Ujbhb{GaNM!"ÁFP]!격Phm7`͂X ip2DC;tڑPTY{Ө-$i[Sovomjkͻ09Ѿ%z2{oB3 |.@>CFGZdGu#;[x{Sm &bȸZL5~IIG;7zx!4X&j-{N6T6d(UY;7!&gweVIo)0&*kۉ j8KЍ( )7VXib8@Kn y+nI~y՛'򅺈BjV9Q: Zg511Gk {L>ѺdHaCs3m+nNJQ}Yᇴ6 ুˉd:t,.:L߭6nˁ#<ؙ.j0S#U/U&7g3uZJapBxve9Dlyl_}#b1 #OR mG~V(0JFp(qG?"$zFq@v&Չx k@yn AZT@ڥN2 7SkDV-GvZД2D)T ΜLkhRK,{$}Wk`]#N-y.*PwépD|KFo!{wP9 m}ZܠZcQ=T- nz UC PԠX|Y'v;t+Y{sgEA6s"4Cu.=|?WNnlٮeW:S}0<MI2pd:`0VfÛWBkS f:E2(E~jYbrc@{wok4q=i>o< x:,rCnw\_žoRȡpie 2{\"llY-Q ~A50/(؅VLbNA-M%[j_"Wmk?_GO (*]Ξ?^1M6 惜m _ _Uvo``wxNN=6MȳڇazQ1⡛2ƴSGUBRܡ@a\Хuy|_ ڼ:m>`elzz,\dW0{s8;oJVǻu٩FH@UBkzׄp31=#i;hAj>4G(-K!Тɂ[6W A4}``uBCjZ\T]+Ey4;Μ`wH4)UXɎ Z8s19Fw+s15pZIpDPp_l xF 3ΰU`q0Qј^u 0rCxH Uu84M G/^OkyⅫ7^MojCF8OTq@gvBö*-j7a:f#~m)dĐ=r{!B-$_ۚ2R# ւ:`"Z%ԓ" ''˖&=9I߫FP!J׆cU%v08a7vs: }Qq#VV%ehaccݻubkoZWVrX>,񱴵fT7HU;UN/6:|t)TD]%aL{ԸYYշ vj6 7Rxl9;Br]A?iX7_]Aޫɑ1[5P7mky:tDw,\#0=FHSڀrc{Җ q* 3, ith#C-NT݆9p@I4nt:ףq\?T:ZIN=r '$MXΪƭW%a֤HSc}VmvWң&H31+_]45 6t WȄw `s6Ёc|eP&wWjR~PTNS]!K5vgѭt߃ ̘(3̦p\D$=q#DF_4X.jB g]Q-.1NL.i%4 O,\1R[3Ь.!PwO8񿷶TDxpn'Gi!/ @>F~(fZ=hsf0<#[D:i ;LEף$H-8!"oAv Ѝ7s٣1YKP ;3C>q_1tA/Ohr<_b 2ø*({#Ѵ#tvR%t=S(Z`0r $[_wsYgoHn~kJG=x&;qFOwi:N0뷦 P2nCF~1yAOPƦU"Xw.}b'c:CҘEd԰$,jo(ҎަoV*#[$f)yH2pM5dUVW@ZG۫%sݦ 8jd^p6LܷNrK(\3iSu/b212`1S(zƒ,B}Z@}-R>e,P0Mx8Td fGdagHZtƳ <<-^Y6tۜ˻mR` +0?~}‘Su?aN7P+, ϓi9j"U h{ 4K\U=aK+8@Qar.(% u6H9H 7li&^)jE,˳PCitLo p=`kB&=U, [, ]cb4v2_5K=yz):FMwk} U?LUKn :?g17?e OPJJu*UwK &=crd t@Ui}0XdQ;@_!t ;Vه-h*1ȞHԘq({nZzEuh8! |zy$NG=,Ņyl9J]`X#)NڗYW/,aa;$ E4c3DDG5M8 [){x&1FXh $i !b3 '9[}jzYsH2zD9YZ_)l]ܶS5@.wrQ]6 ' A1Xۆ3MϻEN; U ASsyeU|9 t0<\bsK {}̃2e3[tG`3KODw~>ƃڲ> 13;0V0uxHb<'\%:P2Jԕ>AQ1)KMp) \@͒3Mg('D)asC'j#Se3rقV4\$R ܬ3H س b2 ԑ|P_8IRjV{9!?4梑á p}.>SpŌOqtפfMG֏%$}B4QI-ȥ*M*9d= 9Lcl Jp iopi And/0L\UMPMT2 rh=؋Sќ⋷Y(%c_cw/BG;:iKƣ5g/1+pR^}E"ܱm xc N)8zFp- `i/4酟dYM1`5$4%318l!vX7HI4R HLTFlTj]/\+sa%bRxmA VCtGBUL\  2wwm!_&ˁ.bdbƓ?p6ZrM!c68GR]aZ#N.3)Xfq&jGƣ=ʔ2HIe4 )_ .rxlЮ;W~_@t}??[.(q暂ZxD. 0;< nѾZ@'3qatrA)l%xx"HD(1&֌9V-9͘3&6m=-s5  ztqHZ1/L8rdfءkk4lBw.iRmŨx\ȚUAsLKRb`vP7BJpbqKlSa99FPKX5NOM!TޤT(!CV ,6״0(I$`I[Z@SLZbNB=%mhyȞx F nORuEjGj>_Re ۟޾zyuNzPVVF݊DpJ{v¯x} OdǦcga۴[Mֵs'T!}<fqbk;}#ļwu^'#Uk_D >\v^a9ȧ"uf;cm3/fĤlnٚs|IPޫ`=X lQ}gX =]#x7wݹuWd3g A9:$[w ZN`6 Y^!Sw|r:P ؐР%))(*QMqAMR 6 92ԋQ|D^leְMQc)eI|Ya, gx7hF[VB 4Lq=e(B3J@%XB-@ ʜ.K #7;(̻z#cHs/JC”8br$9XY87@4LJ`BY a:: UgkkaǥdLb̂Hf"֋?a+9W<īiz=8[f# 5@'D9Bضvټ/Q t7Eu8gbR âx8(,$α.duaڹvp  6E$~r-j ަ5;+ڪq7P{!lozm @BÜ(]u2Sc@,NO$-A Hͫ`kyWGJ Z>/.1#ā#u02ˆrm %=U,g`[⅝s  L)2șm6ʋ6(;CvusqXc4E ׺<tTFe^C&"/TW2ZpʩF '?6X5|T4)A|Nr>`Q5FJP ŕ,+qE&3\Cjԣbd}vL9=6tX;y?Su0j22x>0Z0/KʹQ0T4\fM]6&f7X% 5rKz?Yoț?>`T`% (B֪%ڸlbղMüjFWi"Y 4- |VmlIfZ/8D@p hD(L2qZAwz8 a+7Րv&+ 4LdH"˯!{$&\8>;(B[} R,` Wa (ې3ZpݿNkVhEZ!!fZOuEф%"(Yez ݷ1x¦`'c6@QA\%Sº)?zxn6pB>UDZ#2N5jV;r068=B1}G%N8T'Zb.{iu2eywVE)O(k8>E9b8r*t\N"a feƮ~!}AYu~)u$ C~ql[buB,[IUGD,q !}<\4I+-ZriވlsfőxsọKp͎6c)6,Կ'UsG3aуV&Uū&n$ @f-aX,amH93LICnIOm z9%5YPR-9qNtn`^@RBTTr=f[uTP 1ݒ+H@qfu &= >aլ%q$J@l_{\crCU*7N+[֬w6-ޝFRlv:V)bl F6"ۣ%#fK $ F,W+ +j\%X`^(Ic!H=WCk.,,RT HZ6֛)Hj[j`+@*U5hFMA,[^]K{r[Ā旣X쬨$PbXkkA4@$P@)z n:_N0)cad1!3w;R~[_ZV9~#4w Mulx$o;%t66k 5L }RGJ=?>F϶ux *0v7ZmBhk E[`!3ZR`KD)!ׅT!G{(V47a,x^U_D?ζT#n FjP /YO&X ԋ3U®T#Ix=jg ^CSX'R-y R v>xhԉT=x,m:C-t<}bL3*t_Gkz {c+WHIN}[DS 25]G}}RL\-;Bd;ӅhN#4S| J k[,^+E\S_ Kx%SV2WFP"U_6r"oS]ol=~k/5Hh mr6ȂiWqZU1d<>syA:30.6h>8(Фur?8NNK0'!zI\Uq. 2̹]mVt#a*;aAH?DnH{A ,a]7{)|ҥ* 䰂7i<$`{DV9[R}&c444#267qb2F7b[;0pŸlNyE"LY%uc`)g51~n4 :^:DmZg,E&c#Slȴ (ao,9:х`4pf Ӗ>8u-\NOh<\,xA}@Q?38-f+.Z @jf{eb̿<9kҦz7<9=/F"V;XČ[ jn&qd$/y[C,|TA%&H/@O4$Ow.+&RL6AyMԿV^U,31o'=Sa=t[,pC+W,g`ݍw~pjCR`/ٕ6o[\|R} n4^U̔%oqiV?LǨ<+%XNDžJ%{0pER70æ[g)sEQ|#6 K6'MIAJ|myg\|NnMcQ Jɠ61Np2{Ls~5d>@'4t v.Tt8sk|gXp4=xpߗ,lbh8̻KgQ7B\ӄ܄K)Lmd('\%y.yA7] u%v&5: M^ўx{Smgno$~T2 z;n.ejjPPM`.@a4L8md!mv ELjceEzx|fM]w&}XI@npzwZBt{/_OW=?94ڄw4A?i|jO]DZ֠p cEü\\x\;n хV>kmZ[Ym[)Ȥra=xZ3-}tF˰TMX;J nZK""|Au1 K{ rt I{[w8XDPpށh NJj]^M)o֯;t-W;\%҄e Th`v0tzIZ)1 KlwLlg발q9Y;J,Jm^b0'ednp >? &@\͍碃!`"EIDRP0 g~d ^60OkFtqF͡=~Ch6g|?eEأ0xL>[+ىidNM(WbtSc82PB~-Vb h|9&z#@ O4zC3AnL4ٱ%wAxp[9hEf!$"֢3'1<gƠ#~lp)x"}j{Z g TBD?-, ͵Mԅ`1Jt$G~Ը\)F|rMށjubG-y1Jl!3x'OTJ);FgJ]sb.9:([97޴BY!QkY5S 6H+K-0^8̦(ʂh YaUk+0\jMH60z. -RR)wf^" mOoOɱ?@|>!mFG?̲6/~|Oj8"IT ;lW+ܸ0qOQ/:_*e8[ ~ Ql "`RK)n?dl25Lmg( <>S̚@M*|PFؐ=D^]Oy.V@ 3$X %FA$X yn0E@t$\V`lRE> m,JS-%&Z-'S)Ht&[Zbzp2d& s2ESY)Tk:M:lN |"_<51X #[i4L(ǯj?̹o J#I 00\G RILPՍ )"M5n…!N:l&ގyKM,]@ @f ܺNXPeĄ) 9%o)ݶ(^stzuՁ\$ρ w-I-\@AЦkK$-HX?:"%1685xɇڶ4 +A{%JWd|%m5y;, P7i,5aE&X5Os"N(L+*W%q8=% hIf އz`E֐0aЯRLm}lH6&0Hazb-_֚ܒ.p;F l2QW)-: 2dXդE_PH:Fob5@9zInيlʞ@!(if* 1uÐi]Apx&oX@ʡ@cO Q_ uBgfAf{'F! 1c]/b`/] h> ­Fku0Z/HmZ_ !yq3A tigt~P3lgF)Y!MXͥV#ܘH͂H dqP:r@9O\"QbIK< WRrbD1DE8QCJ;Sq\(v"<%Fq$bӇ>>PSqQ GE_5!.Qmy07cbxMBAhLB'Oʆ"è  I1F@13SefVw7Sr| j/ i&?Q>F?!ch%.Q:=X7_7φU#PMKbIZBiS56oaPUڸg_E&'")g 2~rޯ7nA7P(-&1b'>SٟB;ըQE)|Hcl#M,M)̠EՊE7JB=9U 3%_SLwxsiZ{0${fzEME㋞p$cLV hbrago<wxwX0kcɱ0|_1;!!6&~ήe9 HV$v]e{7IւVWWWUeG̪Y~$~!buP %NbO&y \8h1Hu] lq:;ƫO:Yt?*18590,%@F 1O6B@"H1ĸHf QP@Fyd FҤLo^\d. 1qA .|v'T="j6uƝcב̡Wkϼ&Dfgm:m'ņ%?0\*'gmk_ywDu \3_F1 a0"[= 2Hpmg|u[X"Ҁ)byiE ”p@%42=(ZS!D?B̎]@]и(j| FʽoFXKM#θˍ_bdgʍ6d5@D ׋uQ17s^m !`bXі:Q2Iee=-YoS^ "i2LghѦjWBTnԾzOA.hk@zL y7[෹Hop6;Pc.Vw[SPGqvB=}ꛢteQ xU*L{(0kύ(Y=T{{N5]ùZh5`ɣhzr;>,kE^]mHxmiAkzlW.)NȠw0xwGM,M6]5Xlad#91gj-/n :@MCоօ[ᬱ3dA'}6 gL8`41s.1y0Ð\a۪l&{ij"AG _ropvdW]-btOcJk+M#AU38{y)G,  5Ft}# LF Œ"05cFkkWbA#rcHVޞȦb,MR-3-a\o7]E " {/%h b_i1 V޼kh1d9ņ׾WҤ 2(/am0vyP5N A|INj\ 7s!%%b1L~6Mճ_q Ut]D L\;t٦br"/ܡ6maYg[F%i΄HR=hEM}LĤĭ_y@}ZLJa`{ۇKot pH{e<0BJu{в….< (*|*8'2BqEX8"܄0LR #6ߔu-sQB +CB`@EdwQOloDp~SbR-mD3'bo`U.bq 5"dt }+8廙8H`S|0'K83oj$ÓheT0%|js_ƪѨDټ,#H уJD5@An lq4HddMT s4vV @nu93VKFRo4EPhM?4l4*)T4?enAcV({priڿ>" j^M{ ~؄s4:ebhZ\tl8ի}_/^i={U &2t W:[8TqLFF/]JBc/nT>)5  /K_xo~je=^@H!> s*7lɇ̻ydg(b<|nk]I>vwq#jiDvMY80hDYh&aWU5te҃0&zLgi:H00m'^A{HQ)#u^ƛj5z? bEuv|jgnϒdaBy69U$ ){PrQ,ST6UpkGja(PWF ,2.وFO`Xw怼 - *~PYI@Rf7nѴdN&~B(>Łh^ QMT4 a(TV[bk>K ha43ߋgձԇl70vhGߜ$*,m}GgYSX""K)4m4a@1lu6ሶ-ԂE ^6u*w8wbԒ# {E4 g"_Nxb/ϥC0:] hDPD)&D@uvVzbY I߸x=HAتGm#Hy)_t?`tN=>/F>S!/iB)vbbBmdZ25N9 1::j*2~}5W2jAPEPmb2>mMͪdo Fבt3N9 s\Hsk7[h%T|N|YC j*(B>Eb| [`9_:WuIvA_;4Om. 6}tW.SS_p W\JNv\)P bfb3/Q6NsPA-h b_mM> +N};>2ֹ:w,֘ozv*Vsv^do-v>I4/ns2;w6x|Ԏw3SïDhB*_k"۬rLM>' 3djNxɆ`e$" j_ YVUB '@p58XCGm,Td 1I G(h`k:&OD "q2UAx6wXBA!aIz H)]b?!նWL(rMPܫUL,'FȀCa l;1F>MŃU4X.&+\@b 48-T/`e2ڀEx],&nq*ٔWzͦX.^65=,tJ /YLs^h~샀\Q@ yipVbM$[ FJ3 L,%:HZFS4 5 :CZ.=Ng#fIti\^`JU^=l:3R@8"Ro^p9ŽO3C/6$@_"*(><|%;a3J*,i``q;/ ;HȁH#N񫄨Q'HF/CTN,J"02&ÒuvbI"Af-i't0 IQK 4R!.@Jj<@4̛n%B$)'q:& F$'$%b#Lk5DP6@Bc-kβK=!5M_g7Ӡ=DIp4J\DO=`1;ɞƒf{6|HqdqS7= ub޴ke㣸ޓLB6/ɀh7#@JަX٘8YhSކ = QЮm9UfO镖zή;F#29ym"i0uJ\;=?=8bg3ȟf 4.MW䡄!;DTK"cdcIާ,E2 wtGgr(EG5k0. lEӺT 돡>쎃,56uAaP).wג (y>jL3F`jHDnpmb`D~ )]#+j+Y=PK[0M(q1!.&Ȃx*;ǸĬH`--51?lQ7̻bU]{% fꖀ{٨)2h+v4b1@i~9@>W-bxi-*)tBؒӨ;%UMYERMUpb<6'jbQ[Խh'*~ )}XO-P"&s+6x< am*(@\ЩVvUNy Z -o~:ӑ/uQ:g=KB['Gʤء&f@ dH!o8- ڢ y'Nmл5:R>^/cKT yEe'q*rZ'UuJ{?kt/cdD 2 gOT= i%*<) [(BS#hζ "Brt˫6Cd_ەz% ЕAP0dKRMH\17"t3 HVR be¹U Y=N(*ZBe9@jm]ڎ*'vjUY?Z(ň3жCh%lMiL8qT"mҪM<@ր>Ij}~eu?$?Hu|1~A{-MLЌ@ݡ81 9lYߟ6 [h qBnge+Y-.2 RmH &GZ2F@6Frxd~;cot SW[<h/#IG Y_õ[>*zGMJ@Z[SZȡ\ƨ:AY}9C0Ej*(R.(>rTGXw w2\& AzT?DpS7pP-<Ŋ]Et=(y\j7i`\E$, W)yJ/|#m,ue2ᣩR:y%`6`T;IF:h=O9Kk7UB>047ֲ O5l-0 :ݝ{;h>m=lDvo_n[G`ѫ0Jy3KrRԮٻܤɭBAp { 6 4DA"*H/s+%YϜYW+H 6(04}钆)4,t:R6Tj zP_p–k޸*hd2kq?X!h'Lq6S2uv2Ogggͳ{lvv?#6+z<d8 KV':]Dm(cӛxg{;wz$+::ǟ; Qr$[|}C$ *erCW,Xz̰{ ʹz·µ7JSnVQ=&nN4IvHWC!VY#>>&mƺ=̊ݺx@<)~KK 91qr#`uAmaQe%);ӭhP-._P/"J՗BinETjRR!dtbEK8'Mc<$>㈮)0+Q3)u AE)k4_a= q`6 N!')AAWB;EAb \!XUc d%n #L7180&6o*yMsNgi29ϲ<ι.ɿz<{;^c̥`%b8\ #tCn3CeG'xe+8`1,lZBK#Ј{m 糭=7M1ΒfN-Pl'{kC6J9^a C-i}J$Mk4)*6wO3WhD}&X?SG07| ޭ&{X_V|[QUZXI(;OG M.l%v1uIp_6Vuuw ϝk5l͵Kxs Sm̼.i,^ ω:R0؋wD__Υs G8 V{ro up<[@/:[Eҵqܲk~WN0 Y &;;mב6> z"R^t]*+nNe8OMmϏ_GI9*/wݩgE3Ox31m-C3zgsaP6~93A9AbY##"ܮ@8|@+֯~ v~Nⶦ2!PO#qB /}I_>qiKZR;>5Ђ% +||G! {KԬ!Pu9B,QP^=bh 5Ok3\J돁hGAO&ӎw+d5{@*ƮJ6*LO7tŪ=yOfuFQESHoqjR""82Y+K,te&ynqoI)knuQ@] uj@倦`?5Zk^>=2t)&hQZjJ{ap!XoRk3bWh|Zn0RUyE9cg3o<'3?LLɆ &bFC |5]A !KūqôWS܋Z*y:&ce)MO 3p YΥnׄ8qL^! F`8eixϢSlX(!D6K?h8Wѐ3L+sE'j zf2H/@8"䰞Nt-|*ũ%)&`p7^OdP', [ 室F9TG*O8XQ2I)GqP^(P٬8vTaW Vgl F{r]nc府ܝzדsPE9B}LyOa,W8&P51Uur[i2vpoWb(&_\(^ga`v\'c}nJW ºZR|{C>!B0| qM.03h[5( 7ʎ3B qE\ j7UM$q/fAqC_F ,aoT$˅ Zai@q_@~(Ɲ 5˂| Dyܤ;x.Qc5Vs*[9uwEIt{V.(<=G,!$G[V"rwMlH$aMZJY2䫲DY5],y *sk?*m}}`@W|t~KM۝38 V[H!^`)9x(06 ,Ww#CeqZ`>sˍ'ȩCp6V}Σ5_nZb} bK zFAta,jYaA:K'D\Ω)^mOBguN&ǰ$:_ I<*t&N9:<;ְ;udSRDmU]ĖY]ٹ9N?ԪCTwv|ҩߏ%E [5Srh Oi_?Gn!lDѳ^nE Fkb*VYک4A& [>'a8gCaC4uӊ/&i:`_vD]kg&.:`t9yS,Љ@tM;j <(jڗk0(ڤܝIGYYaPW[1D}AϜLu2J5 -/&Gd0"A+ 0Qӧ0 -Nkg0%mb3)–5l9l^4J娘neW]M14鬥j5 j]IyoշwmrK|A&eӱg:qgݏO^F3htwlWAI7f5$者0)vooC*̭ -lY|j-ߧ(+Z,Qyז]}o/ ēqݘmI-p;;ᚸq0NG 4ɯh)[Z['"#nmpmsˡb$Mc%b&a?|WIE#Gz Y ٴ;y4JHHSP^ lBb6{C (t( KaB78Ԇ#:uNeƿ1PGi9iHnr4ML,l>0*(/]Ez,Y҈܆d#c2PiXk0ڜ}6\pep_}իoV ʹO뮸leNj.z˅ 4&aʆpN?1`e8 !=bKT,WC݇<m$zn-5 {ZmNUX؃jD*"1x?jdR-ȾD5QG|/jnFd*9@ڰn95p/'EBT@dxLlNl]VR12R ) /V J9 &~K&jM?( -YmDѽ>i͜6j3~.2 /l(^׍Ux*XEĠ oʮ1҄$Ƞ#Ba.A1ON l Dkgs1S9O86 _khɒ5q:o؁8xL;/% z5#:7DْWݜc1PvJn: . 7"M3{cUl<[s*0׻wƄ'.[4ɵͲemsÎs5f娄*`jtٓi[ā! (꠲[8.-Hvx"{" *&KC:iûػ`NN^f!F))O gI;j@6dXCvE qWf[Ptv(~o0gB}F`7o-<>!'خ(<\PF`xiKA!|Ltq9&Mw>[ }K^]Cȱ^ ]?sl̨P] "/EhÛЫMA C>U07̦ix~B,D7We@^<-1m`]ARA8'4 xeQްA7`N99QRxͶ <QǓW5mLHnCi  ~K7y4),A]P\I {B-ſC GJ+Z|j'(d]RP՛=B<97-s mc"b5М0~)?<8[L6_ aP3ΊP}Cu@4z,_1C# Bɯ kynwkS]Xb}ը([?<F? sb\@U4&!#3疶E( o tuBꮈr 'HCsVS@Gs9&zJ[\=&|^ӸW2EjWQA@!]{a=).v ,T4|nauCHh59/^9Fj|oeKм*v.J5hQLFtffl%%60l50+َ<+X[bi> N)dFCvZ|j-f(~Bq}_Ca@(ɦEɚuI{ :Ѣ,>94@M13RuZ}!W t}WtU&ZJ(79+>hd7Jib'*א^]_gd!%'Vَ 9>Xm1v%@Tw_z@ЗZ(3Y؄ L}Caz 0]sanpLd!kF6Ci6Ǧ8h|y?Rmni⹂vO2`(in-`v+(>&K WrȻ׊A W|g$-)?,uwC.q6X(\#ߠ̎聶%SE)^|Z vo4ǜ3K֋KkBl0;pG !O@8V+1.K\럀m&tң( <\ `8bj>\tG]34svtvq&Ч%f,/qk7TnhY8i3x.di(B(2y|5tȯNq$zo 1 [WGL7uH%##2# pPHk*Iz,a E &cH,*6#5kϥmį?þE0)ܟG-VwB>?'Zk&Ovm^q7ǭOW B{;6(8҂m>߅OSշv_gp<:?>_.S#m#(B,YBgYN~^csvgTfw2H:ʦFw 6V#_ABSqfBI`&LBC qӄ%ti2HOtA՜}}ٶhM#8ܞHf ESjzֽ2CjONіP ݌cj,ݔ \C8>/ EkaHkM!=sҧ1H0]pHctk$GP+5kЪ5q&5&bfl J,n򫻶rC)+yAY*ca| W?~4$=.| G/mKȥ(NiZ Z_8BŘDJc b~i*t\>Ðhsy]I!R ^&+{Fѵz1x5xmٰyt=l}6?.bs0x S,( rx;k DHXA1ݡo mFZ1N8SJYW Sz_\yis+H5撫ⷎm #\F]'T.k;\zIҼ=]n%Lcx!Œ [9s@,$iXSEOHc[OVԉ6 u)YC@x7#Gۡb(AD Lܕs&kU0.igP îڦ :2;w,ei4rMfِo Ⱥbƨ6)Z{kܘ^FcdlLv:hz鄮BP еwo{Ӏoy7*XhyLtn6k#Pײ;vgi r n% .0~] t:D#ytf!{HG~?M p,82>L~ݽWy8p܊6ܷ:w4G"53,1Aovۼpww#ykGy>nku>q;ܽGfڿA7K:m~+g3ljof.iacWcASLN-TQpq<\aO:IM5ICCα~ԌG']\7eYow<@9Xh=Kx4?J1|=S'hasA($$ u^)>v#Q[(ÚܲYKBJafBP8t^)0\n3]FEpԞR ^7Nof yمB9C G_裬 v~_}ͩstvɽwތAeS57뇭mfTu[]FEC.Q Qc;{N7gK;'7W?LϟGv-h_F p=Q)h|^L~1-~^L7 ='@qf'06tՋ`|MۜwAms k<(ia`Zl0$tl+tv3UpB_Zs/Q40;ѽq軁>E=PvΎouX,{l~'ʚTv՜ZF6;41/,Z@dL5҃$,(eË~Dz[*(סRN1~ĺ*B\Z\qUj9dr+/vͣ<ݹw+%>e?P(jLG|:ġ&<`.G.+lŢkY+RdE0O'(kXAZU% սbv.m6t){@ppG55DԴlŏ/޼xEs @m$v_xm80wap0x럝 *ېZaHzr_eBt,ˣŤ)Bl^!i6dI*K bZiIZ4be/Q*jX/+&ҍǞ%hiZ7𝁍wÊD<Êc_%ro||O3?|>!Z# ͣI)ɇjxtOr)V̸/A8dL@ vPD*#a)B: R{ۜ"J70YɻGقmiךi=Ez;eR5A-&P>)f:BlϊGQYG#~؏˳1m!,t y2_*S]uĹ{B;+9i/zS);dN7Z[|F kPjêjmBz[3|&^qGOaouPb] "݁B.õEЁ7 pd32 ߸LH<5-z̾xI13xMնp@<ܣ(&Wmz&q .|^3yC73"dJ8l&*ٚ/roߨm]ڃlq4DcW?@:\=`,ibʱlCP!_?[eI M_k _'n@&; '췀, IXE(;9+C'bݾ,q 7g~೉ch?DXJ&Y6"ĴY&FS- zkp` vqpVMVf ^ >un>/%nJ(^NY}Y<`eP%bI H0^Q@ilx6~iM԰Trctwbӽa7AaBv69{"%^]ǘfi[{R)rDvͦ*TsyoU:5uD1lBY_Ї)| C.۠4IޯM(9!blVSXi4Bm%+o)[v\ Kux(( qH% Pf1$˩ LMk"h 82@B+=9 $&T1R/Q=$[ڻW/śg‡nJ,(mI;|1i<@iIx ۲g,$vTIK/O=̈OИQQmn'@QPb/k88Iձ?)VCW?**F* /-lP媘@rek@EUJz_s>ʋq4Kbq.rd^;2EFj&cř_9 vQ\&'8lmQi_Lc$LٖTM>\t^G&"-lFu09gN;zM4%KUS?z9T6i}$oCJLsDy) c%{)@T {l>noכx7/.)Bv1:淋CPzrNZO2G$B#<M$(p6`ooO`S+t>PjbLԅڛԥ4I061 :zALmLȍp+^hp*1h8!tT;&&ه9[/ɪyC5[ZNL!}vcgg+A$%_݌nP-s F K)ǰ.M% =hCVRa!WLYS % ;2JXk ;rp~$K֯(?mܒd$}5oPnQ4ja 5tOrNZFk ^eiУѻu [S̫\Wzl=8ǂf36}L˜_10.FqEZf*pa9B(G/*clnr bܠY€ƣlLh~w? jw2u(xr t4V]ad/ֻ6u>Ѯ5@I"=Y& V#a2C$e. gt>gȈ0YPnPm)1mP?vÊ[W,HE aCB>pqAxLg1e2>Ɖ8(Up4Wuᾥ_" Ein k;m٧n$Qqbvl p Dɠ Ȭ}WŔ;^Tf6VK֯60CmM $%]COJ"SV7Z /ۿoJF<*#?skWo\Q $(6Fz 9yxAukrWp\HjCqdݶjnY{;|؃rvFfffQ 9Pބ! QQ6bdH*sՆV+XFY>ô~jmOkq_~OlDI[t_f;Bٙ׽\86d6 +T`JƇn)-ʾ'LC=೜>}֣/(=/vp:bw7WA*-. yGݠ~46HjD!R"_s>3i27Ttag̽,0zO*0 tqGn";#(\<\jۃToᡑ ?0P3FS>ż mlx:Ud~AI4T)TTP鏔ݬ{7 j s; ꄦW65x)0ߚ%$c.z,u(sGx!<)$aw栊(y/Oex_㈠ad9^b0QtPC%U9]0,LB>FŝZS% l싹(/9"P\-TKoϝy<6>o:"]|NJu2)膿0T_ 阨A^>h!9nޓ]ka҈65^I r;?t#vw| !IK`2 .f4Ʊ)TTÌ^9s"-k͇D89vTs 9?cWآ |#|a=qSS( EL}9,)N4,Oe]o6:)zSbMP S܅!Vؔ]s VodHhn-\ڌ'M&D 萣ym][4s]jfyBTg 2 g}/ K87'ޏY\A88nY8>DMBH@on6WL#kCS&._aVH(j?(!0F[H&s,j/I#mQa#m 3N0K$1Ȇv78/1?#x0(Aevw~!D;M718K j= :|sb/:mP@rҺg7`0%OY"'o 5h;Z=Wu`x44b kͭr~S~rYr( Fs|-\\# {@  Jg`~:"#DA4㕹 0BV)uy"R<n Z[ʌXp&A>J%_ˏ %Z[/2:R:A=kO@ ߚϻUVyLQ.2 x ?eK|qf<˾69W&N:Ggfea%GdhP+QX*>:{\f79,q.`8٢]d W9ϧmV:XT bm 1n\6LС 1{6"Z^XZ2t蔏Ndu>K<Rp.b|F"S\s襓-Pxb,ALj@Ѳ[ {?+ +|TR5;:DZQ4l8UՠŲnِXnHQi6i,l4S%T@ HY-LUTLK*#/kO梶;۪T.LM0! zFA 9?]G6O k3^FDR=vt\![f'Mu  JcFMB -Ad<ѫ ӏjه#ʚYШs~ D`K!TÉ0J0z5Ń DShR"骎ݾ; > t$zxUژݶʬ*D`2Ⱥ1iMM#AfQ0*XNC XE>Ł:·YDP𯉎=LT^$4-jja[`#Kqh9>W6x:#Ls-k5se짶5FUwiLNIb FqK=e sYE_>.,k44WN*4oď5jWY(  @QT+!Ϳ'?zPnn=|E>>J'T1G"3 5)aS{57&%c,U;S-@+m@bB3L$%:ߴrm Azk6?RrT5+djT`rpl2a9$02*em3~:Y?Z(ٵ kF4zN,/gWQo&qi9nhs{S )w8 f2mۙ/\Y]泙F2̠]`=44kq|b:$BABLkI+llExF_NZDa@ɀp>$ 9)ʐDנ:T /"aDq7ռV!&_Mmf((h^Lh˶Vlv͚j} UCvֆ (A:jq;̚G$v@*wɌ x R G~/GU_bC~ԋGӓ)>(==^%wX5-@%7|liZi2ѦD5G Jۺv)^fWt+Rxr~;{CU@.Q1A]Yu4on! ]Jϲـ8Yzd uL }yp @놪=㡕咢&@1u- tTm JjiMI1m y¡ Xl]8Mz}H/ eu6V\oFQ[Rp ʹ;w W$FTf|F/4_vx,% :-A0@&]wȼQG]f Y+Y :yXz2XȲ(]OR;"yjdm\7(wl5[X;cW nV :] +d#MjF)_mGSD"aTSܪm |T)=?FLLMܧjA, LGF,`%4+5N.Fc8T)L~@g\)B$7(𤢞puvJ9'SQj6:gf 7DLD~Hd+Gu`Dz39v/S}NtLny=#0&TT\SeT沔̺J%Ės)-)v*pg?Eqok@+\`ZxÞ$^@v&Įh?+\,)0h&OW6RKW" Zj0Xj!睋gjZjD,G UӦp/XE~3$jv*[t4+w'լl/n6=I* YyoBɳPUjV<]=(K!Na=Jړ+bq)R:8S_yOh܍ ̥%(0OhCxgc-T|!xS@e7fe`MC98Eob{>=/ t-qgt);/^n|<}݊ H3ND5 "hQiYpWGG2n.N`bJl9%d1ߎcnwX ݥΨ̥D6x{ pP3pUV?AI=GG;jG?y%3ޯ9c 7G *Dw)^z*n3C*;ݫah]kOqȖ)ۍK2xZxՂZP XD/\D+,7/yƊ.M7ԬXl21!^FCwqBLPFd!š9,2aTd>;YJI&5΍0ƳSPi ZBm d:Jn @5,KrS^/f8OΧ6 ыɱƮ+.4bz7MZ3=ș̑7Oo$jBP ˥H<] e+\ɻIݣ2Z{ 7m 4aYᆬd_LTߴu#9r=?ֽ_S?g Hpm*h5<oD| 'Q; Z#Evu+cXGT=ez~1bM(EkC3LϮ_/e#ѱMo{} Ng:jC qN26!Sϋ12UdLؼ&%120}k2kGB]. U0mT9gG9ZGG@{EbGS։KʟrE? tqMD2A}mc6(|>D-9i{Ը8&9={mBI͍,qt~7 q=vc0 7Ju/-idR}+k&G/ދ-Ek%]Vqp&z='gTx$XO$>yn P;rkH|3Z8?jcׂd:zNv$W) &F䙤jΑgy\u5. <ɰ+%wq& #es1Aȵ@?WFݯ?zctNh-1P-y/)-.$Yw>U \,Zv6}E>D~s?E͐OfʤD3$u P|,ٜ7 L/IG4qH&l,evlLUمŸjrB#8rL4'UY$SM>Y$%:dpi2)VYc>죠Ie=PP#Iı>8$JKbJ@+!ВYM9(#TggM@A7Ƹۉ%5yK_|#/i|;_шX`gut&Jydw, :h"[?8_qgƆƮj .L 9]+nO+ Bf->lk2P"ƩJ ̐,Bsz\qJAN]۷Dj+!x| )-A3 K#h8Il.nгpˆ#CaHG8%i}+>Mc7 R@n/g?);I^s9 P<8 H&ˮU$u$ RFa|S RǶvރv$`^rf0Ahf;s¯*K}ƺ仯z0kcYO0N@ca 7Άs3MrsA&k}]%rBfxaAc.͉s0`Q(~Kb-Ivі%-@XbڳbQMF.d)y<:c g9sĬk*}m;CI9aLPe S;(!ww2z9 ޥ-Z-$$̾YFLi|H}Lo>馡y iav5 θ&JZi"*~C)wxΧRm$m6{6΍CؠJMBVةiZu!҆+͸:)/˱BYL?d%|0l )`I#.1NpᏕՄS:P=6.[Eк36@a ɸ"9[#(9b;tnJ UEiE>fGOZf\6)w ]@Msk]ͧs96ld -2ZuT rͨU6;NPUPMUŀ.~#WL^@'| NNh6&KHja8r5\fG@z.ASBf%UR lF1qGTaַLToYo=cIJ9F*/ÿ!YDŽ_ҵ&/ܚg219^ g!$FuD%YXWD `MPAٽʰ|lrB"~h..吰P=G/]"AM)V?Y]ұEhs' kW:C7 Q%9x1-;@ySb _P :ujSkMg8>A(|Z8lG+B-U RD#%H,d֎W;_PHv[ujٌѡi/*kM ѻYA0Wj-5gY0 to:T#8osV#XJP9o =3mb)fҙUh,zGtDGfe&j#r.MZ6#U -t-njȍ?*Z6_]A<(JkX)yᰌ:8q&?,9Ƀ/3eԢ,J Fv@.9&CV>E8U>KV=iw_A ^ j⡪J4(`.m>f}*qCYOϼ$>O~DdgG_ PAv6,y RC{|AV-H Yh/3Rb7a߁" wchGV9ڀKy{)v/XSY,_Ku?lY[Vkח+7l%~2͌;m&)$tS%>+ݧ?ֆe"#23vMuq}o%,vXl[h޶{dc7?*:}KY^k KQ95]\uR~U(cիL԰}TXl y&={a̟$~S%@lC CC )ͺs97fȉg)kJe 4*#]y;([l^w}^㷞,HR-JJ$x*%/.s pr#DBx])x i) ͨ]`jaNi3ӎnkؾ78shn)КWQinec+CjU~pn?k/Y7/9 z.tuyʕ@bL#<l8}#W86ndC% (L{ƾ1z6W x Z4uZȩ6c*˃l'F^z?T uƅN2 1F)n1_zx`81ÓPe*F{lmXQ- j=l4;rK%' ;'>QG{0W:c+ ِn+ T,\\nڃS|]֩?Hȅ ^gI``mE'_J/a%6h chW.(B,yM[#BV٪C%WZG2VL a&Yjw23 R4M-a+j7QWvA%-GEr,JX@TBXե?*q|Է=O۱QY")&vU;Lo/W_,m6dKQۯlF]0ؕd.#4JDó8y-o^a:2'`]*rJUSaw4ֹ&tF#翁nja 呯Ln4848ЙvR4ucsN/4OgA] 0؉܂l߯{Aq]Eu8`z켇ڙz/iuϪQ:ѸDKg= x\@G1 мfgxٌSVWRSکv߾p-#i/q`.1o,v;z|iL+R60@qYAX<5KZVx {xsǬJ!a80~Mj56~q@OZ 71:XDO 1I?HV^v4J$ cêS6諊`8C0:kX7m_eA b" AO 8ڷ<ƹ,[娨U>6GFclGsiv2OlF溺E\ '$ Uk-5`/2{gLVLpNtx=7j9M2S5ڐHWv<3 U5;tj8[f~`i_%3O^e"UlQdt@A 8Ǭ/3Gnd r)Qp^j[8mj"FL_[4]?GAERtjrݱX)*x;gL5Ҍڒj8T;f% RHVo/>}uWҭԽJb^vO_W&n\S?=Iʏ03'i3ڢ]j{l=aZ>/w h@Uz~4f;_3[,]}"ȪW8?dsBxut f(HQt {otqj.UwFD\MkAW7?.ɔ26s $sR2~+w%bгnGRZ2@QL'&shhb->稳:ȉ }R`WfMUM: ?#hWk5ѭ{oK>xZ>lE>Z{:p$#<ͦ(q*ѫ*7~3 )p̪ͦ%яpKc55NΰlAj`'ɌIj$ 80Z?W2I,F132nt|R3<"B .!C%`к}CH&WDx6 Evxo3h7\SbVWr=ś FgݛlC8^$2lBY;8e .5sLA7Ayqjhj3?Ap^LFB,bf3NWPgo*AA B/Uj2^3%.rE0p7LRJA+ b# yȖj+f1ZAIx$]Zki6UZ t*ưZ63MUC1 KS\a<`XqfoTc>3zp\~|ZKNҪ ,9Z'-jQ|UmytIFcz67v%sĕ ʽy{WF4]nuB f{X)֋C=6׮e %+JWSH4V  v^z 2{cݲ (@.0U97*^*ԔOh1[6:ā)1]=( `qاVg}CdD>LW@k$7!AFF TFmV>̦HI}{LmuTٗw+6w6½llspj>.I#!ϰ[@N"@ἤJE}ūC<$xnK;E~U7sۛ=$AytW5=5bбO:TڏF6Arܫ }q^Î: w`M# kZr6&"[dmcC2)ǻH4g*\1pӌ1/nH53T렁Sx<( KeLX 8Zሚ[!%q恱3dPUXKxI0 E㶠CTl'|NG+|[BӛFPy#l#rW7tE[Q Ū1@۠,2Ĵxg+iLti(Bb$gևk M8F'AfE4鷟OAꊃ~t6_ٍk;ךf4en-aaPKǐnedua x`@$d#|F@{98;;݄ A{K@rP<3Iw\iV%kVuw~W*f2*Nt^:H0 ; ks0ZYoq}*ccѣJ4{7ާ׿_`TTz)_&,zzxu2Y*1Iga6a5|O 贏C6ep_0KOiI&ip{]G('fR.х# p-t)C_gd4l4}H;Cͨoyi~eO;r]F@_ tpSC?<.&M9@byBzUGМPHEht2&h`UN1Thy /(1htB:&p6Y1EJrŠBr#Y)f~v&.Qʼn즋7cRO&ʲEwwc|랃WNBMu,Zݓ8 %F}ݠUNGGgl~͝jchp7po,_Q^ҧ( |fUo0%LDv/*3늋rW-['m"I(H r[4"FgLAЛ5о5{ dGj^ -M·)؀(g,m@c{JeB W؈;Rco (.Vpwy#$! >vV +/PS®Aht)Krѵ"VBc JM3< PuΆ- RmU|bGq?U~p9 {_IgԹS4G׆KWv=yT25Qy.oNV-F"3} 2QN^Co*NzVo1,NWW}*&RND <`wSxErfK1ڗ52UJDI/VE!3g;vþXs\; qNDYC29Ɍ-BPB !ʝ6OXzMdNk48`)X Dxc&bE Դ+u7K79R6n J􌆅 VL0O 8gG F@kR20#nu""\WŴD4&#i;p}t5XrӼIUmQ&K@ A%ȨR̰|Zü2_dVvDY-ۦ;ͅsrMvX-7پ(YM] "1y{6"/彃W<.NV2̙|orvkJֵiN!ֆLY7'i+Hw \HK懚5zrKW8%V°b# IC-C2c]7aub]AQqie=zϩ"9Aoo;r]E3RHq izM|?I;]EvuJ˞]u1lm-}^^zb-ˬwdw;tG-⧬6*Y%5EZ A/N[dOX"9|j|5FHu:hLT.Meq5ҤEe2)n|1{ݏ|TW0cpJhޱ)~o%^ݼ&|@F,,/Vw#jTyL׭{yN`سn<ڈ߬Gكf\gNSs=0'."$Ge%ulw\9VdaA|nX"VKu3'o^bmk򬠕mڤwiuR0C:9P zx԰^R~MD^l>]({.<^cL7Q_tXv|6#[-V /}{Śe]ZFNQL>m%рb ė|`8O / %U \4)$09uOq?MrfW̗BOJ9 9L鏅aom]LmӦ WzVB,.TphXQV XFx#(+1 ueUڢyRP`vV]-Vh|^<+#Gm$]w1{05L رN"?*?]z<It#l}L=[?[`eȸ3 6C}$Wi< p+ѿߎ'P25:o[Z wQAtԏxԁn4#NjōZn n4҉POub,K ǵ` x'Y+:8悲'#I@ ܗ'2Ģ Ft@gh`&"4qvތ@2eyab٠LI O^]Bhe/ҁ`tbLj G1Qdqm ne{-Z'w;1O9çWNf>9;rXbYUY RAr9sZ%8Eh@FcLkEm-.MʤWٸNvNjݪB@ VTY|ߞ+"C#K8BnZy:tbR)V`g}mg $Sp~mY1 0ۗni:Ӣ-FB p <Ͼ,yM15D֮כ7XzjkW[Q Gꑔvwɩ*ɣL6 ٵ0}|mur~A#md) 5ԟ#oZKEE cm޻yq eޚ枤֗M-a:B \5ꋧjcLGA /@JhMdQl0t!)SPذdѩ /,qA`[(ם,m4Һi6oN}wrVx,Wwyfa,(c1js/ߪ ,z}zQeT~?<Ɔ8mC'(~A TRO%T#62wK͎QM9s /L I^Y[xXp MK;)Y[uKةKڳ'Yʒ'kԷ̶ѯ6A )&t?IXzs!ZJ;ŤR}ly EE/_M3k"C: ~$@jv:7 mKX=phD`qꪀMO#Q.,t FQ0 @pD 6JUYW1e%ގWFeiO9y"kّXZV-xAGm^J=Sm`@1V| K+.)"Ơċ6Z";6~2kk*.ٛM,TF)m/*8K: oY9׌q<(}=m ȗ>0: = ?M8N+7G0DŽ[N3;`x>%σ(D&kJĭ<ԃDÆdC3TT7]lh3g~/lSH R<#=S`YHx+K<42$짗N"y,3.T^cxW r'6L8 I/@j mR zG;s8әr>`$74fO& ppd#(tMWb'Wy5,T!s]LHW& \ PxltE+I8%S:ˈ67ah2Qߦ RM0sR@p0ie$ # wU_`s-:=՘ K|BtU O)^ȠPm!`UYG5=uq]^^6/0G8 /4QS%_o%Ƚ"S8%OXs';N&S esGK[L?KV~G9)@j$idU6Fa/ZqǠC:YpQ*8Q ,tT 8ҡ~/F*`%o400J$ FCB':`,d=s(u&k1n(dĒS?yk䒪"FLvʊBRLihʦ%NDh$X5&ff癹l׹cr(vA;[p$P#ҙNK%Xtں~%1|D"|df:'JRìgXR*,t<@)*OuN9Q @7*GDO#*D7]OvjiV $ټǬvIYfi馅OQpRY| /LS_VR"KGUc@ۀ5 lB*de?iY:^Ypc'(i'ޅx^!ǩЪuqENcD#Jf^!__D|qr\oVCk~!\ Eu:IPDYZoXr,0|x$-,7MR/721n s*%/!Hx7G1=|4PۄY|5XJ`ja#3,44GC8++{Ͽzxz5%S8xbx)mZZlLbUKhK|wu&΁Mv0P D?7&5gQ,, c8}ZkmRH2}s0NH>_+A\ʵxC83oWpRw8裖DŲq8`!!; m|4}~-*A;KMLSk0?ܗc_y=,&-{jeMX Ka`跟}b}";{@*W UtwĤ|:߸rs YB!-feUs7dR;X=ޱzW,G Gu/O1"S|YfzSF4XDQ4sIRp@,^Ƶ?L/2)߹..)72nf0{H{'_*6:`1D!CSF솼 mV$Ġ]ZtAN*>Rz;O»@m? [iYPIML*([ʊ 3I݄l#r6JD6f ԙL6XLM>I+  `s&+|5yT+.TE!aK5L͖,kN2r)N0oHv~[$Tԡ.̺M22P[En&>=6%T\h/>.8pyf{?-jhx֟&4N gŖE0L L!-H/K˟;QԳ(* !xITG,x)<60poP#.[7 =xg8(dT{í9&3AIIN^A!5ͬ1Z l RMѪ;Vގ,A9ZKyi+ן).qNPjc+M@7K*uiJI-޿#$ZMh[&Urx UŪj!z?3V[S!ӡISP?zc~w7AD7o<_nD>SN&~RT BwB 15ߣ6hTA1Vp܁ѻ{#Bs d@aH/cs|a5=Ɇ3ĽyF?e7xn*[PI CkkNIr3B5\D Gp2:GW"j͒:b |D'┎e$zM6u鄊|RzϓMvx}Up&Yo=dvZ-yf>]YVz s[ns*WZzyVO%nD_5u:M= GBRJ5p4ZXTef54TƔقZ=ZhR7/GW*MS]Li}rcE2 I8=Z-.a#J=p,,94H>Zn%==_/ 4qr]kiыzhǻ*i%Ein%Ҭ-زrc% fme($OeUS"0b)x-1 ,ELVh<jZ_Ý̴3}2Vaۭ_4\ Q׀m}ۀM'hCԟŽ\^™8?q,w2 rg鵶B}?^ 3XS j>4܏{~˫)z'Wڄ#Sr9aFgZe c|(55jd#Qo@dX A@r)*:Y(8 [Yo& Dнz&e@K`4BpWr+>,*iTHD^˝ Z149%HY? F3 A(XKxs"SaM~^ɥ]UrNcAI[ ht'Q#=t!NMh=wC?{w70~Ӄ/z/K{`{u޳ߞ |u@^yؠ߃zK<~bou8Dzho/v׿~u?+aohe׽GMh ?_v_v^`__^x+7zbw׺lݟ+ra1_ ==4yC/t!+{PԞ5"Pvlo:f̾~?@IIr;|ۭo[_/= . f( z6Vg0WtӜ).!Vʆa//^nJUdT&Bvl(q s#lYde(;L)Op!; Þ O~۽|*sQ!:FOoUoK;3N8:U.f{^`f 6hm|%q%}3HIb\~.^퍢ۏөH•4@ia&ves"Ρy2۸Ye㤈\7u렌Ȣ̧4]|эI&k9SUQσn "k78{w #pR%V)uF츮n J&uMYVV" d:\T_r!O{M!KE~C\V/GQ -*@$SUX3Eh6~O8P۸&:Eg]ݠWd8; /{FУM&Q$'uG8Θ 6Pa[kom|g,7{]8&Gx=?9#T2 ^2VFƣ AqC,`SfE=j(y1xJ;ww^۽ڗ$ђA4㶴ދAdN\DjfdSBeJ0>P ꊀU _a_v\O4Dj܀߻pA,'.7% m(kQ,)P>~_w_R]P ?19{eC1d<`}EA]W.K @܂emx5aUO=?>)eHl\+/w=LYȀ4R;6\}ow";=*L9%W(PG ́,>j)v`JI^q'Tώ/{EUupe 6`7axm]gG7ZG2'-Kc dzNq8e^eL#O'So ӌCb ؁ “$HՌ Ǡp4VP"Rvsf FcP[E RV#ضtϻ$_f4e{`:e)-IV:PIEMLNM4:^aa.q0tMsuTn9>0?`x޵pf5*V2[<9p2 7N6ʩXPs{ϫuniR>P:U[xQD\UVO2 hz[#AHJDVf^Qʠi3UU7& [88?n/UyRL@rˑOG-Ŕ49y c5"K6H ږp{ͧkBlU,Qu.g+]ē"\Z[/jmvwQkfc6Σ֍Z,&}-˘ժe55<Rwl_Dt>7j@EJe7G,WmU?oTݎEȾ)ӡJOĔT+ho Z8![+c=βc XQTg$Y P*G~X/ 4^t8\:K{dL7iTa^{J^(]:ҖjEbwYŮY']..¿U19 bweZnj{͊M[m5?OV?y1lE{=e*0+<̳'h!t1a# Zifg6$zdAB !忮eSƩUF=DA)1( !|s'SE"O>6>yOqcO%Vsɭw=z YN׮U ϡT(H@XUD"K% q SjN,I\QY}*ռ2r& k+.^6=t V= BqrVP:0F|u"6׆s|"2eQ?Yt+htc*K&lK$PQnv*Eg^FֵzwoEY^ZCDc`TGg` b9Tp~9%̬^|M(#S2еIW#?,JJAYMO@I^r~!'t CQ{p\*R78ZG3Rg"6d {BEu&dakB57Q쒎,:t4BuN"廗窀VJ-|U>*# q M0*o^.j]ٓftJR+*֠qAЌŽ]˵+u`Tr %5rNozqb&Xp ؄g0N/A mm ^s<:-jWq:kvƋqH.Ju6P`TP 0ޏaUMOPA^ %*ɹY5*ه`KU65Rʝrm5E'~I{nڧzg=?cx>Uކ:=T l>?*3^ݸyJhfaAԎrj ٢qI$Fs5X½|%Kq4~|^՛RpIkxsYkvvy/Z?$q0dܡ]r`'Ζ\9i&O ϷaIK\[:|S=DZan^i/@j=޾n pveiFǐ \˗-L(8% LMJ:!U*Y?>X_#ژ#jtBI0;j˞heOB'Q ~sѯ{?nkjeA.-V"ppBf7e+ rL>} Ƹ0^}sGv's0L7܉V\ :F!>@owƣSZZ3Vpq7Vh fM)fqj~|iᗟKfc\ܛ/ |E3ŜVdidN0r~=thwX1%X+yA '75` `Y8W+?}₀&ˀt6v0_!S.XeD=&wk侽 e@O/(fM,ie*-adL㰢4xTmn#j?=BSNFZ|: l ij(:$${MhпGW;(?ǂ Of![x~r71Al]C5f\dhFެծգii&\m>rst=BH6#$E4ޝ4wOV|r`0>!k-˩޲|W  Jy'z!kAT+Qfi֡y]C7OuLP;[Pn~@NdjWLW(T*^%f( >&Z6ɲt"Hʅ߰UZ5-|ϗbWGܦt.-Ne^Q$EDCY3!F,TL=՗@ML]=.q㳶2k{Mu\n⏟bkiu5cl/4yC L$x0*ւS4h'E;,;j6vU,tÒD^ d|RL^YU"ԾX܁Ԟ`:7S~pI NYыFϟf]gX } 6Ǝ&=O#zk"(YUgѭe6N< +{mw}gg ^8ғuTu/׎x/ZItmQ(cаWav#]íCKtYH! `;F|fwy QfIAd>}ggVw"2{)3ә2(2e(Kk=:C &I0D]S[ Nd(j㵶 %EEg!v|8هu#f;Z-Ь<$Rn"]VqjU(׽Num8RޜF^7{S:KO7ora nc F/}E7$K,) Lo|+nxـmހAF_ыnM|+@K" q< dd$Sd%E'xX4L˖Ma^jH=E8DR^0ot:ycu!b41w:-!F}yLP$.W Yy` ' РZ ݁!VTBw{τli VS)I~싻 2Ikl3IJIc.F@1ei"=Ř $VjsyfRk,*%OOk|qs:g.s{rlw2/}X žSb%F$ /~\ez0,~}7Xԭ,q[F,u㳚.Js*׊R0ٓs2 b|L}I }OkbBR@aSZ3O4CK\[#>sia e㝇Q,(asgf9fzi;>nj c ؃vׇ,AH[pxP6і(孅>{VJQ^( y%FE|yN]lKOg'c@zKO Cx9bޡZ Ƥ!Grna+ (mLk_@1 %ij2Z\m{35&r2(!) MSZ! _ ?rᰆ2{^ <wgĶk:NЃo-#蒊ST EUjˣ#kKt40HՐ_=(]jihvv=3\r X@VJaEpa,#!ڃWůůZZR/}Ύsȥ|:p- Gjk 4n1m/"U@K+Z[°)Gl;de0+5%vv`mԶԃBPm 0 *pc@5GU=}I=o}yW>o3:,FK] ġ-:&|ˤDZ#Rqs?RIX(G+l$"8`o@ECx|~K?|R{:t.Ȧ x|NGewɐh4J&oM$ޞpYZ!Q`|KZnt UOOib)%,f1P:= ~ge0F{NG\ELt6X>i+qAֿ~GHAXBui"Tbyi|)$u]Γʵ\\7NѰwQ9DF/ O0 =,LuI8 -7 CAMӁlj M2"WOQgCލQ@fE [EN2~q0{#xy`W{ICGM=w8CF.)Hs:#7Y2풻M{X sic>}/Me^aҩ} 7۳,Y~UL>))5eZ[ȅn:n+?lp ї"+Y3-J"]5 ]ionHݼwgI/t9lw8o>,ߦ~7MCZuI74XyMm!aevf 8K"B/AJ>Ս[B}?ao6Mݵ CuD1er7Y|^v,L"(۠~ e1`bZ FWB:-xu%J8bKb#tq_5yT% *0/{r:lf+ouJ$ƨ" (H.~bDш@{4&۹8`R<(|v\n GZIYmh6Q-M/W%ՉYdUPn4Y])"Ÿ$.ZZ _{ȆhGrY8(S !ʚ?Q8av6í~?Miupxw}9oAa?'S jF=Fk a@ |,Jr ~S^K)DpyNY `luK(j6C?ꌟ~zi꜡d iw*]Le\њm$)7lO]MQ.N+2+Q 'J\LB&Glur [i2AUEԿs\fMБb r^"{ P^+2I*FQ,C(8x? ZxNzJ>렚G4FG{|.݌ gW@߭@ 2_JIB 'j8~$e4.xplrJ:AZ4cf!ՆP 8CcI9A/R&LN%3J6aJքRNNELM"ǜ#B *}b')њ4",hv!^]gpk Mf|_ cD2C2XCF4}rzly6Vߚ^9WAb/ҡh6MXF焩Oo؜kۀ 8@%ɒ͢S{YӚPAxE>TA [th+]FWd*TD8.jӯLS+vc+Aj)kx+^L_t虬k06_+GW3::p\b=.-ߠQhW|YM'UC>E5aa 84=xfeZh̆wn[E**/%W&zUAI&w'^VԲ-|j':Q4_BLDʂ.\_ tXLiJޤE8a8rڡ:8{6N)Yx"۪)C?l[5 @cBp4@Gˤn,פbjON~IyWW\BVs^v6J LofBL(-nޙy ~o, Ҵ{1AGYW!C7sNqRΚ0ף$JiM)FPS[q C8'3sO^FaP 2FF֫ծ? 8>8ƇF2%1+'e8RahZ$8/88ISJi^?ae"lj^mguL٪lnhvJ J驊Hf Nf-AnۍȢ~}JjNIureu]&kwUkVe %Q;%RMRt:6o 3'.jnER.RnG^¨֩Tx\ q;s+7\"#=;#1{T&MAጱW//b1N/ lj'Vx8 {\\~l>֤6o^5eQ%l }'ʹ(&5׿&?^7OLʫNטqzL oC*Րr&?X ӭ(:$K95|ʴQjrF\2UC9C^ tNl׭]^u>W9俜L*bW"Mw??Ym›~؜S*S({3OwO}qʫO<0y׮gi(7\{?{'\RLrW͹^;a̜?ƍ4,A5]~,K|W,AK3سdTr' ]jgj!_ƙ,o+Y)>)Mл{pOꊷ.tҽm6I*pCp$]/=.0IDKz+- u5"]҉RŲc8[ISdOI`Ȉ&lnoLQDK$be@ $M2|8_, Oe3@Kp L6n_#-vxP0gq7k]$ FCw7ɲ5WsλflbhHPZI 0,_Tt KDaV?'!]͓ٓ.$k#c6}F*Ohh\ź`>LT fS!w>тf;Z@n=)GGW.t9+'DOdlC[ `% xl*i/RhgM$U{|! N'J?*`cM{C"912{3ks3,?gBElWó7{2\u.X;.|>,t~C Z"fnGCcpjE M>͖['jtȏ)(E_# Gwk N#g-}!`Icvt!r'&)p/J +{RSr :i+OX6^@6;c +2DuH (Hwd`T "1΀Fߵ2]O£wmzqV77k:oCmIIЎ_kiتUd"KWS4¥]1T "yjWaBWM5.BLRbn(B~_MP7Bˎ2G MKl^=KX5f/!%&yF/OIwduT:5dkoS'qT- _2c)&Ј)Wxbf> ~)E~CM܂l&bgЊwi*Eh 胂U@ɰ= aFx7Óh-JC hy`@Mu`QUBfˊQ5꾖FA5(=-Cj)ou]n=k R$w;:1_⯙S?Gm>3Ԫ͇Et>ۥ{1,*DR 8mC PjT}V4gg XÛ&Tɗ~0'&1FS[aK)MEZe^n>hϗcQwf):J:R;qIeϮ|㽘(_߆*s`.!D<&f=ʳ+v٫;OP)t?eɳ6!wXʦPEDMpc tYpt=z M{N'R_`{1opW[^,2e+Q3ڐ7s8Ϧ'߫%C3~YCŗG/uK/܉';,cd$9|8t;ePdsѢ#cHEuQO%KmogcJa'ݍ(y,qKܟD]#`]QY~_e^[du[kI&3v soK j|<+г5k4îֽ+üz4 /z# zĽ2f8hLG]g„]唯AœWBlM{`zDDHI ZPzC@ƎywrRW^֥.μ%f '&X}x;b.Z9Y\7d&F{8+fD%BPi_}@!*8ޮ`Tvq^.jT+ȗǠ C$)p8B N/yC&%ԗ 0WPHh+LyJyRNQ&FFy@=s݋7+JF'LM褳A1N:Ѕ=w:4}Af Mr!孷fUj%58R^gzxg$u!3gsY:b.Iک$3"eE`?;r{E9ꦀΗ[9Rx\=Sbʮqb]iHӳ+蹘4/ L>^p E(mRD߳|RE8  d\eQbͶF|(w *Qݨ=k9S9+*5hjq{QqIG4(a@9z(IJD5k:gs| |>&en>꺛kd}q B[r"cp Dq%BB-m;˄Rkg7Gꋉ2@VY 'RHT E<<>}qX 20|vrژ?wo`ΐk+y|w{#*с]Vw$u689v)8Nk7kl ΃_Dv  "Mpʜw 5_GcA|} Q|7B$"2D1 SP-*+Sp89OYCRV&lR>8"|IʝT´6txjR:҃ShxW^6ŔKr]^-uY6 4@jm"r1Sهz[a-:ʠwρ94i;+6(٥8|q/B. y]bT6q%[ȁv͕SgT1URiaMs#`@Ý3zxp7Tr~03o`:ƌa(sa0([ʼ ,*d |{Р2ED59NTz|.-FÃPj`c&8CM*!|qI%ecMv(WDRRr?p{gg.LK#W惣=4r/#ڊy{&ÉJzC˝9P/2UEL\L66kCi],zmIu9_K`5KjEAP ^zZD*.e ^_|EQ4Iq4dcac _-͌ T}udOg9J-zyAJa}5U3I9Cnp845%.!t7+'/&ͦS(jsNbB\)WѕZ])Xٓ쇘ʼnq'9!]= 2eLYlӇx:$uDn MUp6Jmg* ™b"j$#Vׂ܉!w1ϱ97^ t_Ѭ٫UG^`t G; ہ6rtN|ǯg/ի  9Ԟn?m3'('!CDMac 5d髿 B@]I `ahCTzlxy8_3~AI,S{RVm2m^MXc.$/7W g{E~w潦e9\"AXY|`l뗅BP*{6[κ=;{#%ϸ@MW|=-ye/Dq u&,X 1+yO ?A;=CcbQdz^R!Op/BYviŠ@ %Sc#MsULQo]GKԧ|ylyCS!<#n&4)J@L f'zFyЍAN 񌭣ɦɿW A@| fl!>]؟G4 6}<k0b.Xg:ph.1"_>d11%[$k4:"KAb\KS2b[i!8ka}9Ro*Ec,T u VaiȀnkm W5 ʚbFD&iczQ6rv5G F:a/_*Ŵha@yȒO.Cx\\mDy A&B%JA3˂YzvBʫpQzJFHq[:o7:,س$fͣ>A^">P[CFu ҥ,C,%Ȩo2*a7!tg)˰Ww1Qɾvp A'醐N iÃZD@JS{ӵ7L҅:ޔYe?Z /N:jPL=(Y3MTݺ[-U|p,hIߘÐ1EWh[hI&.V鴋B]I8kvZjuZU4V URjLnO* .BN0#8xHKU:3״cm>|qbH?[)BlM$gBiG6'vdp4-Vo1?Ui8RH]p?蟦î@H6"ņ '? |6%>.Pڥ :p֑k^dxEK/f$zw4F (]g|ZU {g\T(~M3-su<H+n7?2Z6_aڞ*g0;ojqv`YΛw͏*zFi(Xf*y(q6`ævH?ENn=Pt~}G ?<ظ8{|zIՕKGc6S*Xmw&Ywd?x-~pg(܎eu~8pI|8Z}/xz7<;Lvo*W=]Gܡ#3gd%-2f==%<8=ـUx;S^%8J ̝*4=h"caĊ窢CCCUF:sjwnd4Ať _ /M{\5iAunh* }" e[oP}zThtoz&Pq- HANAa01kd`ٹe^ڼ]f6őiq߁q %a˖d$ e2[# ,022S00e1mfQ)EM Rv7,04Zl87m _&HPtZV^TL%R .;yy]{9>T5$֠wL \E1@YY(e(W?kAΫْ)Y JJ:/TJ+%(#6#V&IdRfAR3)L  FO7=XtSQkjոm.fJoh -CZߐ60 iNܐvaH40\>=yzz鵍=hjm\aja0!oH҆4rnH0]^i.56uK[^Z$@*Ioi=yA:M}q|(ozI??s6 ΦwxY6j+]9ݹBkk2ǟ^M&'9;>vIZ&KgqFcSHn~/+c =QFvβk_}m8xʺWѥ]<.se1^|OS<7\~~o ^`l_C_|Ey~SPE|Ғi1ώcI" @R@UXsPoy"1mW8vpD uonJ7 Zn|̊^cZ 7Wz$5 &6"R*2>H~4[4^ǸUXw^i ‡b2.l4,z(nIKv'ܗ°֨omڱ} 'B9Jo qgyP!15}Djַ93t(ـ$y|"]m)E ?[1(clc(ֳ"X>Pyw͏hߚb9Rj7`9&=toJet3֛z6;-4d~*iO,ycط6xJ(1҃#r:Ձ1n)ȧ2{itjT!`ߪp(Yfקjvbj$`\ ŞBK`ҼB92k63ڇk2{k͵*G|:)*GgU<WZ7E TLlz8PrzjvӾ~ lߖ*?joeޏ'.VeO˼'jbZE*:|@|oP%pF5\_KpU6v*ٕUu :52$'z@r@Vi%AR-)AMl.b=c`Z}uSf$Y`L dZ2y}& ӸuFv @̓ۃQӀ>S߽x15OoK8kB&q/&!|E~PgoEg:ؚ1籊o8>\RϣX!©& +uwYDN0j*S[vkԥk<9A6]vehRR30U$Uwx5Nz~"@Bq7اˊ mb-dT=:b?e j =;mTv(WP#i"N*6е[&i[l ۍ5w}b⦐0z;펔ڪP^5[nk&`z`j޽VV{A- wkpV02Z_b۔5 pd-uu}£v_I޷IgC/{4}q`h"I e<%y]^~_KN|&|>6K%[3Z1ڌ.l3{o9'l8&+.dnSDV'='=ߗK{@T ER`3 1_Wu4KbNpp.iZLLT'KM]5L6_s2Y*%/4R&ْI'<;b1YZȟ 5FrIjOAX$Ż(R:^ϞDc8dwV;JP 3fIbq(u|#MW%j8_=5ۅ2DVUC"X(*&Q`{Q&c 2u]{ͥ_GH Y?|f 5RZt߸P#zI8W$0~&ȈCKDhq!xUNϝy)efe߂;%[_6@7[:Y')؍q,* ?#P/1}EYE>Ud 9{ޣVe tշ8& |2&|UpQy,s n-Ћmop/d/=w[ڙ,VdOks@N8 .ݖ({r8IίzG}qQ0L=O){Lx1)Rq`>j@,a:}; nF4vR݂''@+.V(fc5Gs5&X*(kZw"*!cܙm2S)z :5JxS @hW`?yVO!3~gȌd$Y8%wNPLJҰr<خ Sj Y<.zy߲ߝ;-}!~~.m7h@ ~>gA:c{΀ɭYӍ|AMVS&rӳ =6Ko ƆAʘ9fN0 6,BHêumι%Pn8w=} ~og.(56e[ϻ*v (`XЅ(m7^ zPNH >EK6}B[p ԉo|U( {d C; 5B+%+  d"axCgws8}CQb3O6X1dY XEV2 8)]fQG7|:ݏq. @Ϋ]_([cKAZF$Cח(;zz$T<ηqغ=; О3!K L>Rn%&rr?w7x=g`o":R%T[)rQ=d90Fԏ.J / H)aUȅ"!Bz{ 쯘1wF#`czIT_RA+#4hܖdH6ӯ?";f65^ܐ2>BoQyIMxM D#s~ĤsՇ ]/| r2k8LYZmL I6bjl&W&Uc4r<3+zDl3!)&5&xUݮ< F̐j21[FJ 9rn*EleY '7v{)瓕]G%q{ Ix]Ѝ&@HZm^wŧҊq<4g:S?|~BDxz~Dsl"/Ӥÿr!yn,p* DJ_;`@ʋiУ HVW׏}ܒ(V۹0">w|ΧTӹ?;zeo )X'G8_)[678ꟻjOO11GrJŹuDhrw~nžGyv)(EZGy6n2 8#d==鿽\-yAI'W8S7r!bDk;ƹ\HGbƱ#\2|Xk'>ʗ,AATYPN*d;|"9}f,=0Yz_tS?xgjJ+/Oڨt鿜}?k2OeELprw Z>yvʾ쏷b 7, p7,NÛ=X<|B Jdǜa أ!6h TTK;x;`1{ěK^9: 2ڡSB+ڳ?~ <6[8'>$ %t YpXy8mR|-1VnJzt49ڡQ:փPM f%ڍԳ (cxTg95J}Lc^IŲ=PБ;Mc~}dN*m`ǐs##Ai3FnL֩LAh\J칞n4lĽ溊 ê1Ԫ>-Yb}wF-dB R}ϹRf/;~JqqR4gfMy:4P5SCA(Ԟ?Cz\Y>?f A6-)GDްZ̸Ϊq2]uj)(׈$T37\v6 }q&pS7B9݂F{xp: +̹~vm__] KLQyu95d?-M8i??ʃ|t(3`yǏ1 Mm (zw{ݺ|8]w!]r:,x3Z(8eCޗa =g֌73pg&buXavtY;trWjQS,W _ONLm ;eDr'G|?q.?6>7QOϣ=eG_i<10x,ű?=er69K=L!zx- i-t/;|2¢^e׉X+:z6]oP#5Gy+?n /|b :gfb c!F'ssLiϣ<Ǒ;>7IO#>U}8OӮi첛q6GOOz5xq4Փ:j(: rkpƷ:s-ث-f)If`i?`g{?ws?J .Q](Yg߾K)oъ?s`7 2 3 />N H.qdlN!.SwHc}uR!{1 ]׹`ks;I FXVg?W[5B ۹ Ru#'7&prڡ.@^^djτ܍\Tv0LΟ<Σ[:zY?6NYzзf0_{8v%KAz Uo=5HQD 3"L>7Ov>T<ʣ7xRS#p7~zQgľA731yK/.p`!nwD=@x =qG$QLp2ǘc^;,j;"քASQ%^I|MgM?vs'Ie?BQYgJR{_\ʹf؈!Æoݕ_ cßOeh֢0} jN FV]_OȐ.\q%=/'ՒEz>`@MPr+¨a_u>(lT1)f_6xJs6S fҾ 5ytw!DETk'$a(ާ`( EH:컞/>`̎,T|l8t6w|p)Ml=;MvxH Nx'9b*9rӱ(u#)fOahg2"S eh_ڐ Az8`i}xzƤ!CV̟gH.ؗL ;Z;svdA5zBH5 *F7kh`g"y|M X 52 +mra,{fWs'7橲{ =WIkO>)ki(߸ [- oU'SBc*J-bOO)7>|爯&:Ic韊?F@;R?O7z:({ ?%_9 Q"Ovɚ\7?J{ç<ϧ @iSGy'=?qS?HK9\ 4o\}zT˼Ā)~8S46hI~kO}%(l^II?!l-?cw9n0(OEzo9lgS;s,No8wtngZ?j2}g.Id6NphV 7Xn~+x.icn~wt`F!߾~ƿ߿~3ɽJn0fyevR]A+fc{_}Q 1w7쀳rzv:+gC)|dw\Xj7)ȟ7kg,!\-A@ϖeoe&(]/9qH%%5tR(MJE%z+` \TbrFIdVH I2l}>yR'9ƇU{st ?ǃ]`OH)gJiC&71VdHI*`Cl1\$Ępj.(BJUWYI x Y i2ySMvPMC' ;ҝ4*6b\a{Pof\DR۫ힴ"*Ӏߚ@EyN_R-p؝ZN `'`k{feGO4-/PŴ_~F*~S4R@P]:Aˊ!kr<{Ɖ1XfO((W! F0x h¿'cCa"F%1wC ՟COVDGYbzPZRx[;]jcv#ݘ| -cX7Eetr lŔXWW\UR#Wz' vIm1BO0` `1Zy-#p*T(iLfO~~մf j'p%\p*h%3^.ŵ?bT]sbrM]J*4+UMuFKAC-)+4A-c b?] 0ҙCRfSq*x*TQD1d +lӎc%KbD.#gu;H]״?p7NFd0-X/yW/}"DR/ݮloh mPbt[qr}CP@"ѕ ࿡7,)Q@am FQA6gO 6r6xG03K\bcH˗mjjO}H%1㕹U#;Ʃ)QlPӉ*ݡ˯V^JFf F( '5*zp:NDh_m ?)PΈ% -δP$M>,(7^vCIԊsLlT^?nw(ٯL TWΌ|~%rZ0[p~SUǘ;FX$BUљ[7[mNM/eE{v>Օ(K@'w̑؍ch Ћӛ9Q_"W˙(pfzod1L1bxo%~86(Uh^8J*@.6X'qZmB?7L#H*eH.e3K ]>B+WT66_bK6dpʩ'!Ϙrm܄~oƂ*Y0@v0w$BCQmLի)#h7`DcY-!m#LhՅWJ+ZJ;jx{nhd[w w 'KRZ?+x~t< l$D&=G\G ,JfQ j PgW4wkWnj\>u>#{.LVv@ Ó%}Jm˩rt}vzzyJ⿵%خ4tW+ U啊|fe7B1FTx|/]%}0U9kEV%[fs} ?Q21: L1e9:~[yygqTŹ^yu3<ʗۡZ7x_ DvCgF}^Cx֋0dOtXs C!BqVbo$Đ@֖t.zu1Ϗ0iZkZ+Sgń8D1+D8x;'J _ʌ$*VAzgS0Z:."Ή": ȟLgZ oԒ&>w(BK.AuD4OCI'4d By&uS je!bR,K"S [Z3C/_EӘTAMWA7I,PK@'/,Orș71'wT7~,q7YF/OXVi}$Ӷ ;~7qw'jh2u{,j%Og!W6 ԋD ]k|q#E3hXh%wHZv3}c X2g1n T{JZ2L]7ؿoAK_]Re:Xi>}z&7 웥؇UA_"wե<3c{9_y׮t=&Ec0Et%Fkje5˧ ;Ts~!bSe? FO9PY! ?n4|rܿ&K 4`'W o?_UO~ ֻ&jPT[v_ƔTǫҼlq9ZQZq8-ٻVwݿ 蒊q{;^2: 0"G7YloQFl#/V۬c=CǓūV:ukjli{ʡ2V}fV^BIl59{´ fNyye{3Ooor3 ;Ө@o 2z yYӔ=7샀 ?Ic<sG jhPl敳hjnԸ9.Ѿx9䘕 MI`L9*xLV~˜B+CƀS,E DۤuI9`ZMҾi6S7ى\*VDn$c)U`NS.#T 6Ke DmmGA (y,0܈1KKT!L1er*Yptnn< =f\x;''ÅrƦ :0|f?YRaV-IjU )2-8IM Ơƽ.f..27Hr7&NVE;#b(Fq*U ۃv[5ʀ6 j]1]ٳw*uׂU.+mZ^oQgM.k =8LvTtC )wG:G6qJxjJNi'+fA҇r9SR@,(;sp U'XWKg8FP!XfH0 O%pS1VPd FfB*}#M@X1V&]JQD4#prGalXSϞNݨe\e~QXV͌C`y船JL`q8oT7!1"+ؑ?6P ԍ++9J)t"1tieS*p:nDS 7?;A \@ݑٍ;L̔܆#4hi`£¶JW.LE(qeaʒ |qң֟X+<af{g ʟi 0jq:s9 Mv!)}:vYz>;4ށԕAe6UpPnn1/$`idV `&8)3'avy+2ɷERYmGmZ k0TpuޗW6 dR"K@vL@Ųgx< eI7-!lmCKcbMNW4X #ZhÖ/?I9&V{%I Ix;W+<ֱ{1GB;l<!#WHS4YmH6^0T_=-l6]a5$4گ&">%diC5ĪB^j= [։ylYYR!"x&u r7NVt44$7Akl!#4H09 $g$C#ag}1*sTI'(hgBHvqh 3f$0Ȳt'SB~.eA`(ڌh7Xg;gھv³/*](voYfPqED\^*Ly[o[}cE(mJ LզzߥS&Nxd ,s5p`  }<(y@ 4Df01#ž-oyR к#5cs5sMF͎2/1a7|Z>=y2T<8@$M .WTTqsh/ Jr` ߤ) A\~V,iޡ$C;]n0.ۖ3Xh1x.^.r?Mhrޯ:yzYV:?p;c7zt[,.5u/e] ~iAQ(.srdyGel|Fk?R+ V_+3ք Hs4f{~n>GoydѮEwG)[9 m|d:2ɨ şCT J_ܜj[U06?sCs9CC'\MeF~Bd$PQd8}ZҦ4eIU^rNHxи`B qwLcbJǍ[/CҀl"ޖi~rhXbdrE3NOETˌ)j*ncQ*&_ 1V%{7,Vnawin]>EDKt7NqZ)f)[Ib^eO@SQv F2p wޥ>&%PSm0Exl~bBoOԕ{Ļյj.x3/⧾qdGqoUgLNQ?3|8smimo W7[o})c<K!Hjho#!| Yop[{[|k'4oBԿ5GW<ձg7o%ޖd65/i[X&"6SG?JN0!D B9[>&.hscO?LAn)^ x1M(䬸˃?[7e ?e &tf`#Ջj,Z|wep@Y֛n={'G@<$%dj:dfM{}^3Nd|X*8^ϕNrIi;ZU@==Z2ώx;Nˣ;q-q,TH)jgɯ̲ \G~5  RM4d3Waۿsn< Og6H&0o:?;bcxkO>/Ζ/< ՇB1F- oY;!0pluR| b&׎ pQ_.(=8v E:pO670qٿʤ ~@M K]rO(%\pd7]V'v}n7hN@O 7]36u{\kwBԻrJҾK&{g<URByὼZm5Ft;LWg  m12H[Z3xssӽ(5:g w6hmȢ@t[r$Y_9I;Mg%5kBI EIʎh8or^[Qފۍs68*09Ql;eX$:O9vf@r8˙O$jyqBU+ f *t[~Q= eܰ(%[UY.Wm,ũ-\7`Uoe3k:#d*7!1S8VxVPHstnN.~7!'6@Kְ7΀m|`~UV{ͩڟL+,]9H6ESwμ w_zU 4#Kن=?n б :M^"J3Zt3cH!pc.|5NGw=<_nUx}vMhG8YSlPǁ1%Gِnb>GٖeǓIcѭr[!Ȯm\^,qYhxju%:1f9ű+YQSe=Q? XD i=jK]Yl_FU$h5e9xNX^spv׈i1QP"E J Nk^x&3g:^ch0B\b:8Y9  M{zd϶&l0z8y6KߠԞn?|`$wG䜅T75qgdǦ3>P5}I P͟=gbE6|&3pF$E&kE6+/P z"I;_įNVb*$ ,ŸxP?|_r! /g eAG\„^eEȧ|c|`4 S4>- |&ƎUr  A a?PB;"/]7Xu֙ZS~nBb\5kCt<$ҖYB\qŢ)]Z ߆I@p%X3;q Wv#HY/ 'ߢ[֠-O-UoiZ,lOGzj:mml$,?VzF?7?>vg/W: |?*y{2wikVv0ڬ?kFlPV*NQ)lL|EjjR D}9">D\)ܟR 򁍧DYP>~n's{b2E9JQ2΅xwVt[Q#,yG`)`[^][T|PvE0&"J>Qm嬲U_6X6X6X6X/yUVM׻͖kv,v׺MV &\e*WqUZ*p[Vqq`mhiU[*kU5}UKo( XX-a\OYꊀTN,h\es*4znܟN7w{#G*x{~ݱ }Ȍͤa4k່Y/] qVϸBՁ 'L6쎄v"ҝj(Ʈ5#!AIgTW2[hJl5"]HRUl7=^qaO[\ǐJY"d?4%xBNA_{NU{-69O.#ˋ-u3hAof;3A!W5\+3NB-ŲSFA(_30lBSR`g#AjDlUثj?T1 sw Da}zj!yU -{n 2W}JrP Ge  adϲ2WSR>C$˷/y!U|T ] Wv=j?q^i8Pf>geQ)?K!L=E]QӞ3۳tiR m+Q#ß9ӄTxWoO x2GIz1UeŃಂN8Ndu>IƒT_EQ.sX7&-RWwru%%|rb~2 1,={T77Xu/__ߏ~׿y= .. [x[< 65iԮF 篞+LJ O.:7 /Χ䠈*__'vw׵suie֛giAՅp5OR L""1vvP҄[P cne.~h DmJ;%@ͣ\~\&@j. g++N笲_~1!#񥯅Vn?j0XM5Ȁ=qCߙW6f;9zx2. 9q3(8ǫ3$`u Pup/۟ D ?plʟؔ/DÉ!h/VOxKMswغT&Z_^Gԏjo5&@EC} oH[̈́&t ZUq#*m5 6`SF"`Kr.#(ҪgG}Ŕ&lPC, $Ʃ;zu_ #.~j恿:I2Xg:wvg>yRG?(suxJjzgm- fq/; -_e)Bs- YR:>~T.]w}VOwBK+B] vy q5I eWB&-cxC'- eR; SJ6RY Cxqˊ^J tݍE ژ0&-%y4k.R߉7Л*֩yUZ, V%Oؼ-&:GclnH1/]{ƙ|1\ ^ @۟OdN9H|H?.щL"!EHFpfy{xe=1Ma:LZñ9fW'199|¼qym܅cldc1mb;)0\ȬB#E ՄQʶ y!b!(nk1Nq u-JT]LVh7`%Ptzkgw?t9-rLxL؎.(z7b!B_j,dm&V4NMP% T&8ĂgT5ƷR~8މSUDHLIbR6%K6NTn)/J n0η C5Gr&r]Uk9ⴶ?xZfMXtgD-pn?C'0S"lMJžϊS)j6q\EE:2&=w,&?V3H[ny#tR:aV^* 7FL.S2hދ['nv1E ;"QAvg$81NF,0$;#qO I+bTLJ YܣVA\צL j(uM5Kfl$мzuztZL  E:;?g;g,?G?a`]|̧͙nNV a[A1qCcXBPR8TSm0g0ܲFX' O Ս!SȢ۬&}-1#% pp$ZӟZ,+=Zq/v@$7ÐyB7?sz'p[_S3V웭a²Vڋ>#r"ӗ Ql!|%`lm:0%z)[ ֎\/%O<^iã7dPQ=2ɕM׵ Z(|+A.”#nM/Y03#wqxf9ᝆQz$/*J.BQ2 0<%~Tƭ)Rrc֕䖢龜0n>j3S LQ-禇: \  3 >H0u}I4< v ,,C!X+)glrUqmgc3ܜY9 FVe8ȾJ H=l0I>qa+n"~Ap:R/-1g5Q:[߀_]ǒZ66d$EJDW2~xxDf(v /,.$B}7A…F gjb@XNhD=LZ=u4<3^B;l#8{6ߗ2z@l]2ksrz~P}e)x&/:|Yp|5{UWL0<4ՠ 2 {y9ۋ5DۙdQ?7xz oof*ɰE_89.A7m#L}SCWQq|<3,jXTf}T!1l"6#ٟ"W! @K`+O/ ظv_WVEu&yCrѧ?sdC*TGh/d$L!u?+ZԬڅU;j2ס+ u\klrj&"Y &8J}NN-rK<ྙ_b]FU2 !||]Q{6mxQ6K:=Drz=9mZQnhUtg̔e~ t6nzOZkng"/ ǖu89X,/< |% x:kComT E=Գ8/{}ޘ'C6JB{:{ៃ4T&xʀ1~Qm:K~|m>3N!zGUϰEGX]'g&BBU!+v1Ń]DX<έCjaɠ$-P2ӖSP-<\%z9;B!!HhKxjT_)pAӭD-ݽ}߻rN,KmȲ)v"6O[qh/5V4?|?AQ=ӟ^/:;ha9hB"߳‰8xCġev8vX~K%"y9hM}qusd6e0uRJ"6|6Y XHy]?K*;9)*C|'hrA;ڌâpSժC#b!bTQ%"F֦|GQ9b!-#PB;*@yp{bzA뛜Vu{rr;ܰjPqӗ^{uGTAq''< +D0^iNtrVd@7 '0UiVuY+"jNѨ$W.+Y|,\O!f@+KA=RC[Ӄ+S%J(6|oFkQ+KWobۊ)%@z%p\u_ÐqDoh,G!=mpQ: DBr't>-F`SXS$cedk?~ fgd˳w~a[/<㗐0eP| Yx:n'OZ t*j:bd g;f`iEsW'P|S׀IyȲ?9aC2G\i|2քγ^F1al~a;РpG+,Zz~=ʺ8TbEnY+&UM؛-vs;=5/lie (twvtگ-5m|u<&4uwX4"6l ĉ.|:>>%Hܐ5O & L^9X{_OiV^B]A1K֋8T~t"QV" {ᙱngK<gjpOuY= efB(քfDS HShqbO%H:ro &DgYW10,N@|d_ӿ lTIJqCh]sd]qAh|wqq洕(wfZW0rUTDw =E^\\M pgyŌU&䆕ULͩlKO7E#+, !%9Aea7W6T"{COEc=N; Ql5GQ{>|\vkC2M׿EK)Ao 9&CxOd jgWk텫1q3L GS ֦#h_zOZP^FL'͘Pkpvne~:^YHŽT2d/ZlY B\86q[-$w)~uqmki m Vߺ [Wκn{kb'r2Ye*y=?l^$ 43rȦ#vڙkEmx,B[-YK E۪"}:#WD)=2uz(P|1gr8!(x߬Q^Ԑi 4+&z_pcܨs*>}z~H?Ǩ4$ea>4 H!ј+KNo )c'~h8I7s>vmƘVC{!>pmۀsb9$pZ yDQ0yt)<1@n}]m'jm^PՌf8Qw.=̃uzẝ^E_'jH+@w;O:O@vdŨFʋPOmƝYs}pKl`uu[{1uKS4hN<Ҟ]gYy%$#0z&. Lw{zvH@ŒE<.CNpݑNV'}нB?Õ$ oRGߠ9䳵{x"*BšqX@K?==_|}p!øfIe,zbxPYP(GLl?ud:wvy~m Co{Q)ra;ghHA)-yCCDdjl*oQ.B&Q$ t|>s"SԞ?rfD3Cޡ:sԶkSG?s'tܙNmax}%Xzz}xH쾰 4f@Ց@$w g6en5 jdZiQ&̷^?%b #Pk%_{?w)sOY?@ݻ; +x#Ih5[үk~>5kP:w?1sis<8 &|rx'a'&:?󟇇(~o{͇w4ǩ*1ŤOLfkm"Kt84W4yE{wBzAf0r?dvx| MJ?N;Я#!($dm-3;V .i5-pRO{I~Rږ0wV!@߀ߑğjuf!@I 0 /GKx|'72"J~j]|N<=ߚϝ}*S)^Z-abOhM4ƿxhP_g|M+& ~*|*n Jp?߻G@&su#|:`5J poC6™xMC Sp~skXdT(--QG^2Ϗtwg`?zZ¿BY[홵pK|L4pl5}%^Uȗ(SֶeYlgzޟGqT,Oa:>`vm{#ύhfX!QFe1бuh#QUI6Ec nbQ'>x@'bҭЙ\Tnw6{]-ڞ,,='W?C@AP;$0vrH0.hlkod:͝ށp+ܳՂwЮ@nM$"I(G"DCOY6;BI gg])9J={e2M#g\o@}T)O4bgp$NS+ƙ5?b+ .9T'm O !Htz.vɻ,= ,P`H2t'pNp =ҩp :w_%뎻,~73ҟ"O{j⦘?T5mӣCv0{0 ߐƑ: ;> kOWܠ?K=]|pagh. sa VjL-b=^=bmS˳Z,ځ3S פa:3[h|9sfM! _qZE~p33d!y>uֲfCBSֵS"%{%x%#\,a?%6x&FKI|_'ǰط'Oт̂D$^d RKd~J7S܊⚬sfgSLbb"2Ur5geQ\'(jGK[55뾙?X6=9ܽH`2t ~6OаnM 48r@lQj}ЏnPslob4FZs)ZcC&H.j,J')yZ{E`u>MQ)U4xRcEBJό1di BMj$f3#Q F EkdҝptFS ÏX%VH10N'aKoʡVw8'h1$A xɦQ4* r:ͦS`kI+)4KHTKS63q[ 8]RH׋Ձ N$P5'Z%%%_tAx?f ARJZ|IAOi* TG뒁9Ȣ9T lLzLS(?!k-Bߑ&s *7PY$9ɌԽ*]_}>7Ia*u7.É(Ң!`fQDME@Ʌ|{Iv4NrKdBvz+7ʇ ϾRr s񘷱Gk .J7b ذYiMM}I*l8\]&ses[m$Ƴ/,o9&ƺWAU +7y` lr-IM˔!fVdo[zVv "+_[Srw-J,O Ĝ$Q}3ѠxPtԖ W^~͓@V']]r:|C6 tbld1[X1l$׾kQZ} +2f&##u_k l+'l>V5lq8%U̙_Q͹J8:ԄPR6#ȚW,H\p//lTŲ1h\91y2U"CDևN<):2Q&)T]Fr$weH7O/?Mlٵ??{;}꿽~\?u B~:}Uۿm. R -L3Y`۞]ѳ'Lz!?)YotC~Jnם|p8,oS~c-vuO_Fblkyb]|D+wF2}sOIP-S};,,X-JqID}})/]#[<$SOd LKAHT)J of 5G? >~y|pPhUOO7O g# "6=]| z}8co0z;TzS3.. МW@ 5U545PiϼU{j+t˂ZܾN74bl7Y2_oVLk1X"' AqLdJ[i I ) 8Y:^p1k„} }+f,}uv 0.%H\bS3]WJ<,D)XrUK;tV^#ɤ^FfB0siʉSB=WM r{8sV<Ka0ݏb# S[OǼl10bM(ws'i|{vb h__Fags^y o⮦ ׬&. 09/~ m<޶gZ`i̠& ֕õ}k|sbi?rIoTG? 0mb[ckv???gA aN>kgBc|!yۻbDDE$aF#vLу0[_Sy3ld#N N74p3WR# 8%2p&4˜dl2$IrՃʌ-HnJ3I\ʞ;aI7Ciu<#`ǹ``]p?oA6g* vǎk{,X/k[f_EcL+'s %#m"4l &׶HI 4E?}&'|$o׍93 miBq1ٲ3C e V3~u;fO,[dRo1^A՛PK6h5ܲk5v9Y姼>fȅށF0%>~*ڦ?Y8>'9혐m]@ƈ^A ۦ:َSNDN}Љf[hDmXx\SYE1d^9Ct "'b&kPSE ~ӟ^A8spgz~NFN4}//`:3# #s?C /.oٍHBBVP}uݙ,4 `t#|^%'׵>{)̡:&v_Ex@oS_(=5f8pW ~c? U 6cӧobKLhj]°f/]k%%Q V(iŌ1!h)hބf!{+򠥊3%2EƲM!y.䟩l3[X֍]DXs9B5Bg좤_rXf~ y(b*E#jŁ*Xn_ Qx^D#[q7YpʚVk^ јqY0&3B pXXG Rå5!U$u*U8t-xYv! )V^w%Վk?Hd+]BTffH lESJ`nBݕӁ+(4o t6AZ4n3y y9΢,;7/暋Ef\,^A9/]bCM T"YOjJbNaTŹi(b.|[vjJQ@khtb,g;҈5 Í$N-!"5 4[OշBD@9FZDM5JbZ4f$XC|4TC&8DGClUYF:JI8Z^"sU"[`'Gʲci(cG5.m/d0nɶ`_I7km7df35Y@԰rM=`ܥRYu;.b`6):WjGUW)YӋqLL_dk=kajbKLF(hyf$@!"͗a<(fX3`.Lթ9GqGAIT5vҐdO&$ o,g¥{3eLa]7|f uwC KQEcIҫۨg|zIGr 5|uwϣ$?gt,n5x6BsKooTtYcqh7B-ve= ]v #404i*K~ f2}Y{ ^ E]έ£|Pن+]>CJI SaxBi4l؃YM$;[yynJC]W>~m^/> $S(,gBT&dJQ< pHԃt4}m,ێژ+vyL݅4QLps!lBjPs8= "))JPBӤapym ")[P}m,m) m{Ua[L7@7j2Fg$eɂ ErSIeSզ!q}߮tGK #F%Hq'C|Vэn$14ebJ2m9FNM-RIHFF{HeV-.Ji7+FiuoxύyT6<jnx|?4=J&h̴n_<`zy Q`MV_ +0(=h͍-V%Vu\-: djmUŋ1q_X&EunFccy&B%"ry$b?;4&qfxx4>o`EX?M};#tNHH4[{†ʖ_g8'qjƞA:Yqb #~&`pSWh:jfh$BJ pVe{~%q? Nwc;r/߯EwҺL:}hdXGgBpbX̚f9t$U{BvrfqXN2T;UI۩̣,x^tE%22X2SNS X *nf%1c H@`ɢKCcޯ-lINxܟ"dŠ? +y r??;hA݆ vXøӟǘe@cVɲJ_̑nj& --z[3757Pe-(|'M^CD[]#Jᛣ9nY|2!}kSPR({E@Ȣ4u7 #+qM }I /^jjwF 3A1gG;[= "uj맥ON?`0n )[m 4~#֨菨3mo7PCK M/0qM$q [r^Bh20J㝃8Ehl ?um3^7;$#=X~ %](d7D.t+!L"TNU`_ƒ(Pؓ7:1χ߬7^%e@j?(n ߆*%phN1Brlbi;OLpNGy2 gY5NJNfCrG+ϲȻ¬/[b7Kܲ_P`ojzȿXFB4B\|YC/2燞3q$=]*\%%MtsOtj!9Ǽ\bͰϑ3^<>886).JpB)Nm̌V /$*ןTi֪әXuh!p{ܰL>kBh@'B#J{D|uÆ1tK5Ztl`+ ·/hd(k;Q@Ǝ&~^bczYonOWeTmLm׎FatƱL*= Eq& J K <#= gU -|Pz$qk\oK^bxkg -%DmײY# FTEPIbUa;ȾiK y3-ºGT$};_$b4=D['aNWsfոȖ#O]r=)sJ0rҪ_k)R:sjْW!i'\NԨvtN;4k;w|e!73dHB#h̟+kސZF4|eSrEȷwRYz&N k 29\+4,'"9u]?jvx4eHJ[6bՁ[ҵ?G\Olwř\Ꙙ3e!mof@" &1[l[s>P<|Y60]"i.ݖ[:ʄ7VsL I9`T魢2^S؛ݴ9/;G }H e}0)s_rJfٔ鈑eRv|<<=m%z>֌p:ҐFFܑ} 7EŎWpG£fBH ߂|@BT08Uj1 mB<`&?4!sZO+eC?O8Ъ* Vm96ٰj3B"hTHT)I|QpsLac~H|zj"C0ڛf# w jq#>J=058I~AeQCUuĐKzu1qPVR} vUF<(R0RU@kmYt2^YKRoG{:>mnH0H;iL_N͛vutu-훯|#O'^*YqquDkJ3+O6g#5^kb%*SEO-v͜3]d^ L%،\;*ѭʜp‘Cexpͯ/߼o4=2Z؞A$251YuꕜJI`,h7|ߙL7dNصX;F)i Sg!Nen{k^]_4>EBaY7 ֡trz7[SKrkWZf=R^^g8)J{y -扡{fTnlLxlxUL )򼂋>o0lqm;*5,ףTM+8[m74~Vet\+dǫ|MlȮ\oH5ɞ4#[W@6\!8cň^ 5ޤ':ӀiDlxu=GC\ױbXmR9s(1;A1=]҉jn͞SϧԌ2~phZw e;KY)r!/_4A|b% *e[Y ЛtA@\!6&,MR ͆@qخ#*q Rv3%|6YeI u9ڞ_3P \TS:0P kRg(e렂tAqܿBCǠ⓽]yYEs2$QBQ!PMxP0+YSfAR4就-ǴV'Wg:Ck(KѦ6<) <3qaPJ:iK_kh׃?NÄL)i)5$6, IacA€#܉ݚ Aׯ_4 wwvvw:Wy {ue1+ ZB-6KOGėAf/3.~F5_eB8X" _*K:j,&eiwFѫsm"R52{#dsHLNΔil,~  i'VuУUNʪLa&Wenڍ8UjX9;kz+Zc9Zlȿģ~ѲƌN=AǏYu=xz o}NI; &?7bz:^*Op]|#&Q9@ņ{j;=Z j^a99䳏0=:0Q/ACcw|!ty9#QP2px&uL`,oڢaDYvAP.E6#ˍc`ӻwm7kNu=0 jlkM]ᓒަ:]gD|'"([5H\I6eP^KxDm$.Ͼඔ9l.F硲1💡",ț1.ɉXbL>Z%]2aC'W ~x V.`vAL^tco#ec9 .K܊^9ߡ~ Z1*B:rn@3(VN %~6-F]>zRÚv;{aFZ4Y9`&~w7NjH- VUq!⹎a;\(. # XA׿?&eW |Kx DՅPE:"r ( \#IWu-dhj\VHv6pޡ$%%]bF>4jlʡ'3 6$-PyB2~v;߽}ۗo~z :זz 3pa Y5Z*ę]r{0PhW?/' wRjo`A+C>nHGxvv?պk|Ci!Sbehw)8tFoN0{z-D3NҮ$TnoN urAUWxضWqFD S;6ʗZԛ5i^RujG:Z£ b~ ɸ/=MARGʏ`djӨM,YTSet:NCV~Շ + !J+,b8d?|pLeB46#Tib-vH+s _hIه&-.+k),ib?nɤAJESP\ǫQєl^߼'2itQR}+Ul9P|-1=t#;KB ;Rh& Z5sP? š HB V#U4aR8@@=lK`P`"#Tem-a""͜chG4UQDȊqD{ǃ[HWq4PLB'Z@K(?7~_݅imm29};p. %g|k P&lQ$Tx\6(Y %Vf{#H% 9:L=g?Mu qV5zu#4!{,\{7~O?r|+TWAn1VpX82|ƚ-.@໮MJ>$5mt16h]hK(pqtMgbcs!~Mh@%[&G,2@Ⱥx /вIN\)֙j Z(&* cw1Zq{ĵkg< 7@Hnu 6^E\n;@pE#@<uhIKw G*gP@)[n_ψl r[ $U3|_ ?dǒ3Z 4,SV88fي4tj;]জWaGX@CRb`HdRcI0T`#w7I./""Wx% ]/7Vmc"dwl QŸNyȏ6mߡb5v,#!Ÿ5OخY$I!WX+9$!+SicK}5[Xx f2EG9ߚ jٮ LxH3kʥZom/fnm?6;ϙ k zU' mwN_9eF?'+.QRso ;28 g_-Mƾt\:}%[9К  ;d;-Xw;Pci"jr `rrEnLJ P8=Q gr,Gqbr߱ ٚ|Wb:C}ƍ !0:]?z`!Ѳۻ8n;xq_*u }Y}^$JZzNl˸s+ 6k7 {jn{s>Uɨ?mnChN>ҩiZ$pX[!RRwݎ۸Eo<L)t7/l}"˲GZ`7H"n6:@(F8/vj~RhRdﱓ ̚o~B$&r0^& Tx74|*8u|!vƖ$Ij.^ r` <;zcU*yt.BM:D{`I\OfFzSΓ#R6yPt>T OY(SM8DCзƦ6,i:WM3We8p o&۹oe^ZvF#a5Lc#Bq2 R~ Fc{N9d~璐HP-p-nW 4a)/jlCgbj}\Ѐ`Xvk٢TRpiu.y HA)ɟ ;zuΤ-䇰4B+ twg<1_FF,ZĮc ژ=VTtQ,q,d2 =+JtV9G1q!  F9Mu7E u.kj3Q&GZ(Olp9:C]!Վ%G %ZD"NG$fu_ y3U-4Wf}B?R:T"H@첓Q~$bW@"VQIrkWa5m==ڋ9ӧ`]V#MkNe Fِ jnBtںİҊF )fo7TF~4c=C]ߤ]MorFP%:*hf)0F܁ ijQX0Nb=M1"#!gsC dw8a15n9*w%dh^ ~EEA .I&gO$D Y-^p6,SapǴLnjLU׬]Z1 ,5ÅBj *͎)<蓞$,=ҪLs1 aQ#)}2~i%pI=]wD;E<`Z /ܝēV~!VDl#|K.Vɓv!AU2~)S-x|"Iec6F"ar ΍xMd!?e2f!~.˲p#=/h6#%&oaEm~] 7fiaDxXDEO0zE&IB_N$DǸu5]! f¡^HU^ Qn=qϤσ{|dmX+s\/<IL caCm?+3RCGrU,nSNw!Hy>%oՀmWU<6}Ğ܉f>s³{Gm<֟U #\ΐW''4Lm0^xTTYƗTaSR3S4pQT}i=':'Z#^F|HjdDzv9XJ#,M}BV# ;P S鞬.Vi0*C[UJ|2q\۪)NDȃ2XꢙD0hG#_H{ީ_NHMp$8q$8A5ewY6%K&ll:ofI]7{o_꽗7`wfl6WK^v'S};usĬJYk"YS?|nH@?D9^0_9#)idV$v<9B?dCd49GNt?,OOTȂҗf_yYp5JyT[f>?{ٻE\.&HDǓDUT=qIa;jARKrRw1):C0J\(k@H1K6'-MHX %HhfŎX%NMIʲE ٞ8'{PךVDؓe%CE)QM2PksC_)2 9C_?yX *l\i@,p4>:`0m4Xu=3H55a6*W2 ZzM6 bP22EBP'H^ X/˶-/S]z9l'm^i)^:mW]L2n\DCJ[^L_ld6G]5fPȤmtHVp7Cgg|cЛ;bCJG.nǹ̽']x\q1_6M X"`\֋KaIW,?_6 iH`',LKY9mC$9NvݓЅQ)6Pd{Gԇq\! *ٚH5s4 K"r۸  ]]5:'jYN_b;vq#l^رI`Enؗ/Ae<ΉY9W%u5&]1۹EUs(@~@ (&!+%oRvSX6¤PX!jO ߶+Hy-9Kޒ*ޖGφ:(%9R(c3!*ӎקVP,!PȰ0us`d_\ip?J_0b-4:X5zq vSMjz_M3XlOy. uеį:ءh 6bfYL?WO -& z.`%Y8+ICCP7M6?Ou]W+O|viY;^,:@~}Nt'cAؓdPLb ;t:qFf TL(?f2RF.}6(˒N,-7N>P(EY1s,kS'،'۰\Vј9yˡ1gLjǍz] Iޘ6B,K^4>#yyY'Rw2~5(;|%#ӋLtUAb\-"w 'a0'QI2+xrPx!͌Ӗsߺc C3EaO?~5~XooVsx&jd:vFF;1^&n҃6pN9/me@P_)ORLf\"3ӄ5<ŋȘΧz#*ݑ # p*]r.VKL8Ms>',zlmAMx)\#ZDj0 ٧0V\wl+/YO}ʑ^UٮzA,#!|i(܋=v?> ?J([2 [:wAg[*^)6M!Y!9[8=,I`,V|9M>lʼnp ]ηewJ_{Ǜ@:Zkn /ViО1$1ˠ;̩ޘϞ-"t`%sAI7&^š@#'Pڂ<[ϭ$k 7 %S\ IʏXa1G KCJ̕#Vuvfl/t/YAI[<_07Y8xg{hߢFj 嫦&ƲZ s^R95 fxެ:iü A Tk& Z~z+&'[RE͕9\y[lo5yOHˮpmo,:n׼M/4,y1T5C? SQ^ȐǩZA|,n.W XY2z#9\>٣# uPgJQ *5|@&=cWR8-h|]1} [Xz@pN1coui|w MC>nUۼ ِqАLăQv=^U ߹GD͗ޛFR>+64]H]͍'Qlf*nIE7wf)nd\6HE^Fsxt}g6{ڇrAxk<Cv*ӝ$G:U{ H2TME:A?5zlujDs6S6Ra69}8KQ~IR GZ&b%]>ieE6x'Y,w^rϢN(ݥcM3jߟCE9G=upBKMpB"X{a΋=#Wtnɖ6~Hx/ۛ[ڨ_NxR=]'Ḯ8ʿbc =/|r3Fy˙ӫ6^gUi(QV pHЎG Gb5-"ѐSal7QPdzZry{/&}|L}Y^胝_OWtXfXj2\c=I MF*9J%ltlH䍏S .8̣)k56\{= rP/ht̜!MOMQZYՊ3Ĕ*".n%_J)}[2 o#̉5tD{hծPNF @_gա~D1k$Ɯ%%-2'J%-kY\8)kaW:%p@ns[(j||uM;}n;Z7LTkÇ !1!wD.l܀W뜃qeeY+̞Y3qHg\"nX;)_Gӛ3ܢ8Ǟ!c8o> ؃ ) HIF/.7Z tCB.e쫊=̟+A!FI%M+]55AYv85?haHS;#׏*zDߖϊ) %%߫_G1D]"K,8jDWTI^L:p` I?bf|s4;‡e!q\ - ;\G[{'ПqyQ7y;f߃K ئHT+@}dƽ ȦVKaIM rkCK'IYVB@NV^4U=EqUߠtV5$S.<.7:榃FEP68) ^9qVwnksPB⽼Ʈ:`t=QP0rt$|ʕ2p-Z*f(\MJ: m\y 4~fb^8iOEO]t3TĎ6v- Qhʚ 6oQ $V,VZfdJ6/U-etx?>LqLZ;q"&ec=jOkJ}OIऑGʋL䏭Leڭ55jOT5qL2)C?, p{|D[.f?Bcۆ7 Qe.~M W⟴1|en<+odfS@0L:dZ}Q, aЇwH pЌ"ȕK ƗlŽE6"%/ףGAlpP)sb2"CZQZ)cӔB ʼnxd", DIsl06*fif;n &@`ZȬB/#y!R"^Мɟպ]g+v{X6Q V8Sf90̙{C'$=A #lLܥD^Ybº]owԔpk ꈛM½PUyi.N3 3zH>@7]o.Fz{A&VePqRAy5՘\ݼĒ_o xާ&kµ-Ůt[K8[֊EZXɡO8ׅ_mpPz; TGjX H$BG6XŲVAի,xc8Je^B9aԎ1Jxa3v0єevI$.Hj!HA9ӛqẕqLig$y5i!zR-{[26._?#;2:8rzZc7q~k'ٴ1\<w?lk %5W'?5? z$Zh>p_&=s5yLK`lO20ߊhr8Wuݿz/Mj/|r_ =JNǠߦ\gR91Aǝ~u5}/ k˴݄1eʬو#7,^3طRL݀(G6Ay~YNC>"4}n{?k$)RH&J!s1ff"Tq<:.gD` $T8 'eEGpY.Qӂy4Foq1 L\urB:!gLQX,-Z|w$;-\Iz )q)Q`Y;J8I;QunS\I?H,1[t2%8S_؆´Q=:KέB܆D&+= ~= c"r"T6Wɭ7*Cjl`JmЮCPI6E8YA8!*قbbx\z yU$ijWp2*meHYO υ[Zifj{eHHkEg6|!!xtM " 5{+hïֳ2YrA)Mx:7.3w@%ѝ"N\aw`d8vUx0VvzBk~ W>@]Xoh;gglBB@FǧyY&3IV\]e$QǮ6y8/9V[fd+ʦa:&2iKۊF\H `h@C+׼_,2WR苘VQ3(ȱw8.^"c~ua$!)@YgUdxdOTT*%W;Xmh_!")DYPk(GRtw[Ǝ+/ySȉVVf#Nz馜8)r9Dtsӕy/3i} 1eeab }sYmonѯj8%˾ZqUf@ YSOey\ST̶S7`L>{4{>ztc{FO( >flQP!Oj  s:iw5Dkf6G}Ց|"O ,}7=}ⱔS2Rq(0GUnP@Frs__џo蠭х z tq9cw bI:&/zͻȅo1-o~F $U+MdziWSj'*q M zF6VtrVC]ԧ-~ؘ,;nƨTEBg|.ay,b{{rfL  e!$矑0[EH%73zlR1G2A;Кப$P֝æ >dM@ƱL`kx񪙿(dkHD$d4sŽ ipJQNAY[?u'n '//ZXaFu<5nSvisw]`\۩} !6 ]]*|)6;.02WOTӷ۠* ůcpkߩG7%X9Sr)x Vbm(+ ǚ~MS'oK֫m ]uln ]^`MjWFTPuMݴ/pZqhz29葢Xʒkq'srݙ L/T\I;'$_˜cG$r%m0 UGI͒]+t_,;$y\A'[H޷HnODu a m_+XޡDf1t=O msw q >)$gx;"ޖިBȤh`ဓ <5س0UoH*i|4ԅD #;1'*Z:Q2䧨ױbD#4%a^h1R" ]9;x<&z9YuΫ'4r0}Xh[Uӳ0G3rjfRL9e"1'?gB qg?pP%QiTjF˝WS_cídqǚ@2qq5u*Ol9fqoHLȄ}$[auJ0 -B@4tZgal!o>`4ݮ;^3(A t"gs0E[mC|̹bd;52mVj`r X'Q죲x1 #޿&&S&^!~)/A]Ϻw{ǯ\~8XD BC#EFt@d ̹/N [Ŷ*EZ)w\ֻ!fw`K>tK^%fH~(>"e1'߹z߾?1Gc~pHKOzs \ۯ٢JQ\ksi?&-^%(&l0N#>.; o !+S`g4aE RݽJ]a;+ұfIEUd' a,fvrj?Qݻ¾Qjd ,2@kXgEA a:S&E(^#,$(%5`X.SņnA+Wgr+CV$p"V|FLF>7a5ڕXkˈqPfM%=S\8I#E,9Ϳ3ݖu?l'R&$hk^yS>gz: 'PgZ|lMGyPäjh2%ReUfUK5mn ]ڼ4rUv9lT*sB(Y>䱢ÙAPG~NA|NNdT]e`!)D㋷kqҐ7(nSfxuhGSbٯ2KEݸ *Q!"|o\jqKr:ΠrylExՎ![SFxv}OW 8_qŽ9%~6Ay9v.B ㏔".j^-Nֆ3n`[ )7;xɚv 0xdEM@CR%Зn>U+b;9D)|ո6^"'>dDo$ćo'&ԵI7XNmkvuW%qz jYAUo )_$ 9D7%sr>;FRawlV$9b6] 4|ץc8б^Gz~HK O(u@uamP~zgskE8ÃuiKDxjcVi1OUcOZ 7.sM\^EMEۨ[Kk7~cqU! -_ל߿]9u24=Q%5: dT"psaVcd}3FMy}&QۺUwn; '^S-^Dq~C<<2FaRG 4f=ꌂ=f6J+tSU2ށnXj|)fƊ͕x UPE+eLBUEĚhDNl &-̆ހ{p*|׾!So^2!q>9^z?fmu!ݐ;ПSl4R 6Q+^QnI vږrxN XC3x6lb{ȟB8p:,1,m[RBU% %^jRV0g8Mee8]0ʄzQXNǛ]@iSxHk@} CsuY[^(rao 9JJLbz&YN:Dm!^W~3hty u4Kw|qDHuƺߜ$뀢صC5 bQ</GPą Z\>) k'cO(uxկzxdn\ 0N*!69it*VȊuVHy+"!ȅXƌӄ_LyiSO'H) U@(7kæ]oRXA0Z>p*:O:DN/nbuuU8,g ]*,9H :5?) QMZL5 WԴi KV^q+W1SO͏?!=f0碟\PbChs"DCV26 ˚Lm}A)^<9Dh?WO='f,Q-'pP<"<SV?r-GpM}άP5Zaf@t)?GNH'HC3͐c-?|BhK^޴{ "mܵ=*I~T 2j,q4uLBjg^;ւ!?C3%Lӝy}:]u !"! ?,."x=FZ# ,S"$ZPz.(e(U'h?-@?>܉3N Ҫd(>g+PRfzə BZq(W+(VЅ;ŭ7p*JA#@?F]+msY*On٨ nsɥ5NrshQg Y T L*r՝ufؐWL񐃩GILDru6ztofbGM)I/m9ݝ y󷣜/>=u?tOq8i(f einze5_GGȽZE"+&\``wt`wut[RN"֬|ǽ W%No-h@PoB+"h4;vQg[ ev`Pk-=3ze",T1Km[hwe`׈݁LDnws588 w{b&<˥F(LyÈ{zz0 r.@oI}{sILbq+ƞߥ Щ:-0,9)5YdB?9oi!j,˳(ߟ|jfrJ2\nqX38#j| uܛ$(f'\ ų {3vH&8lGYxR۳꟮%LzӝWO$`m+=Q"dJ9^"iݿGIIA.11GU*IE ,G/Xq(xɅDJ>|RT,fzFZcPEu`;Mt6$V W|ox~5JKbp\7a%Ѭr8*1*}WG79d2C$Xɻ"YE*ԒNXNP+ԥHy9xpF`%1WaKJ:T<5 7_pkA@tC?ktEgܟpZkÞj(Q!ᐶ1ߊP :0ko|A+[6qjm~23wI$z' Gw֖~RlAyL^I/l >$J 3aڄZ)ϛlqqDǏS"E"IO<>2[mYfjĈs$Vs^V~fҤܖӶYkPJaoJ#($U%&\H#'3  OATUþp}?1>]R1>Gn#\Y^VJ\ݫ ;b߂hUno k.%F.f9'fePh|.QZMLϥs2YB /<$^Y*Fwc 38\]UX[6S 5^qZd|t6+N,bEjXOyqPzȮ[C.]gL3P\2K>[mĆX+1L"n㵤nߵ(U (F(k+&=0ߑ4}g20J(SLS.S KVF#=kP FԘ=/ķI:VԸ44cbLK&v6qyymkqK2X,β6 . \-\WzL]u4~iya:^qR,}&j^~ >vm$Θp#i .6&c02Z/ǂ4hw_%!EZk:k-.T?QYcStŇaԭr3FZ}, c;Hu/DV\@. U,*+S QAP`61R hS@krL<&`aY=XISKM5]\t |`4{[7WY?bs!+a`1Q%|~M$qġ5xJvIMI:ǗtUWu,;2@e/8¥r<ŕIB̤?im 6.iYi#OF1񛷙@/'m`/ LpxTCy !N7f+=>k˨kS%S)OF%2Qʃ?#Ͽ8*5hrϞ=q>>*tVrܼ6P0t֝Y_׫oCxEYy>'Rzw3٠GNGR.RWҍbR+^?Ks* H[O"'/*NMySN.=%T/OD<֮JiO|]nWHG+{@pXlľ`pq Ht&(=@ycXE_$ KU-Qd}vޤ93Z 1~2:?YBaeSe%R5 | MѫzÐY0zt.K%6z!K& R&Um&Y$ @68^",7VFI Y7s~V/p6F$jsDvf f00?!{}2t.fV,ؠ&`ÔM<$ZN'VG_𸌪*^@%!ƘzkO#.w ǻZ&|~.dOVӅuC֓L2xiӤF)j_J@-tNwd4f`y+]-1Ve'e q\- N'a m^IdViY|>9]0q՜Ĵ%:w.ů[Q`X:jw!׏i%Yj_֒DDz ~6_: _Y>r |(8Ags"H)aUj=x=Hu%7֏>c.n1*<+v8F^}MtB1j]r ab>y~|+9dL4E{z\HRXX gGG?<{ʯ|CEч,>1q8] i`[ύ2eb/8뱾TU 3Sy$oMg gW,Rc߇txzziFVpJCgg H_uP.ͧ"W>vppx-peD"whGd^dșR-OXD,~UHYHmeUE]#Qҟ7Y|Vz:tچC{-Ml % L:4 krzkו|;##[sVCc@gH" %P. dɺ)~/)m'{]kE8bHpU3e4 <Q4\RBVAK-RǏ뫦/ʖ#ƻe5#ڇT` dzv !]Ȭjv*{r*tWjvIYcڮ< ]+'kK+a=Sɾxdžχ%gIMIX($%q8),I ڤN?5ȏC*0hd&R(3ia9ؕ0D?=ͻt9|$P2Iѓҋ./ <-"Ύ"zm_I$LZI?ڣ,`ܷKKN#,MT:Zt'^ 5wfї\,X"#ߥ *!l?O>@''!2Gػ^CZ&dOWnѻ1Fwe(4kyǟv3IσqM.{x~ov__]/j82UhL߽7Cȿ"tHrcEĥFYBmλ & NgE1[b"3BM/'/%c=x8nge0n_P<ʽؿο?J4]}D}R; ]_)ə3ky/a2- %e [Y 3\@C^O&CnqƱH ; 3g$KI2ز4ck<]ܱ%ur.Nz4V?4Tӑ 4[&؇]BO^VD,B[rw^N9z(1h拞C4!V)f7eYĭypW)RD$> L3gu 3bHR/OVB((>"}A*GD+@jc򪲪ᬎ\OLR~+a#J-:Z+.͍2,'×$.<)ӛЇi1r6))I]{KvKczf*+`+ zQ%D'q+Nd B ) >+[\q1[xIRX0b{J:x/g'7oeV~h;ѫ | &aj]]p yPgc]O4C\1n/]ƗIX^6cs?F4YQx '7/%I~=:YD_u3cgn~{=#a$u(#S%aaGHdä$ zJ׭pAS5) ;\A>3x89K|`[؝rI=Н®}r,he?իYw*hqe)ƻ$Pqgv6{3s3K1ᙏl~,A!-[ν)"HRhOy b g('2[cVmԊJzUz[oWn鮿V2ݻK )#7`;;ۄi91)s3=>tlUqt1y39)lUw]}۰S7ìlHh_õW)Y&c-\YFG!EY.ᶍ?!V\]h1JkL!J /VLC( ̝ _DH*wZ{ً2DBlHX/ {YEHR ѽ`B B0UXǵ6|JMvA^뻏\P(̘)K3VA.ò(XX Ź̃.auPZuE .%%/콜={1rĹ7Pݙf קB<;I+mrYGAS-BjƝTjrh\ͪ W O$RV>' "*36\]Fy,|nX=1K; 3#SD!/5z{t [ g{crBk @x R(cqY6G=iO'ϚU~wUk8a !B\𢄱>CνYaM]R5ǂ; 530K0D_xFt>udӲ I' S ENYM0 kzS3X iS)I6z%_MBXXZ\崕R2(Ҵ8_Et46Jeqd[̈S_O6r8ȸZ_ڂƪU_s~;I!8-[QgE҇(7.|`vr. ٵ55$v=$_(MPǑCxD%XI9gaj5} `D0VgmqEut\`Pf ^/::z5ͷ~r1gEWaEY~Jst2Ι>&!FOҎ^"|-TḥGtˆSmWWQiHͭ{s|Kͦ M4x,e\Tb~aVwH%GfjS\5oXtF R_HDᏤ~zԫ^41̕-TSN=8]:jf'gջ҉:Vz[Aδ~Vp&L;P@'Ne$YP^aq.x5" U1}`ݖIz[#mYI &֌%WA@fꂫ%Úd*\A~~R[}?kn֎~ T)%zգWM3]ޡ+hW]i\ђAȲU_Ha`qr2H;Jx";at΂rƮ\R$BW3_vu8+|/,%ye3*/Ij@+=DxP-,8S7kL {ĖŅ(; tfk'.OZdAɲ"\GC-O )@%)x{8ill?^#ܼx$LQṫ-ul1 mt T:J}瓇~wɤ{.ê4 㑁`4pA1:nulgxM%yǠا`f'ץGXLQFZ /KV!P-O+ qgDۛ!d:S-t߭#N t-j.-6+"*3}Rt e1w1#-2Y4Ƴ;=,(sW ;OػlPWLz=Ry2EAk33F:I)%h%aiCۚ@L%"vƛRL&뉩 9Y|tm(e$ ݴCW_?KN3 py촉WH- V`X 3ICTЌ d6D_ޮѯM쑾8e6m/x9Ժ~Vpa%s=qD/ Mpƹ¹2(@x[3QY c_hh#V7HdFm'AQD/k+;ܠ7^|i ɪR/ #ۋȮb3H0&*FF̸F Sص/s]Ι'z5gU I4A _)(2ykT][̴1X8=[YXp{'T#_5hYنznknJsu+#90/A+( s)qm@zZB53s\}/bXhן].ùj#K9v28&17vQ~ï}_?ïc^ rb &$m+#13u=fVcjb K=7RW/CWhMe )zs<(Nxe$p\.c|RǀmRƝ]e\o,1ŭZB^3l:#כ+iW(0Ž&%ۅwȗƪ>%(v'oŰ425'`d%agn$}DC;.Ӯo!5wؑci(ҊwH6nwݱ0 1нpCft/z*M54T򣜊vꉤ߹"!cK"MNfSXe"R/{s4WKh+l)"&&[Bf$(WoO ([Jӈ:E82jġqZaGƔ0 \Gڛ6ٌ6I1M`Z ؗӔ9OPm=Nl3'{[o~۞"C8J<B~*Da$t%%?+MEtRt Hg; Їe]OU}ɿZ>VB3g#jޣ&ܾӠ:WS%cd6e&Ze|%:P1@8c)y~ 앬AT Yy8Y3n/TbT*BFn&uz!T]tnM\D^jog],s($LHYH.j6ҫycgV^UTVΪa&yDu#m޼ turR: C aл;u2N>s.zjw"n[x N(mL0Pn*UXlPA]7ceQ;)AlpO$=CpЀ؜8(Ͼn͌~8␸jlw.w4o~ p>FNTb.dt>V$Yb%/pQlgIB~/?Z7DJv `_4WLy:9%L4-6a^~qѢ׈W Z 5tNd+P͙jҤDw3R+ v8L6r1 @e;0Eel}y&8PΑx)BD?WX[; {,r{書n_ж7ԞfJ{%QA8"]_qu "}X' 57}՚y䏛{S=ϭ $&^+ilYTcYĿ=c :mCkY?M[N@ݙ LW oW]FY/=&Y o ,Y;Z| BB csy:A;ȵz,,drkQ`+Cݨ{-ћ0WB иz uGȩqWIy!kyGKJӞ@%¤ jќB]3o 4%ҹ#Ng\-{"!>El8~T~UOA›)9{]o]} ɔa7вǖ&AN ˎUr9 MLmr3(1TįdA4I6 2ôoO%) 4 %XZfCT6FA3knGWWөbRlnyA%B$idwD[aF9ɌyT]U=쒨n\1a"n +/X\[~M"+ #%mm_FھUROSe=2&-8~Ll\UyP` : _%c7nX5/(-.`XV{J(vMz>%/]n2fIE4: S T1"TR1W0(ۂ?A5%LЄ:LnOY8[#%`9ۅb8Cj>b>ͮpʩY)[@UVN)*Pw3GشZM ӎyNv5\ CV#/鋈]CaP ^%I2p%># <93^nΖ ;ߕ47[+9O´ 3,d*n"ˤee+Ї%+NRXc^,49nf$8#AIyPc` u)8ݱ5I2V"@KĈRm,51Lb|aqc8b.NCqrTNigu>q6r$J6Jl5H1]?WK5񚁟C Z";]JZeӾGK@:jga3[!B״1-Ap߇%]P[j: 9SY4- | %fLJl@`s}0>LSW/9*a{:[®ȠЭ[gufԢ$j4vי81,8(;,<+hLNE'rG\&pIPK X2PD7;Gl0/xv(IL'YTώf<R]+ BMC EOHN]rKOOJ@l>]O&X;9q)qFTF` ᩎ}V]#RY8`pc"$'$J$4Ktrpz)5vV;l>L˵_e9k+(Je];W.91[o=Wppv-ط% C0q]zpaYKG:Jx~nA62mv?%< <<z 4b-/{5|i$!8UEh-ՠn5rhqkV͒3 p_[gzb{߲frհHH$WF9l-v HXG4KIsk+1xPp32j"ܗx?ԖqV5AQj󠑍?b–YX2yS N=-O I/IJC}:^`H҉'e9/rh:.ϡWVa3 :Q_dvANŕO0Ix#{TSQo˺_|=1=\~^ %Aؒܧ='sc}O`\ bA,*GL0ZIq(IA {aZS&Up`1m:JFl͗VwzŃ'qL-û$X <[e$ư)%ّ>r_vVg۸ᧀPJ楓c)ql9Ѯ-dR-%ds:4xT""q uSa\c P=@{pF|"BԝnqъHq\>&5@UJ7tK=1Cjnpk$cxaD8$*hGS/"&oMڕ\«Hw8EZf5WC,5am}SP\\vwEzӲa֋S *' rz/mꍙ]-pKQr"]:EZC5`o~ ! 8!z&Uz~O}H"$tl-i3bʦh).PsSG 9On:)%A-_ˇӓ&$'4 BmffuVщ[ юy;A Pؔ#ìKgGSkF,VHQ1D4.8Vf*uq<$`.wM F!JBn 7($w5NeP-6_FuP'ޕdCq:@;Pu{E)Ayg>>p5)LN8 IyѪ-.l)#fQ"u̍ݗh62W FL8N_F 1GO*퐩bqmF8: %\kJUeܞu1@Z(0I[8b OqT8 nt`;}) tA(b=|"c~ŵ8ϖ8(ɱ@ Ea=bP%ySH)ydl>?zqlʐy W7y\8itRc:[cQajvT ʛ$!6-zg ܄ߩs5Lb 刄у>^*t!7n6e׳Nh^.EBy#~JH$>7ܞ-ߓ Kzh31nChOao=/R?*'8'BoOYKKJI%Q7頑UXOk SnڻFvڴ< cHS`O=Gpa }̄>yrM4閎Z"QM/zDmJTs*߳Miquu|`-jJ`JUDC."\+Ue\2Ba?hbChpriG`\QE?m'LDT$-PRCrV:=oKeUm~ ǰj8Ddg&8{f$ c3Wę踜(bH>PDZJ6FKpGYesE0^@t8l\ӚLJ~K'eOL'x۠vi,23ts s]<1"RN2eUrX P% W$2-$ BMR9*(B *tf gQO2:)tdq ϤqslR%8+o+6n:c&r*CԖrHDkKYL%ON ZƭGex=s+v@K%W+Btjt8i=Vspz"3KJhI?gn~Ɖ[)2]#Exbs(3Z8E%SLJP&`b@<:Tr i"cs22k`y`320@Q@{' “Mp ^}j(IV}«0/L k vύ!ږ2uM^zEQ1|ƚY/gM Vp4tࡂrj!s|vx𵱥RFy# h~;6d?W- fp6ySȺ)N &ӯC>aSzI%g$gޠ3tȜ# za~Dp/nyA(^IUkg_)G.ٽ8G[(J2-0 2.Ùc/c$g'ie  QsJҊ!APگ+!_eNvNG 3>^}#c=afSRmGp\X u+.g?7ZSyD` Q∩%LahMR8L ~!(>WX-=`{Cz2rVɢ*RhVf) X/vuZ/!Vr͗([5؍b|A*:z88sȭkd&UguW3CI:ZR()}pT >s cT3"u#s@Ԡ##o6tظGgk#۾(eư恤:p#_/]U( Lƙ0`pA>QN@{~̖ZEAоO"H'~8 svbɫWgZ\ɐGLbE(BŬkXqag3M8uջ4@ЏRڕEFgt|ndt&HNjcr8i3IuD vb#=e yJ@鼻 /ht`֨ViN3 OfAԐ$8I g&),I3=6VC̈\/o5j#Nltԉ$Ylqf1k-92E\R.=ؐu&)iu&+7+5 75 mx \K:F}9Ђ;ԭ A}*&JQ.6k6^dNp~NJxAPx| iWZxIS7dG<'dtxSfb3 ~`h f"Hd])ptd=*켔Q=WZYMu'9ԯQp=U;bҔJȮ,$O)Š(PG fކJոugtSEydjY$Bj(nIӾ.nޘ6АJՋУ x:Bk&|E*)_BppӎfcP f{*{bKjɳ?۸i1V>TCb4HYr<kiyMT$F}T$#AegeqON εtS~/x .y\HىΊTg)2X.Нṩ`(*b.p[cj(> ۡryM+'7ʊYPvl`&a5^`ˬK%H՟ Dt;>;38h0>ٍoB;/զV< ;$1ѕ74/VB#͞;NWQణJ\G<*JY0~3Wj㧎nH\Oz9ܬ\4db>b8jt̬Dr n/+GS0mX"@euyJ<&./衠fƍԉɶ7(OG\=uJTu7HdE51p4:Vy)aՊ)B e=>GM'8FaďgAKUd7nVb4R|ZTNDd 4%!}aҞ(r^aaoB.5X| 꺠KKoJ-q/l7V(*߽٠NVAKujV(<6GOH0^dpV!+,j2]cդ`bsa0;yB:z^~/>;Y8@ UlxrI.!@ ZA9I$Y7F+g+G1 ɭROt$!@-MD^L^Τt(l?yU:X1z󷅱9ZR}iN|ۑ[fIlO9Ӕ Ғ /]/>I?Z`2FϲԮTܦ $[W).^Ko j6UG2AhUe#rWudpyɀѹ XV1,["Q/_ kCA;dqP1PH<5FUB~ą$~zVnj%q qA6Q*Gu T?z!3):6BlfD1m}G^'MA~WkZD qw ` NE+DRGBLfCȧ_8$~HTzth D,S%dymHQr=H zWn1U-S.bv҅Dۍ]zUalw/=ZhS, {ExDa`yf*0A [Ob6V|Gt27yh?ݏ.d\ө:QDsk0乡=SR. 3H0Z "&v++B4tii+/cI"IF.9CYJB|`}2 ͏8]X}mG_ULPoF!h1^JNjO~"ꜝcR4,HϘ*5 A_^ 樥;l.%-1R&_pJ0`ķR&T99*aөtVjfu*IZ Xowd0Zar"* 8xң4Y) dt'63z.0,7hD;L ǰgrX張|%3WF $ȍe6U )ysщ RPMX(9΋tՌlc'8Ҏ+c$QE=p0nC)‰߯Ѿdw3ښtގ#ƃh~L?8\STp 2IkW"?+jS~]!4W!d͙qi.:.c Fטz.ŭ2=Cv3ޠ,cɐvT D<ľ!pk[uO_RuZ2kZ5hUZf)]Zn)9Ҋ-w]Yd"ʛ.9.Y:g(EҖ~/(*^͸IOJH^B9koEa,bz!*Te (`zbZPn;sB=94BX} [5ȸ)A?R=yX̍QH=Ll׋s+nV1@Tqx)YЏp?el =$45GACn22"lMYW7ްh IsQTa=$s/^tu4; N<:!O c?Υ.m+ |6=0iR@zrN>oGaIv8ߪhhڔG!THSIj@@lׂGhi~Dw/X'氯|`U{Y52&p ȨRH^68qOj R6ł!wK"nkseknaXiZFهZB~1YV`쳂(3.wQ~FRIщpCW9UfY椀mdngdD&- uZQQ.qh%U> J\̣y ѾdL]32G 3¬B0jASSs;Mx H!eJuޖ *f#>m|qc;܈LOzp_l3t:PذHz[o;ϐFDBqHe}XUb4iT:57Mr++k-& ߼Q=ꬲ8uUnmȔW +ЄW#qiݭ8K ɩ g-ϧ `4랣bP tͅ{TEEoxHݯR /A" n"o%zR!OFTSOVpfW:]4VO]^g];_J٘T6FPct KVj(vk0ͰTK=PfEΡ. 4,xo,Uc(&:33kCi/Hgbtߣu$AZ^<|).:DOEI`X'qv{=&4 b(Q}52-H4I# H X|·Y:*Olxv_s%F*bd$tD%!]*R(=\*Ex-FWXy炛kTw:#ݖ=<*@> $| Ja@`c'JV ;9mR!m_B!{k_BQ]tzꓓ_~[9p~t=?PSUɜNvWRN)1Y@3PcTp\}8w1o'o^Ͻ<ۛ?f'Su*/1Wǧ'G?==:e}vkjo=w!5~Yrnki ę|#t* L$ H)<>{~}C,RD'nwrjp_菡:ސù.JS)=I>k}rk;|*/^x6+L _gar/&="B_'K9EՠrψSe%%,1=ZeB+}t쒷=wxY< a=}Ô_n'?uc`KUS^[͛ǟ؋e HMxx+$Ym2f:PNʀ ?Knj߻B?v\ ?GE-o  !_N0! c\ vi0^zQl98` > j{% wGwKa3,|">w  ~>}Uy$di[1XB$d)#ߗ㟴Z%|<~ 2#~0&#;LQzgDU9vU0ʍN J*GJA5Sl7x/[>塃n")Lw̭-*P7CQ.пZذn=HW7VϪT*^buhtit%v|j{=qb1\NE+tEPh B.^Mwp_^zǫadEf[bT͛\RZóXʮ` _|P 2%mP*~^A\mT&iOKdae8CQ.mz\RMCac8c ߲#WY\g)[0*/VFCv~vL`2Z`/-"MW;;w[+"^Ctim-Q*^ 477>/R`Y|k,q|ro~ԋmԚ轔R'Rm`y:>جxX8$[G 65g Mky< M}jq6tPTn06XqU!22j*|>G\~|"s^ab8<~ux|:s@@$cCM$zJ(#ᵕ)<]/(L8(.m(G]Ih<D"a'Kf{˜}껽v~%e(}XRSMt[{6H40j_ FB ]'Ven`q[aOIJA04oFddA#=PukӤ # mtnb,!]aAwL~c{?|՛Jϭ13>Iq]2X$Ti={YѬ9}-5&}.'G?$eLѠ6 - V>}}OcG,.! $ i4~rɚYajNf,'Yd B* 0ѻT1L>4F)ى(,hXy30nr-?}vt" DiTe, wWsZ2w2u//"i[/o`3m"`cd R dzdzc\o_Tvvvy:m ,bRPȤ*˚CH W~Ac]\tK*Crm+iR ٺVEoF:M NKaj~9*'зX,-' @\ޖPeY1Ü=r?M2ϰm LH nBꊯC4Q׶m+5j )T:cj]JVO_dIΰIu{&#`wKuJV Y\JV2=3մW]a5,BgVtp_IRr<^ ւZ䷹LZ릋WpLV:;PdG.\G25;#;?0ULې\IQP-U=)aXiS@)aXnv$Q#6=5D˰ݬUu/4680pNz %_b;z(P?,Uoi2yjH}I&j!og%5B[WWQ) kM@y$L -Iʈia0$#q)-5x#a={۱1:Y9Nc9s=ҥ)D )ǐp9N5g٦Yv0ˤ(ws8[򇷅<_+>p]XRXZ 0&*[38~} zt=;09uɼ)uGj~~ף"UD/%n+p[al留P\%)p=mVSi^G~oRA؍CoF\4Rٴʊ0--Q!{C͗^>GPVK (6rv:MŅ-* A9*1iBeYhA7Sg|%DMzm30Ёq'|ҋB27E2>0qC|ؠ7rlO e@U[ZZyw'Cx3]SyhjRORz?"+z\'$}MO/_QGʼ c4!.q '-YYaK?vA8(:F玸%5o$ӮuWbA;PCYT.逓xn/FKțmhC2PQuh}h\HY;2^lHTdQE`)2~D$"ۺYM$65:&2uͦt :q~e3_L{'wQ/;QmÔH5j*àś6r whؤ707+ֲ NUIvƻܒY45͎7^y꼶߿}7َ @n+t)QI& q!g/E+zk˲ n+;;VdLBVg3hԔI&8LCq̿F[^4VwCC=N*$т`T{ eKak fUiV{QNjmASqBzQ9-Mv?'ED\mg7J F4 9s CeMHV.ZwHy_6,([}uH} Xdrj8t@HW͖nkt'h+IZA0/6@vt5 yJ4;}f%CϺA7 IB_r5ɋ)T,` 3N>)?ِBHOؤm}DzԺz]J6d[8oSld*5g5`J rcB. HB~-Jz}۫6v_.B5E9+/W-D6m^ ]'xCV1QSڊ/ p]B&3CBޖDiَ4Ahm5ٿ:v I cXt䫠}~Z+/ ״0W;qqcxXk"V5XH'(|1E#9g V.S$[!ͰYwl(Ы9 eI5K#BN.S$IW]rG 4AR!aT'),嗜BIJ oZ, ].A~Eclj,T",yCGx#gfw%)eCJJvE7b.lbe]ǤlQi6 גbFn5~UW'"#- y ]K(9{$G D/j>Z¸p2/#d[Rb8_m+Wzp'9K{MI.*-DUȠZ<5[A bÏH-|yqwiI렃xɂxxD'ogS:BdWϏ~yW1v S,m+V*lkŲޥoA| {;<9qjw7$-"tAOv $njhl_|EΖ2ԆO;[*_MD_UJRvrD ]u ?a-ː<&"dޒb E1qkM9){f9 @%y}$iԄdJƈ0! sI4[Aw0à&' W7\/oAp4H!aDDsSfz;|4yPOg=F̾&%ѥiSL&ILoX_P 6\.? ۔S myW.VVq j1]q-fq"䣉X )L%F$-21SR򢔏*d]qv>ŏ;~ &5ՍʑfTn\6;R#BBPHkNQMGNhÛpf-w g nr?}DJ0&$`6 z*DI9J0:|B#KIl=UR(K!1}eRUA@BAq,EQKVZG5E.zt"a4AIt_+94UK`nZHU. Y:eǏsF)Qg.qc_Ar_Cxv $t4h¨+$dHPiaSizuMUcyd\qwnot9^A'=2/~f<,y_]B"(L@Uc{ +1[mb*91ze p'?_g)nyV6;˧r} ,v6lLwȑOa:Nթ9*VF3r g ^/FʅS&쨿zn=> 6ߋڨh|@8$=|u'kUm?g4J*T9ivc#wݶCUUaE@7a?/T|Iul4SjKBbq 6KXF*,*TMv3d|Ir=JE`Y(AZwkEur0MRbJYRso|_ `pIiokH;;-wj]@3m(W\@슳5&E"e|@rGI#Վ)I>]vMkbv LvM?c]v-`q'kXtcGw yq"SJrHI N؃gӬAh6JTIse\;+qI+rFS -9 vܥTYGى^7J_K l&2K-*nHk,~ mr-ӳt6E\s)zV 4=Hd&0BUNT/L($iIPLm+Q1D?.S'L*N$f 67=559qЏ%[FeN}:٪Jf(K@OP!Kdb nGxHXՒ|Ɔ 9JNѽi}Ced 1 2B&1SFџĽo)Fa.0A Ԃ"]IAhļ%dfhu%I[g;%4CY %{6oFҏ>9/]|02⾰xY_': ,de:S!#eF&F- 3IF*ȸ*vee6~Bej$=%jp~Z\PߜZ TXormg_IIHь³IdM&r ##c0|N/r[{hIXV2pi@7X aD~oCm(*„h]ߝ|?z?__O_(n˿ןNqƦSˇEQ~\vN^OOʸ'6~+vqxPxiaQ|ACRE+xv(>? qK?(mto\]sya.z^ %r{F>j~GWy˳vZx.Æ/{05 mۈ~jryRZqto/ h7<Ynũ{]k?"6{|X>9 냈VB7S:i: K%G$mrC"0_KPla+ r+^i!G1"v=bb٥!_J}\&hxyоA,Q=xw8! (PG(HN؀dBa6W\\={\_ v;7hT+J}{oW+/lvn#[?3%0j5g{3Vu$ۡb9C ,*kEe- <.gwa[Gap-o;t*t/{.tv+^={m:{nKknjuk.`f[ jLZݩo;~-]ܶmnSȚ4Do/dCq@3չQy*ݒ4zonMz&虮)_=@+2ya`PYbBcɰ7;fV1x5[ ?vFsf^1LiqM7g%5v6k8w ԫۺ MTn_yЦ" ?As˚4 Z^+>@myoإ;ˆxNs/!®CJM Ql'x;,,IcjMjZ@N*Jr^vnOZ44OKSv 9q bQ'.B.T b{['Ě=@\<,IPgh O Ĥf.^Uגt'P{>w#h-/ /Kиp]5{Ne''sٴ9+ *hj~T3f3J`Z3N,I2o"o H޼1Hcj2f9sWI-Lxc8,ﭵ kt8nrrжSP~2aS؛-gYJEN&˜LAc9>18Sߛc4ۃ~r$ Um!Ъ!jַRa]t<߾^tuZ썡Y,E傢:Fw %C/zw.F `ͧN@aD%|v??6G`c9G}Ηtvs#[:}=?5|%9S= oSϩJihN#^޺U ETjr_%iKL!eҔkhzDˊ\=MםͼŘEdMa Ofin`VпWk>ƾjy+K7\Zs fKvobb_FbX'6O ;n<<`5z<5 -m`@uriyIrB[ꝪEc)60f8nr?}x/Ke`/GŦ1Zmժ? :Fh)JkkxCF$PGFt/(؋8v %S'v͌X{0"1bRuሬ /~+Gڍ >t['(A.l:0{?D{h%tWBלIMqkCWuf [uN`8 4,x6{L8[3nTߪJC;ޫR!0\2p\~V67+kWuvvwLBTNDk෪]ͦ!lf[cUrř|֕;U\ ոۊ?XeПCoyk·d``/Pc5r+Tn! (v|ݬ'i vw6L 80XQ 7Pk{ۣB cQZdVPMp 1QC59QHl# ,qv,cv6s8DIy"5LC447QE vzss߳, s4 F?;vrҔ{ =g%MXGV.NtaY@G2nov.Dvvr|W 2TY=Q0"#l+gw Pf0 ^ŏQWMω4x/0Mũ=cTss]" 6R&؊.27%?vwaGuKMXT%L.\6MiȭLwܝH%T?] !lɔc3`8,C5#o 8ʒ >w+bȫiM-x~n,eMFӠބ4_}aT5m ESٮbPF,^BlZ(5,l*֙3I܎}xP`wn☚S":KҸhzDLJ]Ќ~q\8BU8By!KKW 1Y{ؚ#'Nu'lSR\$021sK٨ż6f~3L2Ѽ"Ҙ: >tN^iZYwvۦgy"FaUyW[CTcfu`S1dSh gғ5݄C<0ql0lrNླྀvHG8rr|f΢e.@sb [ќӤHC4qH2%iL;ѓ̔k΋?VDjwa t]$ғi-d@W (n';p>x\Dd.P.n&*8Sܡ*_v!jK%FX,6SsPyw}5oNJ12L!Faǭ)Pz:MUmzp`oxrB`1(E^\7Fߞc8`|˩o;[yߗsYbܳ_m`7cSá0zNQF蜐L|ƭgnRT9/tΩB[s{}+g8'Au3;`T'EFVݚiӰ? oI1 ju1&аQʜ?XfS/=GTf+N޼$7]X͡/ל?weU8晙7 sQXA2,>>|.,]S#8 tw P-x|SS5Y.#i/+EVfjD3Njjأ@2Ș[dbG/ ^+[tOdX !k%疤.?cYnK?]ԚWL-v{~?v_cmw3Mڄŝ~)`Ɵ9VŪVN>@e4}עjsWô$-BVRֽZ)zSq`iփbJqzkQ]/m-!Nb]?Syk Xl٠AuNՍV޽ߟ/M,]V˻u`=[.b+X2yaX+{he.=1P$ݮSˑt;xc4;YommeIctjΚ; 6ͬEebwsO}|"՝zk@db6FHfMh}spڜ&D5oat$FUV y;-8LkBcnr^Gc^NϞ632`@/q^4dT-rYPsZf;rN/t%őگ>K,N FRCChc}#EHMDh ܆0ODgT͒x_՟@E=oSh~䛛(y7!ԾQs~^T:AZ [iοvRԺSdwvs ucXdQm槥űX<Ѳ$M"$]Rۦ!GhQgc:7sk>Q ]7|# L[A毱m&sE_>_Z{9X8Y-)TbQ9 e`4uk;B^E]jVZJ--2LlI\[ߛAo5 v&Ƿs=#iI `YD|r?$#:39@+  ҋێmԞ63ul.~8#m%v3F۴q7I/4K$Jbd; F fMX'b{xҙguIfM,檲9ga?ޚNM@[s4aZ : 0I k)e,tiwJylzmP`N-i2wil65lZrkX9B@n#ŵxFFW,r|`$L}32=x$77/|\g:3b7<3mݓΠGN~q*֣ں(9N [V(%1%7KIbDxE}Lwݬ9vY7dr ΍'P= ]o88wW(&׭aqL^L"H7~\^")ml; Q]Ţ[-tң|c h I{eyfCX1ǃ6h/eIDnӋZE2z tbXc~!&θ[H?H`IF_ ^s&U^Tr'{;"o}Җ3ǔ MR"&c4ߩW+YY]|?z?__O_(n˿ןNqƦSˇEQ>u Q(Vc$3si7OtN(x{r+$}J$3IE vH׎ۏPa)'-V>}.s wn7/l=w]< }.~:oAJ K׏yl\yU 캝B2ūp6܎كyllwԫ֢AKa0Pyfn.ut%aCCxL ԳNFNK%Ge~Hk Ӷ76lRu~$qԿv4^Cсc#v)]OreT^x,y̫ksĉ T=fmGp3̣RJ?8zU&+ݎ8o'^KS `]߫䗴@n:]rɧ 9WNI̮jdC'g Mј%:4[9K]ԁN%=o4Q**9vS+_^[UU,e_t&94qٶAmuۃ@.5VN L3_iPsXjO}k.f~b>6U}/왡AMc 4O<2y,]%𮳳9, n;#;CgZ"gv7Vug;cC"'gǻ2hE<Woyͱt7s>Čl y`&qʫ{;瓁PݝNGӐO]1~:>UfX:>y5)4jVҴwnVy`n Ml3.P~-I И=2~cyIoIT=4斳<*n6qJjbfɾZuU4';P $-ٞxާ~ƭnB }-MoIZ$4^?sckhԙtlYa^EUڇ-m`0/iFX&|Rȅ`T艝L>mp.֥{ͻXyiϧ*3o/g~866:9֖6N}D0rc{l4*lis<<[7W+ћ66L}6O.ir,LyS\ܰ9lS|7g3ͽ,eL؜Z%m0f]&67uoEuԫ|:Q_s}ˁڏU O> gš AmѠ_==<~sX\ xrCu)nm ptMҏ^z:u":Ó7GnGynN2NTYPS5[Hb.ؿ]tR]H+h%\yH ͐Z>K  ۧeA1[KUJ9mX?=DmzR:7 -]SNq=h}(ğbKZ3 X?$*dBY (|oO=X^]^JLr} H$^ kj2A.66ZWny=Irsǝyթ;G4ތb/Xdc2?yL=j5^[xӣGOjJERX;u.adoAWC%k`?_TujN nv$ {pܭ7Gt:i`JpqUǭay>u5ϣ[N;.>݋B{T({>".~MCC_5EVԩU*|8"98qG_I$,3"!Gnn h4 ,^XUE Ǻn{Dpx0 BHH%*V@kX>]5D4hdEz ۉJ3yָr;z.TvNӏA3q//G;~t^h [^/72Vw75A %~ IbKM `ɨ` ajeQ(B$= C-^n@?̊8 `/,kL'PsTdDi:ͫ秿?99GoW=;|&OWoO8yr|OxrO_G D|ٺ8:~_P_^<:FO_ P6ut^<~>?cl94D~rrz''ۓׯB ǯ@//On;oCɋՓ0Wyr˯W/$~>,8zC &œٓO~9Z~'(O,<}u|z?a'Goœ7 O^AP5\jo&cyv+Kv$3qYj@G(0qO}ERBQzl&~%V(dExxb7${b"Iiza**nbsV,>T73u5!:nωZ߯|L ekq77]?X_4 ^h,)ہɲ HWkH I.#r"= )]DSZsB bAIJ_jE7Y=~w aa`!{m!w%@t;% lYnE8Вg a@+ޏ } $j/0y'mV\{> _]CTG |%1WsߪjB檑fJpVf gaV-VYqCfřS*]9NptD't3.EKrˌUVbzDL65IpK@^m~.V_Ak-M+sn޵wm)&tz%GIi׉tSWĚ"uIʎh?!ɵ޸[9O 0ܲVƋ(+1ÜnTݚl|~W_tM>/o~ڧ뿵KOSsU뿵>BJ__W?Y[y>x3$-p*kDWT"5c\樉#FmMwڂ?drirZf..ALvqi %zGfGʒ}߾skv £fAd3t\tg^%">.VUG}@I_Er+xdij]p ,(brᷡ}=2 mPNO:!"{8 #MQAEx4gk[Lq'PwL{<%ysaTAAZdp)uurõ ~b;,/"ێ] &ΔƴH|D%A?Đ BgvFT"gKci(!ul lzX8B[B0{6r~i04ӰCt~SO_y\nmگTvUo)jA!5e =o\Ry>V+[I m{x熪eo R Oֲz"i|^9`^d^5"j3D*8xf*#Į\ =qoG$"]odW L~?2^p [u C*:u[X֮e7T <$dQH9T[vT~'N|&Tgql&mǾKF5p;2Dj( ƔlQIK]eҌ-F`{#Uxxq'q ϼYMx5.a]1Y|bF*l)*wEqzRT/&uDyh5(t15^l!5՗67˅bKZIs#SjK[H: s#x<~~@j嗎iXs/-T* osI4A?hCWorz+KpD,vvJ-M\@T(朣e0BJZNrMd#$-OO:VyD7K%Lj5> qWkVD0?cX=#^Ҥax b(}Q+Zsx,Xz|:x W)#fقV+ 1&ӶX`s\8IFYAhzAi̼ Пm@+R T.ѥ\WlHh,`O I|FcG*hPV݌w LB-d/Jܾ Į~oybE1}ݤZ,Ś2mqcaS_6L;r|}X+-dE9wAT@7$*$ZG/VsQ-f6 c1LHh_+Q*1u2(:K6' f Xb̨8Ҋ>"Ql/QH*`+V$ߘytU~/E#K+rab4mQ ϷvsS;nunO]dPĿj\)RK?UDA%l/+sä>x kk?}gQEADE5Ԇ͙dV -W7cZJ&?v{XMM3%v˂xsL3i{>p,8iL9qSY>d/#xVm69ڧI?C|hȡG9:sGV’47 `@N#3pLBג1%yJHQǃǵ:VVc/;"c⛽+\.IgS`ν[AǻhG̉#nGw.8#ڍj|? p{]{.ZTZq7wgԠ8~$gʏQ0He|j>-߷L[_Cb ސ4sըlu #'R&1 ` 2Ƒ!4pTr#3}LH5ID{x K3͒i/Co0m'Zn GFΤAwEB'i ަ-@y4W8;NC0g{<p'NiR?u8q;W2P·ίp}ujb1;6yy54Ӕ i $I=^K_"]S]}J)_P:w؂ ،]E/`ݐk:9ĸw˞o'卍# ٤ &y{토S^q4H83T0I8`')/Ǿ!]j7قU;é"Umks$2㼌nDS` P1HulȞ$XO x h<=;Rg( q)Aí]8ਘ"(@Xxi - t#{ܵ<=Al B񚦖ǝ> a 83I_4|g"Amqǡ$Jj8 36(3{(!o b : ;8 RAF%jȃ6wJ pq 4K73H|xvpj5b3wyӞӳsr|Hs\B4T"̠ W0JJ@`{Yt_q0+|'1ULÇЃ0x:GT,>hSqW*Q9ϻIv|Q= 8&YO|&`4G3^rq秜:1s pe MPvH9t_~,%a4Ӑu3%8{HpZ`~Qןs击 $|Ed3JN[P1M8\ahUZ9`k>9 M lb5-)(%ud:%$xםS$ņΧQ' zC$/|UHY8je-@kU/gڍgi𔁵]CͰ|?)AM%#1@QF{#d)զ>Nd#O}4Hƣ{!A9+7Ѯ>g΄EӝLY UŻڇw F4>ѐ|8RS?i$:Gl(qzɿp!X=,f  5dOzlfǵhzgV<˚O)q oo_wV?i%UՄ%m}7nݠ߻Al޵~cǵzgֲ]M🫏{skx"2+k,(<2ZU%J7 p9v`:F/?g7}Okmetadata.gz0000644000000000000000000000602200000000000013401 0ustar00wheelwheel00000000000000M[B}!@nw{&M%6cITHjwݿ3$KD7D8 g|Fa)ylVxZ=<3#drUcY:{JCjя*ջUp O⊧i aP6+΃ktq\\ΊT*g4;}Wp5%9OPP袌Mx}ȸ֔D]V ,#({rLgvZ[hbSS;_@TzöM,O+AlEsdU;o nm#TR,T煮i}|Cݷ厧Q$sD`GF/Z*\ +9}}1œ^aTn6'H<)s *)M$k^iiv`V;e&f,Q4bDi#_faD; k9 NdC5C5<t f '%ZbƾUBҖBC,W5ւ!{ "`ix;!9l7DI}2ݨ-$/<%dPRT|A&CixP=h͇JH{5Amv l)m:b =6 0!Ax^ 2JjRl aĴAhm27 _K*b&FN3`s@@{Hce@6결 t\dݍ-el؀]4F?gG'karx"l:쏌qdq]ٌZ^u8qH}Ŏ#8z8:MO#|!mqĀ\8e0O@<d|ghVd!֋,9rcg-Ӻd0- v޲, \  \$9ĕeԳNa X &st6Cɇ{a1'"Y*XlZ)-vwͧu;U!b<0}&N>d8|(}cEV B IߓoĶTv`^=|sRK(Ig<@E`T4DLjWCƱ @]k~=XoKR0 Uܔ*AabC4B D0ai @hx+q49 Hx4I&tK? K0^pdau]u!Q\)d2~EAS"3NxTnIBɂH.Nk@s͂`y" 6K]Fu2VܴȰC4d|a{uuLC )ƪ"5Z1)y_Um">-_0Ro`O#%Tbc +FZbA2($Qxa 2%LPY9kE$$K#9m %s>TOԮ~sٙ=G/+t8xn}Пo Zq1 k\$2a-w:m0/fgNau ZݵKXHۼWS&6tkϔ&es܏ky2O-^_CFRCV#6dΖ /apWS֨RxYvB /Pk*v PK"ʾs#[wLXHb%D*T5AWʴj+pE8)V|s^?p#d{2gK25𻛿W>{x|>1w3:w}Xa^m Un+J}{wzU4: Ys}"s6CḩY ܶ!Vz w씅~44fPXƒA9L Ly3K#6T5 %4}UGhMIFnry6,!a<!+Z ѷ zGP>OduR/%u#0nlsVz aܶޯBGwR:adǴ= 0") if s.respond_to? :required_rubygems_version= s.authors = [%q{Nathan Weizenbaum}, %q{Hampton Catlin}] s.date = %q{2011-04-25} s.description = %q{ Haml (HTML Abstraction Markup Language) is a layer on top of XHTML or XML that's designed to express the structure of XHTML or XML documents in a non-repetitive, elegant, easy way, using indentation rather than closing tags and allowing Ruby to be embedded with ease. It was originally envisioned as a plugin for Ruby on Rails, but it can function as a stand-alone templating engine. } s.email = %q{haml@googlegroups.com} s.executables = [%q{haml}, %q{html2haml}] s.files = [%q{bin/haml}, %q{bin/html2haml}] s.homepage = %q{http://haml-lang.com/} s.require_paths = [%q{lib}] s.rubyforge_project = %q{haml} s.rubygems_version = %q{1.8.4} s.summary = %q{An elegant, structured XHTML/XML templating engine.} if s.respond_to? :specification_version then s.specification_version = 3 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, [">= 0.5.3"]) s.add_development_dependency(%q, [">= 0.5.9"]) else s.add_dependency(%q, [">= 0.5.3"]) s.add_dependency(%q, [">= 0.5.9"]) end else s.add_dependency(%q, [">= 0.5.3"]) s.add_dependency(%q, [">= 0.5.9"]) end end stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/0000775000175000017500000000000012206724733025203 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/0000775000175000017500000000000012206724733026562 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/.yardopts0000664000175000017500000000050712206724733030432 0ustar jamespagejamespage--readme README.md --markup markdown --markup-provider maruku --default-return "" --title "Haml Documentation" --query 'object.type != :classvariable' --query 'object.type != :constant || @api && @api.text == "public"' --hide-void-return --protected --no-private --no-highlight stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/CONTRIBUTING0000664000175000017500000000020112206724733030405 0ustar jamespagejamespageContributions are welcomed. Please see the following sites for guidelines: http://haml-lang.com/development.html#contributing stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/REVISION0000664000175000017500000000001212206724733027734 0ustar jamespagejamespage(release) stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/init.rb0000664000175000017500000000111612206724733030051 0ustar jamespagejamespagebegin require File.join(File.dirname(__FILE__), 'lib', 'haml') # From here rescue LoadError begin require 'haml' # From gem rescue LoadError => e # gems:install may be run to install Haml with the skeleton plugin # but not the gem itself installed. # Don't die if this is the case. raise e unless defined?(Rake) && (Rake.application.top_level_tasks.include?('gems') || Rake.application.top_level_tasks.include?('gems:install')) end end # Load Haml. # Haml may be undefined if we're running gems:install. Haml.init_rails(binding) if defined?(Haml) stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/README.md0000664000175000017500000000771512206724733030053 0ustar jamespagejamespage# Haml Haml is a templating engine for HTML. It's are designed to make it both easier and more pleasant to write HTML documents, by eliminating redundancy, reflecting the underlying structure that the document represents, and providing elegant, easily understandable, and powerful syntax. ## Using Haml can be used from the command line or as part of a Ruby web framework. The first step is to install the gem: gem install haml After you convert some HTML to Haml, you can run haml document.haml to compile them. For more information on these commands, check out haml --help To install Haml in Rails 2, just add `config.gem "haml"` to `config/environment.rb`. In Rails 3, add `gem "haml"` to your Gemfile instead. and both Haml and Sass will be installed. Views with the `.html.haml` extension will automatically use Haml. To use Haml programatically, check out the [YARD documentation](http://haml-lang.com/docs/yardoc/). ## Formatting The most basic element of Haml is a shorthand for creating HTML: %tagname{:attr1 => 'value1', :attr2 => 'value2'} Contents No end-tag is needed; Haml handles that automatically. If you prefer HTML-style attributes, you can also use: %tagname(attr1='value1' attr2='value2') Contents Adding `class` and `id` attributes is even easier. Haml uses the same syntax as the CSS that styles the document: %tagname#id.class In fact, when you're using the `

    ` tag, it becomes _even easier_. Because `
    ` is such a common element, a tag without a name defaults to a div. So #foo Hello! becomes
    Hello!
    Haml uses indentation to bring the individual elements to represent the HTML structure. A tag's children are indented beneath than the parent tag. Again, a closing tag is automatically added. For example: %ul %li Salt %li Pepper becomes:
    • Salt
    • Pepper
    You can also put plain text as a child of an element: %p Hello, World! It's also possible to embed Ruby code into Haml documents. An equals sign, `=`, will output the result of the code. A hyphen, `-`, will run the code but not output the result. You can even use control statements like `if` and `while`: %p Date/Time: - now = DateTime.now %strong= now - if now > DateTime.parse("December 31, 2006") = "Happy new " + "year!" Haml provides far more tools than those presented here. Check out the [reference documentation](http://beta.haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html) for full details. ### Indentation Haml's indentation can be made up of one or more tabs or spaces. However, indentation must be consistent within a given document. Hard tabs and spaces can't be mixed, and the same number of tabs or spaces must be used throughout. ## Authors Haml was created by [Hampton Catlin](http://hamptoncatlin.com) (hcatlin) and he is the author of the original implementation. However, Hampton doesn't even know his way around the code anymore and now occasionally consults on the language issues. Hampton lives in Jacksonville, Florida and is the lead mobile developer for Wikimedia. [Nathan Weizenbaum](http://nex-3.com) is the primary developer and architect of the "modern" Ruby implementation of Haml. His hard work has kept the project alive by endlessly answering forum posts, fixing bugs, refactoring, finding speed improvements, writing documentation, implementing new features, and getting Hampton coffee (a fitting task for a boy-genius). Nathan lives in Seattle, Washington and while not being a student at the University of Washington or working at an internship, he consults for Unspace Interactive. If you use this software, you must pay Hampton a compliment. And buy Nathan some jelly beans. Maybe pet a kitten. Yeah. Pet that kitty. Some of the work on Haml was supported by Unspace Interactive. Beyond that, the implementation is licensed under the MIT License. Okay, fine, I guess that means compliments aren't __required__. stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/VERSION0000664000175000017500000000000612206724733027626 0ustar jamespagejamespage3.1.1 stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/VERSION_NAME0000664000175000017500000000002012206724733030422 0ustar jamespagejamespageSeparated Sally stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/extra/0000775000175000017500000000000012206724733027705 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/extra/update_watch.rb0000664000175000017500000000051312206724733032701 0ustar jamespagejamespagerequire 'rubygems' require 'sinatra' require 'json' set :port, 3123 set :environment, :production enable :lock Dir.chdir(File.dirname(__FILE__) + "/..") post "/" do puts "Recieved payload!" puts "Rev: #{`git name-rev HEAD`.strip}" system %{rake handle_update --trace REF=#{JSON.parse(params["payload"])["ref"].inspect}} end stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/rails/0000775000175000017500000000000012206724733027674 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/rails/init.rb0000664000175000017500000000007712206724733031170 0ustar jamespagejamespageKernel.load File.join(File.dirname(__FILE__), '..', 'init.rb') stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/MIT-LICENSE0000664000175000017500000000207412206724733030221 0ustar jamespagejamespageCopyright (c) 2006-2009 Hampton Catlin and Nathan Weizenbaum Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/0000775000175000017500000000000012206724733030057 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/0000775000175000017500000000000012206724733031030 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/CONTRIBUTING0000664000175000017500000000020112206724733032653 0ustar jamespagejamespageContributions are welcomed. Please see the following sites for guidelines: http://sass-lang.com/development.html#contributing stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/TODO0000664000175000017500000000267712206724733031534 0ustar jamespagejamespage# -*- mode: org -*- #+STARTUP: nofold * Documentation Redo tutorial? Syntax highlighting? * Code Keep track of error offsets everywhere Use this to show error location in messages Just clean up SassScript syntax errors in general Lexer errors in particular are icky See in particular error changes made in c07b5c8 ** Sass Benchmark the effects of storing the raw template in sassc If it's expensive, overload RootNode dumping/loading to dup and set @template to nil Then fall back on reading from actual file Make Rack middleware the default for Rails and Merb versions that support it CSS superset Classes are mixins Can refer to specific property values? Syntax? Pull in Compass watcher stuff Internationalization Particularly word constituents in Regexps Optimization http://csstidy.sourceforge.net/ http://developer.yahoo.com/yui/compressor/ Also comma-folding identical rules where possible Multiple levels 0: No optimization 1: Nothing that changes doc structure No comma-folding 2: Anything that keeps functionality identical to O2 (default) 3: Assume order of rules doesn't matter Comma-fold even if there are intervening rules that might interfere CSS3 Add (optional) support for http://www.w3.org/TR/css3-values/#calc Cross-unit arithmetic should compile into this Should we use "mod" in Sass for consistency? stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/sass.gemspec0000664000175000017500000000270712206724733033354 0ustar jamespagejamespagerequire 'rubygems' # Note that Sass's gem-compilation process requires access to the filesystem. # This means that it cannot be automatically run by e.g. GitHub's gem system. # However, a build server automatically packages the master branch # every time it's pushed to; this is made available as a prerelease gem. SASS_GEMSPEC = Gem::Specification.new do |spec| spec.rubyforge_project = 'sass' spec.name = 'sass' spec.summary = "A powerful but elegant CSS compiler that makes CSS fun again." spec.version = File.read(File.dirname(__FILE__) + '/VERSION').strip spec.authors = ['Nathan Weizenbaum', 'Chris Eppstein', 'Hampton Catlin'] spec.email = 'sass-lang@googlegroups.com' spec.description = <<-END Sass makes CSS fun again. Sass is an extension of CSS3, adding nested rules, variables, mixins, selector inheritance, and more. It's translated to well-formatted, standard CSS using the command line tool or a web-framework plugin. END spec.add_development_dependency 'yard', '>= 0.5.3' spec.add_development_dependency 'maruku', '>= 0.5.9' readmes = Dir['*'].reject{ |x| x =~ /(^|[^.a-z])[a-z]+/ || x == "TODO" } spec.executables = ['sass', 'sass-convert'] spec.files = Dir['rails/init.rb', 'lib/**/*', 'vendor/**/*', 'bin/*', 'test/**/*', 'extra/**/*', 'Rakefile', 'init.rb', '.yardopts'] + readmes spec.homepage = 'http://sass-lang.com/' spec.has_rdoc = false spec.test_files = Dir['test/**/*_test.rb'] end stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/init.rb0000664000175000017500000000111312206724733032314 0ustar jamespagejamespagebegin require File.join(File.dirname(__FILE__), 'lib', 'sass') # From here rescue LoadError begin require 'sass' # From gem rescue LoadError => e # gems:install may be run to install Haml with the skeleton plugin # but not the gem itself installed. # Don't die if this is the case. raise e unless defined?(Rake) && (Rake.application.top_level_tasks.include?('gems') || Rake.application.top_level_tasks.include?('gems:install')) end end # Load Sass. # Sass may be undefined if we're running gems:install. require 'sass/plugin' if defined?(Sass) stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/README.md0000664000175000017500000001505012206724733032310 0ustar jamespagejamespage# Sass **Sass makes CSS fun again**. Sass is an extension of CSS3, adding nested rules, variables, mixins, selector inheritance, and more. It's translated to well-formatted, standard CSS using the command line tool or a web-framework plugin. Sass has two syntaxes. The new main syntax (as of Sass 3) is known as "SCSS" (for "Sassy CSS"), and is a superset of CSS3's syntax. This means that every valid CSS3 stylesheet is valid SCSS as well. SCSS files use the extension `.scss`. The second, older syntax is known as the indented syntax (or just "Sass"). Inspired by Haml's terseness, it's intended for people who prefer conciseness over similarity to CSS. Instead of brackets and semicolons, it uses the indentation of lines to specify blocks. Although no longer the primary syntax, the indented syntax will continue to be supported. Files in the indented syntax use the extension `.sass`. ## Using Sass can be used from the command line or as part of a web framework. The first step is to install the gem: gem install sass After you convert some CSS to Sass, you can run sass style.scss to compile it back to CSS. For more information on these commands, check out sass --help To install Sass in Rails 2, just add `config.gem "sass"` to `config/environment.rb`. In Rails 3, add `gem "sass"` to your Gemfile instead. `.sass` or `.scss` files should be placed in `public/stylesheets/sass`, where they'll be automatically compiled to corresponding CSS files in `public/stylesheets` when needed (the Sass template directory is customizable... see [the Sass reference](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#template_location-option) for details). Sass can also be used with any Rack-enabled web framework. To do so, just add require 'sass/plugin/rack' use Sass::Plugin::Rack to `config.ru`. Then any Sass files in `public/stylesheets/sass` will be compiled CSS files in `public/stylesheets` on every request. To use Sass programatically, check out the [YARD documentation](http://sass-lang.com/docs/yardoc/). ## Formatting Sass is an extension of CSS that adds power and elegance to the basic language. It allows you to use [variables][vars], [nested rules][nested], [mixins][mixins], [inline imports][imports], and more, all with a fully CSS-compatible syntax. Sass helps keep large stylesheets well-organized, and get small stylesheets up and running quickly, particularly with the help of [the Compass style library](http://compass-style.org). [vars]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#variables_ [nested]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#nested_rules_ [mixins]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixins [imports]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import Sass has two syntaxes. The one presented here, known as "SCSS" (for "Sassy CSS"), is fully CSS-compatible. The other (older) syntax, known as the indented syntax or just "Sass", is whitespace-sensitive and indentation-based. For more information, see the [reference documentation][syntax]. [syntax]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#syntax To run the following examples and see the CSS they produce, put them in a file called `test.scss` and run `sass test.scss`. ### Nesting Sass avoids repetition by nesting selectors within one another. The same thing works for properties. table.hl { margin: 2em 0; td.ln { text-align: right; } } li { font: { family: serif; weight: bold; size: 1.2em; } } ### Variables Use the same color all over the place? Need to do some math with height and width and text size? Sass supports variables, math operations, and many useful functions. $blue: #3bbfce; $margin: 16px; .content_navigation { border-color: $blue; color: darken($blue, 10%); } .border { padding: $margin / 2; margin: $margin / 2; border-color: $blue; } ### Mixins Even more powerful than variables, mixins allow you to re-use whole chunks of CSS, properties or selectors. You can even give them arguments. @mixin table-scaffolding { th { text-align: center; font-weight: bold; } td, th { padding: 2px; } } @mixin left($dist) { float: left; margin-left: $dist; } #data { @include left(10px); @include table-scaffolding; } A comprehensive list of features is available in the [Sass reference](http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html). ## Executables The Sass gem includes several executables that are useful for dealing with Sass from the command line. ### `sass` The `sass` executable transforms a source Sass file into CSS. See `sass --help` for further information and options. ### `sass-convert` The `sass-convert` executable converts between CSS, Sass, and SCSS. When converting from CSS to Sass or SCSS, nesting is applied where appropriate. See `sass-convert --help` for further information and options. ## Authors Sass was envisioned by [Hampton Catlin](http://hamptoncatlin.com) (hcatlin). However, Hampton doesn't even know his way around the code anymore and now occasionally consults on the language issues. Hampton lives in Jacksonville, Florida and is the lead mobile developer for Wikimedia. [Nathan Weizenbaum](http://nex-3.com) is the primary developer and architect of Sass. His hard work has kept the project alive by endlessly answering forum posts, fixing bugs, refactoring, finding speed improvements, writing documentation, implementing new features, and getting Hampton coffee (a fitting task for a boy-genius). Nathan lives in Seattle, Washington and while not being a student at the University of Washington or working at an internship, he consults for Unspace Interactive. [Chris Eppstein](http://acts-as-architect.blogspot.com) is a core contributor to Sass and the creator of Compass, the first Sass-based framework. Chris focuses on making Sass more powerful, easy to use, and on ways to speed its adoption through the web development community. Chris lives in San Jose, California with his wife and daughter. He is the Software Architect for [Caring.com](http://caring.com), a website devoted to the 34 Million caregivers whose parents are sick or elderly, that uses Haml and Sass. If you use this software, you must pay Hampton a compliment. And buy Nathan some jelly beans. Maybe pet a kitten. Yeah. Pet that kitty. Beyond that, the implementation is licensed under the MIT License. Okay, fine, I guess that means compliments aren't __required__. stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/ext/0000775000175000017500000000000012206724733031630 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/ext/extconf.rb0000664000175000017500000000037012206724733033623 0ustar jamespagejamespageroot = File.expand_path("../..", __FILE__) File.open(File.expand_path("lib/sass/root.rb", root), "w") do |f| f << <<-RUBY module Sass ROOT_DIR = #{root.inspect} end RUBY end File.open('Makefile', 'w') { |f| f.puts("install:\n\t$(exit 0)") } stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/VERSION0000664000175000017500000000000612206724733032074 0ustar jamespagejamespage3.1.0 stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/VERSION_NAME0000664000175000017500000000001512206724733032674 0ustar jamespagejamespageBrainy Betty stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/extra/0000775000175000017500000000000012206724733032153 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015412255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/extra/update_watch.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/extra/update_w0000664000175000017500000000051312206724733033705 0ustar jamespagejamespagerequire 'rubygems' require 'sinatra' require 'json' set :port, 3124 set :environment, :production enable :lock Dir.chdir(File.dirname(__FILE__) + "/..") post "/" do puts "Recieved payload!" puts "Rev: #{`git name-rev HEAD`.strip}" system %{rake handle_update --trace REF=#{JSON.parse(params["payload"])["ref"].inspect}} end stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/rails/0000775000175000017500000000000012206724733032142 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/rails/init.rb0000664000175000017500000000007712206724733033436 0ustar jamespagejamespageKernel.load File.join(File.dirname(__FILE__), '..', 'init.rb') stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/0000775000175000017500000000000012206724733031767 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015012255653646011654 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/callbacks.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/callbacks0000664000175000017500000000146012206724733033632 0ustar jamespagejamespageclass CallbacksHandler < YARD::Handlers::Ruby::Legacy::Base handles /\Adefine_callback(\s|\()/ def process callback_name = tokval(statement.tokens[2]) attr_index = statement.comments.each_with_index {|c, i| break i if c[0] == ?@} if attr_index.is_a?(Fixnum) docstring = statement.comments[0...attr_index] attrs = statement.comments[attr_index..-1] else docstring = statement.comments attrs = [] end yieldparams = "" attrs.reject! do |a| next unless a =~ /^@yield *(\[.*?\])/ yieldparams = $1 true end o = register(MethodObject.new(namespace, "on_#{callback_name}", scope)) o.docstring = docstring + [ "@return [void]", "@yield #{yieldparams} When the callback is run" ] + attrs o.signature = true end end ././@LongLink0000644000000000000000000000015512255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/inherited_hash.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/inherited0000664000175000017500000000272312206724733033671 0ustar jamespagejamespageclass InheritedHashHandler < YARD::Handlers::Ruby::Legacy::Base handles /\Ainherited_hash(\s|\()/ def process hash_name = tokval(statement.tokens[2]) name = statement.comments.first.strip type = statement.comments[1].strip o = register(MethodObject.new(namespace, hash_name, scope)) o.docstring = [ "Gets a #{name} from this {Environment} or one of its \\{#parent}s.", "@param name [String] The name of the #{name}", "@return [#{type}] The #{name} value", ] o.signature = true o.parameters = ["name"] o = register(MethodObject.new(namespace, "set_#{hash_name}", scope)) o.docstring = [ "Sets a #{name} in this {Environment} or one of its \\{#parent}s.", "If the #{name} is already defined in some environment,", "that one is set; otherwise, a new one is created in this environment.", "@param name [String] The name of the #{name}", "@param value [#{type}] The value of the #{name}", "@return [#{type}] `value`", ] o.signature = true o.parameters = ["name", "value"] o = register(MethodObject.new(namespace, "set_local_#{hash_name}", scope)) o.docstring = [ "Sets a #{name} in this {Environment}.", "Ignores any parent environments.", "@param name [String] The name of the #{name}", "@param value [#{type}] The value of the #{name}", "@return [#{type}] `value`", ] o.signature = true o.parameters = ["name", "value"] end end stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/0000775000175000017500000000000012206724733033413 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015312255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/layout/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/l0000775000175000017500000000000012206724733033567 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016012255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/layout/html/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/l0000775000175000017500000000000012206724733033567 5ustar jamespagejamespage././@LongLink0000644000000000000000000000017212255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/layout/html/footer.erbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/l0000664000175000017500000000075512206724733033600 0ustar jamespagejamespage<%= superb :footer %> <% if ENV["ANALYTICS"] %> <% end %> ././@LongLink0000644000000000000000000000015412255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/fulldoc/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/f0000775000175000017500000000000012206724733033561 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/fulldoc/html/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/f0000775000175000017500000000000012206724733033561 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/fulldoc/html/css/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/f0000775000175000017500000000000012206724733033561 5ustar jamespagejamespage././@LongLink0000644000000000000000000000020012255653646011650 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/fulldoc/html/css/common.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/yard/default/f0000664000175000017500000000071412206724733033565 0ustar jamespagejamespage.maruku_toc background: #ddd border: 1px solid #ccc margin-right: 2em float: left ul padding: 0 1em #frequently_asked_questions + & float: none margin: 0 2em #filecontents *:target, dt:target + dd background-color: #ccf border: 1px solid #88b dt font-weight: bold dd margin: left: 0 bottom: 0.7em padding-left: 3em dt:target border-bottom-style: none & + dd border-top-style: none stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/MIT-LICENSE0000664000175000017500000000211512206724733032463 0ustar jamespagejamespageCopyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/0000775000175000017500000000000012206724733032325 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/0000775000175000017500000000000012206724733033275 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015012255653646011654 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000775000175000017500000000000012206724733033640 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/path_spec.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000664000175000017500000000440412206724733033644 0ustar jamespagejamespagerequire File.expand_path(File.dirname(__FILE__) + '/spec_helper') describe "The File System State Monitor" do describe "paths" do it "should accept a valid filesystem directory" do lambda {FSSM::Path.new("#{@watch_root}")}.should_not raise_error end it "should not accept an invalid filesystem directory" do lambda {FSSM::Path.new('/does/not/exist/kthxbye')}.should raise_error end it "should default the path to the current directory" do path = FSSM::Path.new here = Pathname.new('.').realpath "#{here}".should == "#{path}" end it "should accept an optional glob array parameter" do path = FSSM::Path.new('.', ['**/*.yml']) path.glob.should == ['**/*.yml'] end it "should accept an optional glob string parameter" do path = FSSM::Path.new('.', '**/*.yml') path.glob.should == ['**/*.yml'] end it "should default the glob to ['**/*']" do path = FSSM::Path.new path.glob.should == ['**/*'] end it "should accept a callback for update events" do path = FSSM::Path.new callback = lambda {|base, relative| return true} path.update(callback) (path.update).should == callback end it "should accept a callback for delete events" do path = FSSM::Path.new callback = lambda {|base, relative| return true} path.delete(callback) (path.delete).should == callback end it "should accept a callback for create events" do path = FSSM::Path.new callback = lambda {|base, relative| return true} path.create(callback) (path.create).should == callback end it "should accept a configuration block" do path = FSSM::Path.new "#{@watch_root}" do glob '**/*.yml' update {|base, relative| 'success'} delete {|base, relative| 'success'} create {|base, relative| 'success'} end "#{path}".should == "#{@watch_root}" path.glob.should == ['**/*.yml'] path.update.should be_a_kind_of(Proc) path.delete.should be_a_kind_of(Proc) path.create.should be_a_kind_of(Proc) path.update.call('', '').should == 'success' path.delete.call('', '').should == 'success' path.create.call('', '').should == 'success' end end end ././@LongLink0000644000000000000000000000015512255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/root/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000775000175000017500000000000012206724733033640 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/root/file.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000664000175000017500000000000012206724733033630 0ustar jamespagejamespage././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/root/duck/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000775000175000017500000000000012206724733033640 5ustar jamespagejamespage././@LongLink0000644000000000000000000000017312255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/root/duck/quack.txtstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000664000175000017500000000000012206724733033630 0ustar jamespagejamespage././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/root/moo/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000775000175000017500000000000012206724733033640 5ustar jamespagejamespage././@LongLink0000644000000000000000000000017012255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/root/moo/cow.txtstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000664000175000017500000000000012206724733033630 0ustar jamespagejamespage././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/root/file.cssstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000664000175000017500000000000012206724733033630 0ustar jamespagejamespage././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/root/file.ymlstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000664000175000017500000000000012206724733033630 0ustar jamespagejamespage././@LongLink0000644000000000000000000000016612255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/spec/spec_helper.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/sp0000664000175000017500000000051012206724733033636 0ustar jamespagejamespage$LOAD_PATH.unshift(File.dirname(__FILE__)) $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require 'pathname' require 'fssm' require 'spec' require 'spec/autorun' Spec::Runner.configure do |config| config.before :all do @watch_root = Pathname.new(__FILE__).dirname.join('root').expand_path end end ././@LongLink0000644000000000000000000000015712255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/fssm.gemspecstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/fs0000664000175000017500000000416512206724733033636 0ustar jamespagejamespage# Generated by jeweler # DO NOT EDIT THIS FILE DIRECTLY # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = %q{fssm} s.version = "0.1.4" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Travis Tilley"] s.date = %q{2010-03-10} s.description = %q{file system state monitor} s.email = %q{ttilley@gmail.com} s.extra_rdoc_files = [ "LICENSE", "README.markdown" ] s.files = [ ".document", ".gitignore", "LICENSE", "README.markdown", "Rakefile", "VERSION.yml", "example.rb", "fssm.gemspec", "lib/fssm.rb", "lib/fssm/backends/fsevents.rb", "lib/fssm/backends/inotify.rb", "lib/fssm/backends/polling.rb", "lib/fssm/backends/rubycocoa/fsevents.rb", "lib/fssm/monitor.rb", "lib/fssm/path.rb", "lib/fssm/pathname.rb", "lib/fssm/state/directory.rb", "lib/fssm/state/file.rb", "lib/fssm/support.rb", "lib/fssm/tree.rb", "profile/prof-cache.rb", "profile/prof-fssm-pathname.html", "profile/prof-pathname.rb", "profile/prof-plain-pathname.html", "profile/prof.html", "spec/path_spec.rb", "spec/root/duck/quack.txt", "spec/root/file.css", "spec/root/file.rb", "spec/root/file.yml", "spec/root/moo/cow.txt", "spec/spec_helper.rb" ] s.homepage = %q{http://github.com/ttilley/fssm} s.rdoc_options = ["--charset=UTF-8"] s.require_paths = ["lib"] s.rubygems_version = %q{1.3.6} s.summary = %q{file system state monitor} s.test_files = [ "spec/path_spec.rb", "spec/spec_helper.rb", "spec/root/file.rb" ] if s.respond_to? :specification_version then current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION s.specification_version = 3 if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, [">= 0"]) else s.add_dependency(%q, [">= 0"]) end else s.add_dependency(%q, [">= 0"]) end end ././@LongLink0000644000000000000000000000015212255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/LICENSEstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/LI0000664000175000017500000000204112206724733033521 0ustar jamespagejamespageCopyright (c) 2009 Travis Tilley Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/README.markdownstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/RE0000664000175000017500000000272312206724733033532 0ustar jamespagejamespageMonitor API =========== There are three ways you can run the monitor. 1. call monitor with a path parameter, and define callbacks in a block 2. call monitor with a block to configure multiple paths and callbacks 3. create a monitor object and run each step manually Monitor with path ----------------- This form watches one path, and enters the run loop automatically. The first parameter is the path to watch, and the second parameter is an optional glob pattern or array of glob patterns that a file must match in order to trigger a callback. The default glob, if ommitted, is `'**/*'`. FSSM.monitor('/some/directory/', '**/*') do update {|base, relative|} delete {|base, relative|} create {|base, relative|} end Monitor with block ------------------ This form watches one or more paths, and enters the run loop automatically. The glob configuration call can be ommitted, and defaults to `'**/*'`. FSSM.monitor do path '/some/directory/' do glob '**/*.yml' update {|base, relative|} delete {|base, relative|} create {|base, relative|} end path '/some/other/directory/' do update {|base, relative|} delete {|base, relative|} create {|base, relative|} end end Monitor object -------------- This form doesn't enter the run loop automatically. monitor = FSSM::Monitor.new monitor.path '/some/directory/' do update {|base, relative|} delete {|base, relative|} create {|base, relative|} end monitor.run ././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/VERSION.ymlstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/VE0000664000175000017500000000005412206724733033531 0ustar jamespagejamespage--- :major: 0 :minor: 1 :patch: 4 :build: ././@LongLink0000644000000000000000000000015312255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/profile/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/pr0000775000175000017500000000000012206724733033637 5ustar jamespagejamespage././@LongLink0000644000000000000000000000020312255653646011653 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/profile/prof-plain-pathname.htmlstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/pr0000664000175000017500000006076412206724733033656 0ustar jamespagejamespage

    Profile Report

    Thread ID Total Time
    3696392 27.97608

    Thread 3696392

    %Total %Self Total Self Wait Child Calls Name Line
    100.00% 0.00% 27.98 0.00 0.00 27.98 0 Global#[No method] 50
        5.33 0.61 0.00 4.73 90000/90000 Class#new 57
        22.64 1.34 0.00 21.30 90000/90000 Pathname#segments 58
        22.64 1.34 0.00 21.30 90000/90000 Global#[No method] 58
    80.93% 4.80% 22.64 1.34 0.00 21.30 90000 Pathname#segments 15
        20.96 3.23 0.00 17.73 90000/90000 Pathname#split_names 16
        0.16 0.16 0.00 0.00 90000/90000 String#empty? 17
        0.18 0.18 0.00 0.00 90000/450000 Array#unshift 17
        20.96 3.23 0.00 17.73 90000/90000 Pathname#segments 16
    74.94% 11.56% 20.96 3.23 0.00 17.73 90000 Pathname#split_names 307
        17.00 10.58 0.00 6.42 450000/450000 Pathname#chop_basename 311
        0.73 0.73 0.00 0.00 360000/450000 Array#unshift 311
        17.00 10.58 0.00 6.42 450000/450000 Pathname#split_names 311
    60.76% 37.83% 17.00 10.58 0.00 6.42 450000 Pathname#chop_basename 296
        1.38 1.38 0.00 0.00 450000/450000 <Class::File>#basename 297
        1.37 1.37 0.00 0.00 450000/450000 Regexp#to_s 298
        1.95 1.95 0.00 0.00 450000/450000 Regexp#=~ 298
        0.80 0.80 0.00 0.00 360000/360000 String#rindex 298
        0.91 0.91 0.00 0.00 360000/360000 String#[] 298
        5.33 0.61 0.00 4.73 90000/90000 Global#[No method] 57
    19.07% 2.18% 5.33 0.61 0.00 4.73 90000 Class#new 0
        0.25 0.25 0.00 0.00 90000/90000 <Class::BasicObject>#allocate 57
        4.47 1.87 0.00 2.60 90000/90000 Pathname#initialize 57
        4.47 1.87 0.00 2.60 90000/90000 Class#new 57
    15.98% 6.70% 4.47 1.87 0.00 2.60 90000 Pathname#initialize 210
        0.20 0.20 0.00 0.00 90000/90000 Kernel#respond_to? 211
        0.97 0.58 0.00 0.39 90000/90000 Kernel#dup 212
        0.16 0.16 0.00 0.00 90000/90000 Kernel#tainted? 218
        1.27 0.94 0.00 0.33 90000/90000 Pathname#taint 218
        1.95 1.95 0.00 0.00 450000/450000 Pathname#chop_basename 298
    6.97% 6.97% 1.95 1.95 0.00 0.00 450000 Regexp#=~ 0
        1.38 1.38 0.00 0.00 450000/450000 Pathname#chop_basename 297
    4.94% 4.94% 1.38 1.38 0.00 0.00 450000 <Class::File>#basename 0
        1.37 1.37 0.00 0.00 450000/450000 Pathname#chop_basename 298
    4.88% 4.88% 1.37 1.37 0.00 0.00 450000 Regexp#to_s 0
        1.27 0.94 0.00 0.33 90000/90000 Pathname#initialize 218
    4.54% 3.36% 1.27 0.94 0.00 0.33 90000 Pathname#taint 222
        0.33 0.33 0.00 0.00 180000/180000 Kernel#taint 222
        0.97 0.58 0.00 0.39 90000/90000 Pathname#initialize 212
    3.46% 2.07% 0.97 0.58 0.00 0.39 90000 Kernel#dup 0
        0.21 0.21 0.00 0.00 90000/90000 <Class::String>#allocate 212
        0.18 0.18 0.00 0.00 90000/90000 String#initialize_copy 212
        0.91 0.91 0.00 0.00 360000/360000 Pathname#chop_basename 298
    3.26% 3.26% 0.91 0.91 0.00 0.00 360000 String#[] 0
        0.73 0.73 0.00 0.00 360000/450000 Pathname#split_names 311
        0.18 0.18 0.00 0.00 90000/450000 Pathname#segments 17
    3.24% 3.24% 0.91 0.91 0.00 0.00 450000 Array#unshift 0
        0.80 0.80 0.00 0.00 360000/360000 Pathname#chop_basename 298
    2.88% 2.88% 0.80 0.80 0.00 0.00 360000 String#rindex 0
        0.33 0.33 0.00 0.00 180000/180000 Pathname#taint 222
    1.17% 1.17% 0.33 0.33 0.00 0.00 180000 Kernel#taint 0
    ././@LongLink0000644000000000000000000000017312255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/profile/prof-pathname.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/pr0000664000175000017500000000311612206724733033642 0ustar jamespagejamespage$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require 'fssm' require 'pathname' require 'rubygems' require 'ruby-prof' $test_path = "#{Pathname.new('..').expand_path}" $iterations = 90000 class Pathname # original segments implementation I was using with # the plain ruby Pathname library. def segments prefix, names = split_names(@path) names.unshift(prefix) unless prefix.empty? names.shift if names[0] == '.' names end end core_result = Pathname.new($test_path).segments fssm_result = FSSM::Pathname.new($test_path).segments raise Exception, "#{core_result.inspect} != #{fssm_result.inspect}\nFSSM::Pathname is incompatible with Pathname" unless core_result == fssm_result RubyProf.start RubyProf.pause $iterations.times do |num| iteration = "%-6d" % (num + 1) puts "FSSM::Pathname iteration #{iteration}" RubyProf.resume p = FSSM::Pathname.new($test_path) segments = p.segments RubyProf.pause end puts "\nFSSM Pathname profile finished\n\n" result = RubyProf.stop output = File.new('prof-fssm-pathname.html', 'w+') printer = RubyProf::GraphHtmlPrinter.new(result) printer.print(output, :min_percent => 1) RubyProf.start RubyProf.pause $iterations.times do |num| iteration = "%-6d" % (num + 1) puts "::Pathname iteration #{iteration}" RubyProf.resume p = ::Pathname.new($test_path) segments = p.segments RubyProf.pause end puts "\nruby Pathname profile finished\n\n" result = RubyProf.stop output = File.new('prof-plain-pathname.html', 'w+') printer = RubyProf::GraphHtmlPrinter.new(result) printer.print(output, :min_percent => 1) ././@LongLink0000644000000000000000000000020212255653646011652 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/profile/prof-fssm-pathname.htmlstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/pr0000664000175000017500000007310212206724733033644 0ustar jamespagejamespage

    Profile Report

    Thread ID Total Time
    3696392 14.408241

    Thread 3696392

    %Total %Self Total Self Wait Child Calls Name Line
    100.00% 0.00% 14.41 0.00 0.00 14.41 0 Global#[No method] 28
        3.06 0.56 0.00 2.50 90000/90000 Class#new 35
        11.35 1.98 0.00 9.37 90000/90000 FSSM::Pathname#to_a 36
        11.35 1.98 0.00 9.37 90000/90000 Global#[No method] 36
    78.76% 13.76% 11.35 1.98 0.00 9.37 90000 FSSM::Pathname#to_a 47
        6.60 2.97 0.00 3.63 90000/90000 FSSM::Pathname#set_prefix_and_names 49
        0.94 0.49 0.00 0.45 90000/90000 Kernel#dup 50
        1.40 0.78 0.00 0.62 90000/180000 Array#delete 51
        0.16 0.16 0.00 0.00 90000/90000 String#empty? 52
        0.26 0.26 0.00 0.00 90000/90000 Array#unshift 52
        6.60 2.97 0.00 3.63 90000/90000 FSSM::Pathname#to_a 49
    45.80% 20.58% 6.60 2.97 0.00 3.63 90000 FSSM::Pathname#set_prefix_and_names 212
        0.46 0.46 0.00 0.00 90000/90000 Regexp#match 217
        0.23 0.23 0.00 0.00 90000/90000 MatchData#[] 218
        0.40 0.40 0.00 0.00 90000/90000 FSSM::Pathname#to_s 218
        0.21 0.21 0.00 0.00 90000/90000 MatchData#post_match 219
        0.72 0.72 0.00 0.00 90000/90000 String#split 219
        0.17 0.17 0.00 0.00 90000/90000 Array#compact! 225
        1.44 0.80 0.00 0.64 90000/180000 Array#delete 226
        3.06 0.56 0.00 2.50 90000/90000 Global#[No method] 35
    21.24% 3.92% 3.06 0.56 0.00 2.50 90000 Class#new 0
        0.18 0.18 0.00 0.00 90000/90000 <Class::String>#allocate 35
        2.31 1.18 0.00 1.13 90000/90000 FSSM::Pathname#initialize 35
        1.44 0.80 0.00 0.64 90000/180000 FSSM::Pathname#set_prefix_and_names 226
        1.40 0.78 0.00 0.62 90000/180000 FSSM::Pathname#to_a 51
    19.77% 11.03% 2.85 1.59 0.00 1.26 180000 Array#delete 0
        1.26 1.26 0.00 0.00 720000/720000 String#== 51
        2.31 1.18 0.00 1.13 90000/90000 Class#new 35
    16.06% 8.21% 2.31 1.18 0.00 1.13 90000 FSSM::Pathname#initialize 28
        0.94 0.94 0.00 0.00 90000/90000 FSSM::Pathname#dememo 33
        0.19 0.19 0.00 0.00 90000/90000 String#initialize 35
        1.26 1.26 0.00 0.00 720000/720000 Array#delete 51
    8.74% 8.74% 1.26 1.26 0.00 0.00 720000 String#== 0
        0.94 0.49 0.00 0.45 90000/90000 FSSM::Pathname#to_a 50
    6.55% 3.43% 0.94 0.49 0.00 0.45 90000 Kernel#dup 0
        0.20 0.20 0.00 0.00 90000/90000 <Class::Array>#allocate 50
        0.25 0.25 0.00 0.00 90000/90000 Array#initialize_copy 50
        0.94 0.94 0.00 0.00 90000/90000 FSSM::Pathname#initialize 33
    6.50% 6.50% 0.94 0.94 0.00 0.00 90000 FSSM::Pathname#dememo 203
        0.72 0.72 0.00 0.00 90000/90000 FSSM::Pathname#set_prefix_and_names 219
    4.97% 4.97% 0.72 0.72 0.00 0.00 90000 String#split 0
        0.46 0.46 0.00 0.00 90000/90000 FSSM::Pathname#set_prefix_and_names 217
    3.21% 3.21% 0.46 0.46 0.00 0.00 90000 Regexp#match 0
        0.40 0.40 0.00 0.00 90000/90000 FSSM::Pathname#set_prefix_and_names 218
    2.77% 2.77% 0.40 0.40 0.00 0.00 90000 FSSM::Pathname#to_s 42
        0.26 0.26 0.00 0.00 90000/90000 FSSM::Pathname#to_a 52
    1.79% 1.79% 0.26 0.26 0.00 0.00 90000 Array#unshift 0
        0.25 0.25 0.00 0.00 90000/90000 Kernel#dup 50
    1.72% 1.72% 0.25 0.25 0.00 0.00 90000 Array#initialize_copy 0
        0.23 0.23 0.00 0.00 90000/90000 FSSM::Pathname#set_prefix_and_names 218
    1.61% 1.61% 0.23 0.23 0.00 0.00 90000 MatchData#[] 0
        0.21 0.21 0.00 0.00 90000/90000 FSSM::Pathname#set_prefix_and_names 219
    1.45% 1.45% 0.21 0.21 0.00 0.00 90000 MatchData#post_match 0
        0.20 0.20 0.00 0.00 90000/90000 Kernel#dup 50
    1.41% 1.41% 0.20 0.20 0.00 0.00 90000 <Class::Array>#allocate 0
        0.19 0.19 0.00 0.00 90000/90000 FSSM::Pathname#initialize 35
    1.35% 1.35% 0.19 0.19 0.00 0.00 90000 String#initialize 0
        0.18 0.18 0.00 0.00 90000/90000 Class#new 35
    1.26% 1.26% 0.18 0.18 0.00 0.00 90000 <Class::String>#allocate 0
        0.17 0.17 0.00 0.00 90000/90000 FSSM::Pathname#set_prefix_and_names 225
    1.19% 1.19% 0.17 0.17 0.00 0.00 90000 Array#compact! 0
        0.16 0.16 0.00 0.00 90000/90000 FSSM::Pathname#to_a 52
    1.11% 1.11% 0.16 0.16 0.00 0.00 90000 String#empty? 0
    ././@LongLink0000644000000000000000000000017012255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/profile/prof-cache.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/pr0000664000175000017500000000135212206724733033642 0ustar jamespagejamespage$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require 'fssm' require 'rubygems' require 'ruby-prof' $test_path = FSSM::Pathname.new('..').expand_path $test_files = FSSM::Pathname.glob(File.join($test_path, '**', '*')) RubyProf.start RubyProf.pause cache = FSSM::Tree::Cache.new 5000.times do |num| iteration = "%-5d" % (num + 1) print "iteration #{iteration}" print '!' RubyProf.resume cache.unset($test_path) RubyProf.pause print '!' $test_files.each do |fn| print '.' RubyProf.resume cache.set(fn) RubyProf.pause end print "\n\n" end result = RubyProf.stop output = File.new('prof.html', 'w+') printer = RubyProf::GraphHtmlPrinter.new(result) printer.print(output, :min_percent => 1) ././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/profile/prof.htmlstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/pr0000664000175000017500000016705412206724733033656 0ustar jamespagejamespage

    Profile Report

    Thread ID Total Time
    109440 91.978859

    Thread 109440

    %Total %Self Total Self Wait Child Calls Name Line
    100.00% 1.61% 91.98 1.48 0.00 90.50 1 Global#[No method] 12
        1.06 0.13 0.00 0.94 5000/5000 FSSM::Tree::NodeInsertion#unset 22
        89.44 1.82 0.00 87.62 165000/165000 FSSM::Tree::Cache#set 29
        89.44 1.82 0.00 87.62 165000/165000 Global#[No method] 29
    97.24% 1.98% 89.44 1.82 0.00 87.62 165000 FSSM::Tree::Cache#set 145
        7.78 1.35 0.00 6.43 165000/500000 <Class::FSSM::Pathname>#for 148
        9.28 1.45 0.00 7.83 165000/165000 FSSM::Pathname#expand_path 148
        70.56 1.48 0.00 69.08 165000/165000 FSSM::Tree::NodeInsertion#set 149
        70.56 1.48 0.00 69.08 165000/165000 FSSM::Tree::Cache#set 149
    76.71% 1.61% 70.56 1.48 0.00 69.08 165000 FSSM::Tree::NodeInsertion#set 66
        58.98 0.86 0.00 58.12 165000/165000 FSSM::Tree::NodeInsertion#descendant! 67
        10.10 2.91 0.00 7.19 165000/165000 FSSM::Tree::Node#from_path 68
        58.98 0.86 0.00 58.12 165000/165000 FSSM::Tree::NodeInsertion#set 67
    64.12% 0.93% 58.98 0.86 0.00 58.12 165000 FSSM::Tree::NodeInsertion#descendant! 82
        58.12 17.58 0.00 40.54 165000/170000 FSSM::Tree::NodeInsertion#recurse 83
        58.12 17.58 0.00 40.54 165000/170000 FSSM::Tree::NodeInsertion#descendant! 83
        0.11 0.06 0.00 0.05 5000/170000 FSSM::Tree::NodeInsertion#descendant 79
    63.31% 19.17% 58.23 17.64 0.00 40.60 170000 FSSM::Tree::NodeInsertion#recurse 86
        8.99 6.67 0.00 2.32 1215000/1215000 FSSM::Tree::NodeBase#child! 92
        2.32 2.32 0.00 0.00 1385000/1390000 Array#empty? 90
        27.21 2.10 0.00 25.11 170000/175000 FSSM::Tree::NodeInsertion#key_segments 87
        2.09 2.09 0.00 0.00 1215000/1215000 Array#shift 91
        0.74 0.06 0.00 0.68 5000/175000 FSSM::Tree::NodeInsertion#unset 49
        27.21 2.10 0.00 25.11 170000/175000 FSSM::Tree::NodeInsertion#recurse 87
    30.39% 2.35% 27.95 2.16 0.00 25.79 175000 FSSM::Tree::NodeInsertion#key_segments 73
        1.62 1.13 0.00 0.49 170000/500000 <Class::FSSM::Pathname>#for 75
        23.84 4.05 0.00 19.80 170000/170000 FSSM::Pathname#segments 75
        0.32 0.32 0.00 0.00 175000/675000 Kernel#is_a? 74
        23.84 4.05 0.00 19.80 170000/170000 FSSM::Tree::NodeInsertion#key_segments 75
    25.92% 4.40% 23.84 4.05 0.00 19.80 170000 FSSM::Pathname#segments 43
        0.29 0.29 0.00 0.00 170000/170000 String#empty? 48
        0.42 0.42 0.00 0.00 165000/165000 Array#unshift 48
        13.85 6.04 0.00 7.81 170000/170000 FSSM::Pathname#set_prefix_and_names 45
        1.46 0.86 0.00 0.59 170000/340000 Kernel#dup 46
        3.78 2.04 0.00 1.73 170000/340000 Array#delete 47
        13.85 6.04 0.00 7.81 170000/170000 FSSM::Pathname#segments 45
    15.06% 6.57% 13.85 6.04 0.00 7.81 170000 FSSM::Pathname#set_prefix_and_names 144
        0.37 0.37 0.00 0.00 165000/165000 MatchData#[] 150
        1.35 1.35 0.00 0.00 170000/170000 String#split 154
        0.36 0.36 0.00 0.00 170000/170000 Array#+ 154
        0.31 0.31 0.00 0.00 165000/165000 MatchData#post_match 151
        0.66 0.66 0.00 0.00 165000/165000 FSSM::Pathname#to_s 150
        0.68 0.68 0.00 0.00 170000/170000 Regexp#match 149
        0.29 0.29 0.00 0.00 170000/170000 Array#compact! 157
        3.78 2.05 0.00 1.73 170000/340000 Array#delete 158
        1.36 1.07 0.00 0.29 165000/500000 FSSM::Tree::Node#from_path 130
        7.78 1.35 0.00 6.43 165000/500000 FSSM::Tree::Cache#set 148
        1.62 1.13 0.00 0.49 170000/500000 FSSM::Tree::NodeInsertion#key_segments 75
    11.70% 3.86% 10.76 3.55 0.00 7.21 500000 <Class::FSSM::Pathname>#for 21
        0.90 0.90 0.00 0.00 500000/675000 Kernel#is_a? 22
        6.32 0.92 0.00 5.39 170000/335038 Class#new 22
        10.10 2.91 0.00 7.19 165000/165000 FSSM::Tree::NodeInsertion#set 68
    10.98% 3.16% 10.10 2.91 0.00 7.19 165000 FSSM::Tree::Node#from_path 129
        1.36 1.07 0.00 0.29 165000/500000 <Class::FSSM::Pathname>#for 130
        1.99 0.86 0.00 1.13 165000/165000 FSSM::Pathname#mtime 134
        1.79 0.87 0.00 0.92 165000/165000 FSSM::Pathname#symlink? 134
        2.05 0.86 0.00 1.19 165000/165000 FSSM::Pathname#ftype 131
        6.32 0.92 0.00 5.39 170000/335038 <Class::FSSM::Pathname>#for 22
        0.00 0.00 0.00 0.00 38/335038 FSSM::Tree::NodeBase#child! 14
        3.01 0.91 0.00 2.11 165000/335038 FSSM::Pathname#expand_path 247
    10.14% 1.99% 9.33 1.83 0.00 7.50 335038 Class#new 0
        0.00 0.00 0.00 0.00 38/38 <Class::Object>#allocate 14
        0.59 0.59 0.00 0.00 335000/505000 <Class::String>#allocate 22
        0.00 0.00 0.00 0.00 38/38 FSSM::Tree::NodeBase#initialize 14
        6.91 3.04 0.00 3.87 335000/335000 FSSM::Pathname#initialize 22
        9.28 1.45 0.00 7.83 165000/165000 FSSM::Tree::Cache#set 148
    10.09% 1.58% 9.28 1.45 0.00 7.83 165000 FSSM::Pathname#expand_path 247
        0.28 0.28 0.00 0.00 165000/165000 Kernel#class 247
        4.54 4.54 0.00 0.00 165000/165000 <Class::File>#expand_path 247
        3.01 0.91 0.00 2.11 165000/335038 Class#new 247
        8.99 6.67 0.00 2.32 1215000/1215000 FSSM::Tree::NodeInsertion#recurse 92
    9.77% 7.25% 8.99 6.67 0.00 2.32 1215000 FSSM::Tree::NodeBase#child! 13
        0.00 0.00 0.00 0.00 38/38 Hash#[]= 14
        0.00 0.00 0.00 0.00 38/335038 Class#new 14
        2.32 2.32 0.00 0.00 1215000/1215000 Hash#[] 14
        3.78 2.04 0.00 1.73 170000/340000 FSSM::Pathname#segments 47
        3.78 2.05 0.00 1.73 170000/340000 FSSM::Pathname#set_prefix_and_names 158
    8.22% 4.45% 7.56 4.09 0.00 3.47 340000 Array#delete 0
        3.47 3.47 0.00 0.00 2110000/2110000 String#== 158
        6.91 3.04 0.00 3.87 335000/335000 Class#new 22
    7.51% 3.30% 6.91 3.04 0.00 3.87 335000 FSSM::Pathname#initialize 26
        0.28 0.28 0.00 0.00 170000/170000 Kernel#=~ 27
        3.59 1.19 0.00 2.39 335000/335000 String#initialize 31
        4.54 4.54 0.00 0.00 165000/165000 FSSM::Pathname#expand_path 247
    4.94% 4.94% 4.54 4.54 0.00 0.00 165000 <Class::File>#expand_path 0
        3.59 1.19 0.00 2.39 335000/335000 FSSM::Pathname#initialize 31
    3.90% 1.30% 3.59 1.19 0.00 2.39 335000 String#initialize 0
        2.39 0.84 0.00 1.55 170000/170000 Pathname#to_str 31
        3.47 3.47 0.00 0.00 2110000/2110000 Array#delete 158
    3.77% 3.77% 3.47 3.47 0.00 0.00 2110000 String#== 0
        1.46 0.86 0.00 0.59 170000/340000 FSSM::Pathname#segments 46
        1.55 0.87 0.00 0.67 170000/340000 Pathname#to_str 242
    3.27% 1.89% 3.00 1.74 0.00 1.27 340000 Kernel#dup 0
        0.30 0.30 0.00 0.00 170000/505000 <Class::String>#allocate 242
        0.29 0.29 0.00 0.00 170000/170000 <Class::Array>#allocate 46
        0.37 0.37 0.00 0.00 170000/170000 String#initialize_copy 242
        0.30 0.30 0.00 0.00 170000/170000 Array#initialize_copy 46
        2.39 0.84 0.00 1.55 170000/170000 String#initialize 31
    2.60% 0.92% 2.39 0.84 0.00 1.55 170000 Pathname#to_str 241
        1.55 0.87 0.00 0.67 170000/340000 Kernel#dup 242
        0.01 0.01 0.00 0.00 5000/1390000 FSSM::Tree::NodeInsertion#unset 51
        2.32 2.32 0.00 0.00 1385000/1390000 FSSM::Tree::NodeInsertion#recurse 90
    2.53% 2.53% 2.33 2.33 0.00 0.00 1390000 Array#empty? 0
        2.32 2.32 0.00 0.00 1215000/1215000 FSSM::Tree::NodeBase#child! 14
    2.52% 2.52% 2.32 2.32 0.00 0.00 1215000 Hash#[] 0
        0.00 0.00 0.00 0.00 38/38 Hash#default 14
        2.09 2.09 0.00 0.00 1215000/1215000 FSSM::Tree::NodeInsertion#recurse 91
    2.27% 2.27% 2.09 2.09 0.00 0.00 1215000 Array#shift 0
        2.05 0.86 0.00 1.19 165000/165000 FSSM::Tree::Node#from_path 131
    2.23% 0.93% 2.05 0.86 0.00 1.19 165000 FSSM::Pathname#ftype 229
        1.19 1.19 0.00 0.00 165000/165000 <Class::File>#ftype 229
        1.99 0.86 0.00 1.13 165000/165000 FSSM::Tree::Node#from_path 134
    2.17% 0.94% 1.99 0.86 0.00 1.13 165000 FSSM::Pathname#mtime 231
        1.13 1.13 0.00 0.00 165000/165000 <Class::File>#mtime 231
        1.79 0.87 0.00 0.92 165000/165000 FSSM::Tree::Node#from_path 134
    1.94% 0.94% 1.79 0.87 0.00 0.92 165000 FSSM::Pathname#symlink? 216
        0.92 0.92 0.00 0.00 165000/165000 <Module::FileTest>#symlink? 216
        1.35 1.35 0.00 0.00 170000/170000 FSSM::Pathname#set_prefix_and_names 154
    1.47% 1.47% 1.35 1.35 0.00 0.00 170000 String#split 0
        0.90 0.90 0.00 0.00 500000/675000 <Class::FSSM::Pathname>#for 22
        0.32 0.32 0.00 0.00 175000/675000 FSSM::Tree::NodeInsertion#key_segments 74
    1.32% 1.32% 1.22 1.22 0.00 0.00 675000 Kernel#is_a? 0
        1.19 1.19 0.00 0.00 165000/165000 FSSM::Pathname#ftype 229
    1.30% 1.30% 1.19 1.19 0.00 0.00 165000 <Class::File>#ftype 0
        1.13 1.13 0.00 0.00 165000/165000 FSSM::Pathname#mtime 231
    1.23% 1.23% 1.13 1.13 0.00 0.00 165000 <Class::File>#mtime 0
        1.06 0.13 0.00 0.94 5000/5000 Global#[No method] 22
    1.15% 0.14% 1.06 0.13 0.00 0.94 5000 FSSM::Tree::NodeInsertion#unset 48
        0.01 0.01 0.00 0.00 5000/5000 Array#pop 56
        0.14 0.03 0.00 0.11 5000/5000 FSSM::Tree::NodeInsertion#descendant 57
        0.04 0.03 0.00 0.01 5000/5000 FSSM::Tree::NodeBase#remove_child 61
        0.01 0.01 0.00 0.00 5000/1390000 Array#empty? 51
        0.74 0.06 0.00 0.68 5000/175000 FSSM::Tree::NodeInsertion#key_segments 49
        0.92 0.92 0.00 0.00 165000/165000 FSSM::Pathname#symlink? 216
    1.00% 1.00% 0.92 0.92 0.00 0.00 165000 <Module::FileTest>#symlink? 0
    ././@LongLink0000644000000000000000000000015512255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/example.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/ex0000664000175000017500000000036712206724733033642 0ustar jamespagejamespage$:.unshift(File.join(File.dirname(__FILE__), 'lib')) require 'fssm' FSSM.monitor('.', '**/*') do update {|b, r| puts "Update in #{b} to #{r}"} delete {|b, r| puts "Delete in #{b} to #{r}"} create {|b, r| puts "Create in #{b} to #{r}"} end ././@LongLink0000644000000000000000000000015312255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/Rakefilestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/Ra0000664000175000017500000000270112206724733033562 0ustar jamespagejamespagerequire 'rubygems' require 'rake' begin require 'jeweler' Jeweler::Tasks.new do |gem| gem.name = "fssm" gem.summary = %Q{file system state monitor} gem.description = %Q{file system state monitor} gem.email = "ttilley@gmail.com" gem.homepage = "http://github.com/ttilley/fssm" gem.authors = ["Travis Tilley"] gem.add_development_dependency "rspec" # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings end rescue LoadError puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" end require 'spec/rake/spectask' Spec::Rake::SpecTask.new(:spec) do |spec| spec.libs << 'lib' << 'spec' spec.spec_files = FileList['spec/**/*_spec.rb'] end Spec::Rake::SpecTask.new(:rcov) do |spec| spec.libs << 'lib' << 'spec' spec.pattern = 'spec/**/*_spec.rb' spec.rcov = true end task :spec => :check_dependencies begin require 'reek/rake_task' Reek::RakeTask.new do |t| t.fail_on_error = true t.verbose = false t.source_files = 'lib/**/*.rb' end rescue LoadError task :reek do abort "Reek is not available. In order to run reek, you must: sudo gem install reek" end end begin require 'roodi' require 'roodi_task' RoodiTask.new do |t| t.verbose = false end rescue LoadError task :roodi do abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi" end end task :default => :spec ././@LongLink0000644000000000000000000000014712255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000775000175000017500000000000012206724733033622 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000000137012206724733033625 0ustar jamespagejamespagedir = File.dirname(__FILE__) $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir) module FSSM FileNotFoundError = Class.new(StandardError) CallbackError = Class.new(StandardError) class << self def dbg(msg=nil) STDERR.puts(msg) end def monitor(*args, &block) monitor = FSSM::Monitor.new FSSM::Support.use_block(args.empty? ? monitor : monitor.path(*args), block) monitor.run end end end require 'thread' require 'fssm/pathname' require 'fssm/support' require 'fssm/tree' require 'fssm/path' require 'fssm/state/directory' require 'fssm/state/file' require 'fssm/monitor' require "fssm/backends/#{FSSM::Support.backend.downcase}" FSSM::Backends::Default = FSSM::Backends.const_get(FSSM::Support.backend) ././@LongLink0000644000000000000000000000015412255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000775000175000017500000000000012206724733033622 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016612255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/monitor.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000000077212206724733033632 0ustar jamespagejamespageclass FSSM::Monitor def initialize(options={}) @options = options @backend = FSSM::Backends::Default.new end def path(*args, &block) path = FSSM::Path.new(*args) FSSM::Support.use_block(path, block) @backend.add_handler(FSSM::State::Directory.new(path)) path end def file(*args, &block) path = FSSM::Path.new(*args) FSSM::Support.use_block(path, block) @backend.add_handler(FSSM::State::File.new(path)) path end def run @backend.run end end ././@LongLink0000644000000000000000000000016312255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/tree.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000000620012206724733033622 0ustar jamespagejamespagemodule FSSM::Tree module NodeBase def initialize @children = {} end protected def child(segment) @children["#{segment}"] end def child!(segment) (@children["#{segment}"] ||= Node.new) end def has_child?(segment) @children.has_key?("#{segment}") end def remove_child(segment) @children.delete("#{segment}") end def remove_children @children.clear end end module NodeEnumerable include NodeBase include Enumerable def each(prefix=nil, &block) @children.each do |segment, node| cprefix = prefix ? FSSM::Pathname.for(prefix).join(segment) : FSSM::Pathname.for(segment) block.call([cprefix, node]) node.each(cprefix, &block) end end end module NodeInsertion include NodeBase def unset(path) key = key_segments(path) if key.empty? remove_children return nil end segment = key.pop node = descendant(key) return unless node node.remove_child(segment) nil end def set(path) node = descendant!(path) node.from_path(path).mtime end protected def key_segments(key) return key if key.is_a?(Array) FSSM::Pathname.for(key).segments end def descendant(path) recurse(path, false) end def descendant!(path) recurse(path, true) end def recurse(key, create=false) key = key_segments(key) node = self until key.empty? segment = key.shift node = create ? node.child!(segment) : node.child(segment) return nil unless node end node end end module CacheDebug def set(path) FSSM.dbg("Cache#set(#{path})") super end def unset(path) FSSM.dbg("Cache#unset(#{path})") super end def ftype(ft) FSSM.dbg("Cache#ftype(#{ft})") super end end class Node include NodeBase include NodeEnumerable attr_accessor :mtime attr_accessor :ftype def <=>(other) return unless other.is_a?(::FSSM::Tree::Node) self.mtime <=> other.mtime end def from_path(path) path = FSSM::Pathname.for(path) @ftype = path.ftype # this handles bad symlinks without failing. why handle bad symlinks at # all? well, we could still be interested in their creation and deletion. @mtime = path.symlink? ? Time.at(0) : path.mtime self end end class Cache include NodeBase include NodeEnumerable include NodeInsertion include CacheDebug if $DEBUG def set(path) # all paths set from this level need to be absolute # realpath will fail on broken links path = FSSM::Pathname.for(path).expand_path super(path) end def files ftype('file') end def directories ftype('directory') end def links ftype('link') end alias symlinks links private def ftype(ft) inject({}) do |hash, (path, node)| hash["#{path}"] = node.mtime if node.ftype == ft hash end end end end ././@LongLink0000644000000000000000000000016712255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/pathname.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000002076612206724733033637 0ustar jamespagejamespagerequire 'fileutils' require 'find' module FSSM class Pathname < String SYMLOOP_MAX = 8 ROOT = '/'.freeze DOT = '.'.freeze DOT_DOT = '..'.freeze class << self def for(path) path.is_a?(::FSSM::Pathname) ? path : new("#{path}") end end def initialize(path) raise ArgumentError, "path cannot contain ASCII NULLs" if path =~ %r{\0} super(path) end def <=>(other) self.tr('/', "\0").to_s <=> other.to_str.tr('/', "\0") rescue NoMethodError nil end def ==(other) left = self.cleanpath.tr('/', "\0").to_s right = self.class.for(other).cleanpath.tr('/', "\0").to_s left == right rescue NoMethodError false end def +(path) dup << path end def <<(path) replace( join(path).cleanpath! ) end def absolute? self[0, 1].to_s == ROOT end def ascend parts = to_a parts.length.downto(1) do |i| yield self.class.join(parts[0, i]) end end def children entries[2..-1] end def cleanpath! parts = to_a final = [] parts.each do |part| case part when DOT then next when DOT_DOT then case final.last when ROOT then next when DOT_DOT then final.push(DOT_DOT) when nil then final.push(DOT_DOT) else final.pop end else final.push(part) end end replace(final.empty? ? DOT : self.class.join(*final)) end def cleanpath dup.cleanpath! end def descend parts = to_a 1.upto(parts.length) { |i| yield self.class.join(parts[0, i]) } end def dot? self == DOT end def dot_dot? self == DOT_DOT end def each_filename(&blk) to_a.each(&blk) end def mountpoint? stat1 = self.lstat stat2 = self.parent.lstat stat1.dev != stat2.dev || stat1.ino == stat2.ino rescue Errno::ENOENT false end def parent self + '..' end def realpath path = self SYMLOOP_MAX.times do link = path.readlink link = path.dirname + link if link.relative? path = link end raise Errno::ELOOP, self rescue Errno::EINVAL path.expand_path end def relative? !absolute? end def relative_path_from(base) base = self.class.for(base) raise ArgumentError, 'no relative path between a relative and absolute' if self.absolute? != base.absolute? return self if base.dot? return self.class.new(DOT) if self == base base = base.cleanpath.to_a dest = self.cleanpath.to_a while !dest.empty? && !base.empty? && dest[0] == base[0] base.shift dest.shift end base.shift if base[0] == DOT dest.shift if dest[0] == DOT raise ArgumentError, "base directory may not contain '#{DOT_DOT}'" if base.include?(DOT_DOT) path = base.fill(DOT_DOT) + dest path = self.class.join(*path) path = self.class.new(DOT) if path.empty? path end def root? !!(self =~ %r{^#{ROOT}+$}) end def to_a array = to_s.split(File::SEPARATOR) array.delete('') array.insert(0, ROOT) if absolute? array end alias segments to_a def to_path self end def to_s "#{self}" end alias to_str to_s def unlink Dir.unlink(self) true rescue Errno::ENOTDIR File.unlink(self) true end end class Pathname def self.[](pattern) Dir[pattern].map! {|d| FSSM::Pathname.new(d) } end def self.pwd FSSM::Pathname.new(Dir.pwd) end def entries Dir.entries(self).map! {|e| FSSM::Pathname.new(e) } end def mkdir(mode = 0777) Dir.mkdir(self, mode) end def opendir(&blk) Dir.open(self, &blk) end def rmdir Dir.rmdir(self) end def self.glob(pattern, flags = 0) dirs = Dir.glob(pattern, flags) dirs.map! {|path| FSSM::Pathname.new(path) } if block_given? dirs.each {|dir| yield dir } nil else dirs end end def glob(pattern, flags = 0, &block) patterns = [pattern].flatten patterns.map! {|p| self.class.glob(self.to_s + p, flags, &block) } patterns.flatten end def chdir blk = lambda { yield self } if block_given? Dir.chdir(self, &blk) end end class Pathname def blockdev? FileTest.blockdev?(self) end def chardev? FileTest.chardev?(self) end def directory? FileTest.directory?(self) end def executable? FileTest.executable?(self) end def executable_real? FileTest.executable_real?(self) end def exists? FileTest.exists?(self) end def file? FileTest.file?(self) end def grpowned? FileTest.grpowned?(self) end def owned? FileTest.owned?(self) end def pipe? FileTest.pipe?(self) end def readable? FileTest.readable?(self) end def readable_real? FileTest.readable_real?(self) end def setgid? FileTest.setgit?(self) end def setuid? FileTest.setuid?(self) end def socket? FileTest.socket?(self) end def sticky? FileTest.sticky?(self) end def symlink? FileTest.symlink?(self) end def world_readable? FileTest.world_readable?(self) end def world_writable? FileTest.world_writable?(self) end def writable? FileTest.writable?(self) end def writable_real? FileTest.writable_real?(self) end def zero? FileTest.zero?(self) end end class Pathname def atime File.atime(self) end def ctime File.ctime(self) end def ftype File.ftype(self) end def lstat File.lstat(self) end def mtime File.mtime(self) end def stat File.stat(self) end def utime(atime, mtime) File.utime(self, atime, mtime) end end class Pathname def self.join(*parts) last_part = FSSM::Pathname.new(parts.last) return last_part if last_part.absolute? FSSM::Pathname.new(File.join(*parts.reject {|p| p.empty? })) end def basename self.class.new(File.basename(self)) end def chmod(mode) File.chmod(mode, self) end def chown(owner, group) File.chown(owner, group, self) end def dirname self.class.new(File.dirname(self)) end def expand_path(from = nil) self.class.new(File.expand_path(self, from)) end def extname File.extname(self) end def fnmatch?(pat, flags = 0) File.fnmatch(pat, self, flags) end def join(*parts) self.class.join(self, *parts) end def lchmod(mode) File.lchmod(mode, self) end def lchown(owner, group) File.lchown(owner, group, self) end def link(to) File.link(self, to) end def open(mode = 'r', perm = nil, &blk) File.open(self, mode, perm, &blk) end def readlink self.class.new(File.readlink(self)) end def rename(to) File.rename(self, to) replace(to) end def size File.size(self) end def size? File.size?(self) end def split File.split(self).map {|part| FSSM::Pathname.new(part) } end def symlink(to) File.symlink(self, to) end def truncate File.truncate(self) end end class Pathname def mkpath self.class.new(FileUtils.mkpath(self)) end def rmtree self.class.new(FileUtils.rmtree(self).first) end def touch self.class.new(FileUtils.touch(self).first) end end class Pathname def each_line(sep = $/, &blk) IO.foreach(self, sep, &blk) end def read(len = nil, off = 0) IO.read(self, len, off) end def readlines(sep = $/) IO.readlines(self, sep) end def sysopen(mode = 'r', perm = nil) IO.sysopen(self, mode, perm) end end class Pathname def find Find.find(self) {|path| yield FSSM::Pathname.new(path) } end end class Pathname class << self alias getwd pwd end alias absolute expand_path alias delete unlink alias exist? exists? alias fnmatch fnmatch? end end ././@LongLink0000644000000000000000000000016312255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/path.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000000362212206724733033627 0ustar jamespagejamespageclass FSSM::Path def initialize(path=nil, glob=nil, &block) set_path(path || '.') set_glob(glob || '**/*') init_callbacks if block_given? if block.arity == 1 block.call(self) else self.instance_eval(&block) end end end def to_s @path.to_s end def to_pathname @path end def glob(value=nil) return @glob if value.nil? set_glob(value) end def create(callback_or_path=nil, &block) callback_action(:create, (block_given? ? block : callback_or_path)) end def update(callback_or_path=nil, &block) callback_action(:update, (block_given? ? block : callback_or_path)) end def delete(callback_or_path=nil, &block) callback_action(:delete, (block_given? ? block : callback_or_path)) end private def init_callbacks do_nothing = lambda {|base, relative|} @callbacks = Hash.new(do_nothing) end def callback_action(type, arg=nil) if arg.is_a?(Proc) set_callback(type, arg) elsif arg.nil? get_callback(type) else run_callback(type, arg) end end def set_callback(type, arg) raise ArgumentError, "Proc expected" unless arg.is_a?(Proc) @callbacks[type] = arg end def get_callback(type) @callbacks[type] end def run_callback(type, arg) base, relative = split_path(arg) begin @callbacks[type].call(base, relative) rescue Exception => e raise FSSM::CallbackError, "#{type} - #{base.join(relative)}: #{e.message}", e.backtrace end end def split_path(path) path = FSSM::Pathname.for(path) [@path, (path.relative? ? path : path.relative_path_from(@path))] end def set_path(path) path = FSSM::Pathname.for(path) raise FSSM::FileNotFoundError, "No such file or directory - #{path}" unless path.exist? @path = path.expand_path end def set_glob(glob) @glob = glob.is_a?(Array) ? glob : [glob] end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/state/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000775000175000017500000000000012206724733033622 5ustar jamespagejamespage././@LongLink0000644000000000000000000000017112255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/state/file.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000000135712206724733033632 0ustar jamespagejamespagemodule FSSM::State class File attr_reader :path def initialize(path) @path = path end def refresh(base=nil, skip_callbacks=false) base ||= @path.to_pathname used_to_exist, @exists = @exists, base.exists? # this handles bad symlinks without failing. why handle bad symlinks at # all? well, we could still be interested in their creation and deletion. old_mtime, @mtime = @mtime, base.symlink? ? Time.at(0) : base.mtime if @exists unless skip_callbacks @path.delete(@path.to_s) if used_to_exist && !@exists @path.create(@path.to_s) if !used_to_exist && @exists @path.update(@path.to_s) if used_to_exist && @exists && old_mtime != @mtime end end end end ././@LongLink0000644000000000000000000000017612255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/state/directory.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000000243312206724733033626 0ustar jamespagejamespagemodule FSSM::State class Directory attr_reader :path def initialize(path) @path = path @cache = FSSM::Tree::Cache.new end def refresh(base=nil, skip_callbacks=false) previous, current = recache(base || @path.to_pathname) unless skip_callbacks deleted(previous, current) created(previous, current) modified(previous, current) end end private def created(previous, current) (current.keys - previous.keys).each {|created| @path.create(created)} end def deleted(previous, current) (previous.keys - current.keys).each {|deleted| @path.delete(deleted)} end def modified(previous, current) (current.keys & previous.keys).each do |file| @path.update(file) if (current[file] <=> previous[file]) != 0 end end def recache(base) base = FSSM::Pathname.for(base) previous = @cache.files snapshot(base) current = @cache.files [previous, current] end def snapshot(base) base = FSSM::Pathname.for(base) @cache.unset(base) @path.glob.each {|glob| add_glob(base, glob)} end def add_glob(base, glob) FSSM::Pathname.glob(base.join(glob).to_s).each do |fn| @cache.set(fn) end end end end ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/backends/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000775000175000017500000000000012206724733033622 5ustar jamespagejamespage././@LongLink0000644000000000000000000000017712255653646011665 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/backends/inotify.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000000117012206724733033623 0ustar jamespagejamespagemodule FSSM::Backends class Inotify def initialize @notifier = INotify::Notifier.new end def add_handler(handler, preload=true) @notifier.watch(handler.path.to_s, :recursive, :attrib, :modify, :create, :delete, :delete_self, :moved_from, :moved_to, :move_self) do |event| path = FSSM::Pathname.for(event.absolute_name) path = path.dirname unless event.name == "" # Event on root directory handler.refresh(path) end handler.refresh(nil, true) if preload end def run begin @notifier.run rescue Interrupt end end end end ././@LongLink0000644000000000000000000000020012255653646011650 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/backends/fsevents.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000000134012206724733033622 0ustar jamespagejamespagerequire File.join(File.dirname(__FILE__), 'rubycocoa/fsevents') module FSSM::Backends class FSEvents def initialize @handlers = {} @fsevents = [] end def add_handler(handler, preload=true) @handlers[handler.path.to_s] = handler fsevent = Rucola::FSEvents.new(handler.path.to_s, {:latency => 0.5}) do |events| events.each do |event| handler.refresh(event.path) end end fsevent.create_stream handler.refresh(nil, true) if preload fsevent.start @fsevents << fsevent end def run begin OSX.CFRunLoopRun rescue Interrupt @fsevents.each do |fsev| fsev.stop end end end end end ././@LongLink0000644000000000000000000000017712255653646011665 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/backends/polling.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000000104512206724733033624 0ustar jamespagejamespagemodule FSSM::Backends class Polling def initialize(options={}) @handlers = [] @latency = options[:latency] || 1.5 end def add_handler(handler, preload=true) handler.refresh(nil, true) if preload @handlers << handler end def run begin loop do start = Time.now.to_f @handlers.each {|handler| handler.refresh} nap_time = @latency - (Time.now.to_f - start) sleep nap_time if nap_time > 0 end rescue Interrupt end end end end ././@LongLink0000644000000000000000000000017712255653646011665 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/backends/rubycocoa/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000775000175000017500000000000012206724733033622 5ustar jamespagejamespage././@LongLink0000644000000000000000000000021212255653646011653 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000001251612206724733033631 0ustar jamespagejamespageOSX.require_framework '/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework' module Rucola class FSEvents class FSEvent attr_reader :fsevents_object attr_reader :id attr_reader :path def initialize(fsevents_object, id, path) @fsevents_object, @id, @path = fsevents_object, id, path end # Returns an array of the files/dirs in the path that the event occurred in. # The files are sorted by the modification time, the first entry is the last modified file. def files Dir.glob("#{File.expand_path(path)}/*").sort_by {|f| File.mtime(f) }.reverse end # Returns the last modified file in the path that the event occurred in. def last_modified_file files.first end end class StreamError < StandardError; end attr_reader :paths attr_reader :stream attr_accessor :allocator attr_accessor :context attr_accessor :since attr_accessor :latency attr_accessor :flags # Initializes a new FSEvents `watchdog` object and starts watching the directories you specify for events. The # block is used as a handler for events, which are passed as the block's argument. This method is the easiest # way to start watching some directories if you don't care about the details of setting up the event stream. # # Rucola::FSEvents.start_watching('/tmp') do |events| # events.each { |event| log.debug("#{event.files.inspect} were changed.") } # end # # Rucola::FSEvents.start_watching('/var/log/system.log', '/var/log/secure.log', :since => last_id, :latency => 5) do # Growl.notify("Something was added to your log files!") # end # # Note that the method also returns the FSEvents object. This enables you to control the event stream if you want to. # # fsevents = Rucola::FSEvents.start_watching('/Volumes') do |events| # events.each { |event| Growl.notify("Volume changes: #{event.files.to_sentence}") } # end # fsevents.stop def self.start_watching(*params, &block) fsevents = new(*params, &block) fsevents.create_stream fsevents.start fsevents end # Creates a new FSEvents `watchdog` object. You can specify a list of paths to watch and options to control the # behaviour of the watchdog. The block you pass serves as a callback when an event is generated on one of the # specified paths. # # fsevents = FSEvents.new('/etc/passwd') { Mailer.send_mail("Someone touched the password file!") } # fsevents.create_stream # fsevents.start # # fsevents = FSEvents.new('/home/upload', :since => UploadWatcher.last_event_id) do |events| # events.each do |event| # UploadWatcher.last_event_id = event.id # event.files.each do |file| # UploadWatcher.logfile.append("#{file} was changed") # end # end # end # # *:since: The service will report events that have happened after the supplied event ID. Never use 0 because that # will cause every fsevent since the "beginning of time" to be reported. Use OSX::KFSEventStreamEventIdSinceNow # if you want to receive events that have happened after this call. (Default: OSX::KFSEventStreamEventIdSinceNow). # You can find the ID's passed with :since in the events passed to your block. # *:latency: Number of seconds to wait until an FSEvent is reported, this allows the service to bundle events. (Default: 0.0) # # Please refer to the Cocoa documentation for the rest of the options. def initialize(*params, &block) raise ArgumentError, 'No callback block was specified.' unless block_given? options = params.last.kind_of?(Hash) ? params.pop : {} @paths = params.flatten paths.each { |path| raise ArgumentError, "The specified path (#{path}) does not exist." unless File.exist?(path) } @allocator = options[:allocator] || OSX::KCFAllocatorDefault @context = options[:context] || nil @since = options[:since] || OSX::KFSEventStreamEventIdSinceNow @latency = options[:latency] || 0.0 @flags = options[:flags] || 0 @stream = options[:stream] || nil @user_callback = block @callback = Proc.new do |stream, client_callback_info, number_of_events, paths_pointer, event_flags, event_ids| paths_pointer.regard_as('*') events = [] number_of_events.times {|i| events << Rucola::FSEvents::FSEvent.new(self, event_ids[i], paths_pointer[i]) } @user_callback.call(events) end end # Create the stream. # Raises a Rucola::FSEvents::StreamError if the stream could not be created. def create_stream @stream = OSX.FSEventStreamCreate(@allocator, @callback, @context, @paths, @since, @latency, @flags) raise(StreamError, 'Unable to create FSEvents stream.') unless @stream OSX.FSEventStreamScheduleWithRunLoop(@stream, OSX.CFRunLoopGetCurrent, OSX::KCFRunLoopDefaultMode) end # Start the stream. # Raises a Rucola::FSEvents::StreamError if the stream could not be started. def start raise(StreamError, 'Unable to start FSEvents stream.') unless OSX.FSEventStreamStart(@stream) end # Stop the stream. # You can resume it by calling `start` again. def stop OSX.FSEventStreamStop(@stream) end end end ././@LongLink0000644000000000000000000000016612255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/lib/fssm/support.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/vendor/fssm/li0000664000175000017500000000253312206724733033627 0ustar jamespagejamespagerequire 'rbconfig' module FSSM::Support class << self def backend @@backend ||= case when mac? && !jruby? && carbon_core? 'FSEvents' when linux? && rb_inotify? 'Inotify' else 'Polling' end end def jruby? defined?(JRUBY_VERSION) end def mac? Config::CONFIG['target_os'] =~ /darwin/i end def linux? Config::CONFIG['target_os'] =~ /linux/i end def carbon_core? begin require 'osx/foundation' OSX.require_framework '/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework' true rescue LoadError STDERR.puts("Warning: Unable to load CarbonCore. FSEvents will be unavailable.") false end end def rb_inotify? found = begin require 'rb-inotify' if defined?(INotify::VERSION) version = INotify::VERSION version[0] > 0 || version[1] >= 6 end rescue LoadError false end STDERR.puts("Warning: Unable to load rb-inotify >= 0.5.1. Inotify will be unavailable.") unless found found end def use_block(context, block) return if block.nil? if block.arity == 1 block.call(context) else context.instance_eval(&block) end end end end stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/Rakefile0000664000175000017500000002254212206724733032502 0ustar jamespagejamespage# ----- Utility Functions ----- def scope(path) File.join(File.dirname(__FILE__), path) end # ----- Default: Testing ------ task :default => :test require 'rake/testtask' Rake::TestTask.new do |t| t.libs << 'test' test_files = FileList[scope('test/**/*_test.rb')] test_files.exclude(scope('test/rails/*')) test_files.exclude(scope('test/plugins/*')) t.test_files = test_files t.verbose = true end # ----- Packaging ----- # Don't use Rake::GemPackageTast because we want prerequisites to run # before we load the gemspec. desc "Build all the packages." task :package => [:revision_file, :submodules, :permissions] do version = get_version File.open(scope('VERSION'), 'w') {|f| f.puts(version)} load scope('sass.gemspec') Gem::Builder.new(SASS_GEMSPEC).build sh %{git checkout VERSION} pkg = "#{SASS_GEMSPEC.name}-#{SASS_GEMSPEC.version}" mkdir_p "pkg" verbose(true) {mv "#{pkg}.gem", "pkg/#{pkg}.gem"} sh %{rm -f pkg/#{pkg}.tar.gz} verbose(false) {SASS_GEMSPEC.files.each {|f| sh %{tar rf pkg/#{pkg}.tar #{f}}}} sh %{gzip pkg/#{pkg}.tar} end task :permissions do sh %{chmod -R a+rx bin} sh %{chmod -R a+r .} require 'shellwords' Dir.glob('test/**/*_test.rb') do |file| next if file =~ %r{^test/haml/spec/} sh %{chmod a+rx #{file}} end end task :revision_file do require 'lib/sass' release = Rake.application.top_level_tasks.include?('release') || File.exist?(scope('EDGE_GEM_VERSION')) if Sass.version[:rev] && !release File.open(scope('REVISION'), 'w') { |f| f.puts Sass.version[:rev] } elsif release File.open(scope('REVISION'), 'w') { |f| f.puts "(release)" } else File.open(scope('REVISION'), 'w') { |f| f.puts "(unknown)" } end end # We also need to get rid of this file after packaging. at_exit { File.delete(scope('REVISION')) rescue nil } desc "Install Sass as a gem. Use SUDO=1 to install with sudo." task :install => [:package] do gem = RUBY_PLATFORM =~ /java/ ? 'jgem' : 'gem' sh %{#{'sudo ' if ENV["SUDO"]}#{gem} install --no-ri pkg/sass-#{get_version}} end desc "Release a new Sass package to Rubyforge." task :release => [:check_release, :package] do name = File.read(scope("VERSION_NAME")).strip version = File.read(scope("VERSION")).strip sh %{rubyforge add_release sass sass "#{name} (v#{version})" pkg/sass-#{version}.gem} sh %{rubyforge add_file sass sass "#{name} (v#{version})" pkg/sass-#{version}.tar.gz} sh %{gem push pkg/sass-#{version}.gem} end # Ensures that the VERSION file has been updated for a new release. task :check_release do version = File.read(scope("VERSION")).strip raise "There have been changes since current version (#{version})" if changed_since?(version) raise "VERSION_NAME must not be 'Bleeding Edge'" if File.read(scope("VERSION_NAME")) == "Bleeding Edge" end # Reads a password from the command line. # # @param name [String] The prompt to use to read the password def read_password(prompt) require 'readline' system "stty -echo" Readline.readline("#{prompt}: ").strip ensure system "stty echo" puts end # Returns whether or not the repository, or specific files, # has/have changed since a given revision. # # @param rev [String] The revision to check against # @param files [Array] The files to check. # If this is empty, checks the entire repository def changed_since?(rev, *files) IO.popen("git diff --exit-code #{rev} #{files.join(' ')}") {} return !$?.success? end task :submodules do if File.exist?(File.dirname(__FILE__) + "/.git") sh %{git submodule sync} sh %{git submodule update --init} elsif !File.exist?(File.dirname(__FILE__) + "/vendor/fssm/lib") warn < :yard task :redoc => :yard rescue LoadError desc "Generate Documentation" task :doc => :rdoc task :yard => :rdoc end task :pages do ensure_git_cleanup do puts "#{'=' * 50} Running rake pages" sh %{git checkout sass-pages} sh %{git reset --hard origin/sass-pages} Dir.chdir("/var/www/sass-pages") do sh %{git fetch origin} sh %{git checkout stable} sh %{git reset --hard origin/stable} sh %{git checkout sass-pages} sh %{git reset --hard origin/sass-pages} sh %{rake build --trace} sh %{mkdir -p tmp} sh %{touch tmp/restart.txt} end end end # ----- Coverage ----- begin require 'rcov/rcovtask' Rcov::RcovTask.new do |t| t.test_files = FileList[scope('test/**/*_test.rb')] t.rcov_opts << '-x' << '"^\/"' if ENV['NON_NATIVE'] t.rcov_opts << "--no-rcovrt" end t.verbose = true end rescue LoadError; end # ----- Profiling ----- begin require 'ruby-prof' desc < e IO.popen("sendmail nex342@gmail.com", "w") do |sm| sm << "From: nex3@nex-3.com\n" << "To: nex342@gmail.com\n" << "Subject: Exception when running rake #{Rake.application.top_level_tasks.join(', ')}\n" << e.message << "\n\n" << e.backtrace.join("\n") end ensure raise e if e end def ensure_git_cleanup email_on_error {yield} ensure sh %{git reset --hard HEAD} sh %{git clean -xdf} sh %{git checkout master} end task :handle_update do email_on_error do unless ENV["REF"] =~ %r{^refs/heads/(master|stable|sass-pages)$} puts "#{'=' * 20} Ignoring rake handle_update REF=#{ENV["REF"].inspect}" next end branch = $1 puts puts puts '=' * 150 puts "Running rake handle_update REF=#{ENV["REF"].inspect}" sh %{git fetch origin} sh %{git checkout stable} sh %{git reset --hard origin/stable} sh %{git checkout master} sh %{git reset --hard origin/master} case branch when "master" sh %{rake release_edge --trace} when "stable", "sass-pages" sh %{rake pages --trace} end puts 'Done running handle_update' puts '=' * 150 end end stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/0000775000175000017500000000000012206724733032007 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/0000775000175000017500000000000012206724733032760 5ustar jamespagejamespage././@LongLink0000644000000000000000000000014612255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/data/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/data0000775000175000017500000000000012206724733033612 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/data/hsl-rgb.txtstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/data0000664000175000017500000001216212206724733033616 0ustar jamespagejamespagehsl(0, 100%, 50%) hsl(60, 100%, 50%) hsl(120, 100%, 50%) hsl(180, 100%, 50%) hsl(240, 100%, 50%) hsl(300, 100%, 50%) ==== rgb(255, 0, 0) rgb(255, 255, 0) rgb(0, 255, 0) rgb(0, 255, 255) rgb(0, 0, 255) rgb(255, 0, 255) hsl(-360, 100%, 50%) hsl(-300, 100%, 50%) hsl(-240, 100%, 50%) hsl(-180, 100%, 50%) hsl(-120, 100%, 50%) hsl(-60, 100%, 50%) ==== rgb(255, 0, 0) rgb(255, 255, 0) rgb(0, 255, 0) rgb(0, 255, 255) rgb(0, 0, 255) rgb(255, 0, 255) hsl(360, 100%, 50%) hsl(420, 100%, 50%) hsl(480, 100%, 50%) hsl(540, 100%, 50%) hsl(600, 100%, 50%) hsl(660, 100%, 50%) ==== rgb(255, 0, 0) rgb(255, 255, 0) rgb(0, 255, 0) rgb(0, 255, 255) rgb(0, 0, 255) rgb(255, 0, 255) hsl(6120, 100%, 50%) hsl(-9660, 100%, 50%) hsl(99840, 100%, 50%) hsl(-900, 100%, 50%) hsl(-104880, 100%, 50%) hsl(2820, 100%, 50%) ==== rgb(255, 0, 0) rgb(255, 255, 0) rgb(0, 255, 0) rgb(0, 255, 255) rgb(0, 0, 255) rgb(255, 0, 255) hsl(0, 100%, 50%) hsl(12, 100%, 50%) hsl(24, 100%, 50%) hsl(36, 100%, 50%) hsl(48, 100%, 50%) hsl(60, 100%, 50%) hsl(72, 100%, 50%) hsl(84, 100%, 50%) hsl(96, 100%, 50%) hsl(108, 100%, 50%) hsl(120, 100%, 50%) ==== rgb(255, 0, 0) rgb(255, 51, 0) rgb(255, 102, 0) rgb(255, 153, 0) rgb(255, 204, 0) rgb(255, 255, 0) rgb(204, 255, 0) rgb(153, 255, 0) rgb(102, 255, 0) rgb(51, 255, 0) rgb(0, 255, 0) hsl(120, 100%, 50%) hsl(132, 100%, 50%) hsl(144, 100%, 50%) hsl(156, 100%, 50%) hsl(168, 100%, 50%) hsl(180, 100%, 50%) hsl(192, 100%, 50%) hsl(204, 100%, 50%) hsl(216, 100%, 50%) hsl(228, 100%, 50%) hsl(240, 100%, 50%) ==== rgb(0, 255, 0) rgb(0, 255, 51) rgb(0, 255, 102) rgb(0, 255, 153) rgb(0, 255, 204) rgb(0, 255, 255) rgb(0, 204, 255) rgb(0, 153, 255) rgb(0, 102, 255) rgb(0, 51, 255) rgb(0, 0, 255) hsl(240, 100%, 50%) hsl(252, 100%, 50%) hsl(264, 100%, 50%) hsl(276, 100%, 50%) hsl(288, 100%, 50%) hsl(300, 100%, 50%) hsl(312, 100%, 50%) hsl(324, 100%, 50%) hsl(336, 100%, 50%) hsl(348, 100%, 50%) hsl(360, 100%, 50%) ==== rgb(0, 0, 255) rgb(51, 0, 255) rgb(102, 0, 255) rgb(153, 0, 255) rgb(204, 0, 255) rgb(255, 0, 255) rgb(255, 0, 204) rgb(255, 0, 153) rgb(255, 0, 102) rgb(255, 0, 51) rgb(255, 0, 0) hsl(0, 20%, 50%) hsl(0, 60%, 50%) hsl(0, 100%, 50%) ==== rgb(153, 102, 102) rgb(204, 51, 51) rgb(255, 0, 0) hsl(60, 20%, 50%) hsl(60, 60%, 50%) hsl(60, 100%, 50%) ==== rgb(153, 153, 102) rgb(204, 204, 51) rgb(255, 255, 0) hsl(120, 20%, 50%) hsl(120, 60%, 50%) hsl(120, 100%, 50%) ==== rgb(102, 153, 102) rgb(51, 204, 51) rgb(0, 255, 0) hsl(180, 20%, 50%) hsl(180, 60%, 50%) hsl(180, 100%, 50%) ==== rgb(102, 153, 153) rgb(51, 204, 204) rgb(0, 255, 255) hsl(240, 20%, 50%) hsl(240, 60%, 50%) hsl(240, 100%, 50%) ==== rgb(102, 102, 153) rgb(51, 51, 204) rgb(0, 0, 255) hsl(300, 20%, 50%) hsl(300, 60%, 50%) hsl(300, 100%, 50%) ==== rgb(153, 102, 153) rgb(204, 51, 204) rgb(255, 0, 255) hsl(0, 100%, 0%) hsl(0, 100%, 10%) hsl(0, 100%, 20%) hsl(0, 100%, 30%) hsl(0, 100%, 40%) hsl(0, 100%, 50%) hsl(0, 100%, 60%) hsl(0, 100%, 70%) hsl(0, 100%, 80%) hsl(0, 100%, 90%) hsl(0, 100%, 100%) ==== rgb(0, 0, 0) rgb(51, 0, 0) rgb(102, 0, 0) rgb(153, 0, 0) rgb(204, 0, 0) rgb(255, 0, 0) rgb(255, 51, 51) rgb(255, 102, 102) rgb(255, 153, 153) rgb(255, 204, 204) rgb(255, 255, 255) hsl(60, 100%, 0%) hsl(60, 100%, 10%) hsl(60, 100%, 20%) hsl(60, 100%, 30%) hsl(60, 100%, 40%) hsl(60, 100%, 50%) hsl(60, 100%, 60%) hsl(60, 100%, 70%) hsl(60, 100%, 80%) hsl(60, 100%, 90%) hsl(60, 100%, 100%) ==== rgb(0, 0, 0) rgb(51, 51, 0) rgb(102, 102, 0) rgb(153, 153, 0) rgb(204, 204, 0) rgb(255, 255, 0) rgb(255, 255, 51) rgb(255, 255, 102) rgb(255, 255, 153) rgb(255, 255, 204) rgb(255, 255, 255) hsl(120, 100%, 0%) hsl(120, 100%, 10%) hsl(120, 100%, 20%) hsl(120, 100%, 30%) hsl(120, 100%, 40%) hsl(120, 100%, 50%) hsl(120, 100%, 60%) hsl(120, 100%, 70%) hsl(120, 100%, 80%) hsl(120, 100%, 90%) hsl(120, 100%, 100%) ==== rgb(0, 0, 0) rgb(0, 51, 0) rgb(0, 102, 0) rgb(0, 153, 0) rgb(0, 204, 0) rgb(0, 255, 0) rgb(51, 255, 51) rgb(102, 255, 102) rgb(153, 255, 153) rgb(204, 255, 204) rgb(255, 255, 255) hsl(180, 100%, 0%) hsl(180, 100%, 10%) hsl(180, 100%, 20%) hsl(180, 100%, 30%) hsl(180, 100%, 40%) hsl(180, 100%, 50%) hsl(180, 100%, 60%) hsl(180, 100%, 70%) hsl(180, 100%, 80%) hsl(180, 100%, 90%) hsl(180, 100%, 100%) ==== rgb(0, 0, 0) rgb(0, 51, 51) rgb(0, 102, 102) rgb(0, 153, 153) rgb(0, 204, 204) rgb(0, 255, 255) rgb(51, 255, 255) rgb(102, 255, 255) rgb(153, 255, 255) rgb(204, 255, 255) rgb(255, 255, 255) hsl(240, 100%, 0%) hsl(240, 100%, 10%) hsl(240, 100%, 20%) hsl(240, 100%, 30%) hsl(240, 100%, 40%) hsl(240, 100%, 50%) hsl(240, 100%, 60%) hsl(240, 100%, 70%) hsl(240, 100%, 80%) hsl(240, 100%, 90%) hsl(240, 100%, 100%) ==== rgb(0, 0, 0) rgb(0, 0, 51) rgb(0, 0, 102) rgb(0, 0, 153) rgb(0, 0, 204) rgb(0, 0, 255) rgb(51, 51, 255) rgb(102, 102, 255) rgb(153, 153, 255) rgb(204, 204, 255) rgb(255, 255, 255) hsl(300, 100%, 0%) hsl(300, 100%, 10%) hsl(300, 100%, 20%) hsl(300, 100%, 30%) hsl(300, 100%, 40%) hsl(300, 100%, 50%) hsl(300, 100%, 60%) hsl(300, 100%, 70%) hsl(300, 100%, 80%) hsl(300, 100%, 90%) hsl(300, 100%, 100%) ==== rgb(0, 0, 0) rgb(51, 0, 51) rgb(102, 0, 102) rgb(153, 0, 153) rgb(204, 0, 204) rgb(255, 0, 255) rgb(255, 51, 255) rgb(255, 102, 255) rgb(255, 153, 255) rgb(255, 204, 255) rgb(255, 255, 255) ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/css2sass_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/css20000775000175000017500000001523412206724733033565 0ustar jamespagejamespage#!/usr/bin/env ruby require 'test/unit' require File.dirname(__FILE__) + '/../test_helper' require 'sass/css' class CSS2SassTest < Test::Unit::TestCase def test_basic css = < true)) h1 :color red SASS end def test_nesting assert_equal(< err assert_equal(1, err.sass_line) assert_equal('Invalid CSS after "foo": expected "{", was ""', err.message) end def test_error_reporting_in_line css2sass("foo\nbar }\nbaz") assert(false, "Expected exception") rescue Sass::SyntaxError => err assert_equal(2, err.sass_line) assert_equal('Invalid CSS after "bar ": expected "{", was "}"', err.message) end def test_error_truncate_after css2sass("#{"a" * 16}foo") assert(false, "Expected exception") rescue Sass::SyntaxError => err assert_equal(1, err.sass_line) assert_equal('Invalid CSS after "...aaaaaaaaaaaafoo": expected "{", was ""', err.message) end def test_error_truncate_was css2sass("foo }foo#{"a" * 15}") assert(false, "Expected exception") rescue Sass::SyntaxError => err assert_equal(1, err.sass_line) assert_equal('Invalid CSS after "foo ": expected "{", was "}fooaaaaaaaaaaa..."', err.message) end def test_error_doesnt_truncate_after_when_elipsis_would_add_length css2sass("#{"a" * 15}foo") assert(false, "Expected exception") rescue Sass::SyntaxError => err assert_equal(1, err.sass_line) assert_equal('Invalid CSS after "aaaaaaaaaaaaaaafoo": expected "{", was ""', err.message) end def test_error_doesnt_truncate_was_when_elipsis_would_add_length css2sass("foo }foo#{"a" * 14}") assert(false, "Expected exception") rescue Sass::SyntaxError => err assert_equal(1, err.sass_line) assert_equal('Invalid CSS after "foo ": expected "{", was "}fooaaaaaaaaaaaaaa"', err.message) end def test_error_gets_rid_of_trailing_newline_for_after css2sass("foo \n ") assert(false, "Expected exception") rescue Sass::SyntaxError => err assert_equal(2, err.sass_line) assert_equal('Invalid CSS after "foo": expected "{", was ""', err.message) end def test_error_gets_rid_of_trailing_newline_for_was css2sass("foo \n }foo") assert(false, "Expected exception") rescue Sass::SyntaxError => err assert_equal(2, err.sass_line) assert_equal('Invalid CSS after "foo": expected "{", was "}foo"', err.message) end # Encodings unless Sass::Util.ruby1_8? def test_encoding_error css2sass("foo\nbar\nb\xFEaz".force_encoding("utf-8")) assert(false, "Expected exception") rescue Sass::SyntaxError => e assert_equal(3, e.sass_line) assert_equal('Invalid UTF-8 character "\xFE"', e.message) end def test_ascii_incompatible_encoding_error template = "foo\nbar\nb_z".encode("utf-16le") template[9] = "\xFE".force_encoding("utf-16le") css2sass(template) assert(false, "Expected exception") rescue Sass::SyntaxError => e assert_equal(3, e.sass_line) assert_equal('Invalid UTF-16LE character "\xFE"', e.message) end end private def css2sass(string, opts={}) Sass::CSS.new(string, opts).render end end ././@LongLink0000644000000000000000000000015312255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000775000175000017500000000000012206724733033646 5ustar jamespagejamespage././@LongLink0000644000000000000000000000020212255653646011652 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/import_charset_1_8.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000005712206724733033652 0ustar jamespagejamespage.foo a: b @import "imported_charset_ibm866" ././@LongLink0000644000000000000000000000017012255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/importee.lessstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000003612206724733033647 0ustar jamespagejamespage.foo {a: b} .bar () {c: d} ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/bork1.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000002312206724733033643 0ustar jamespagejamespagebork :bork $bork ././@LongLink0000644000000000000000000000016612255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/import.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000034212206724733033647 0ustar jamespagejamespage$preconst: hello =premixin pre-mixin: here @import importee.sass, scss_importee, "basic.sass", basic.css, ../results/complex.css @import partial.sass nonimported :myconst $preconst :otherconst $postconst +postmixin ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/bork3.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000001512206724733033644 0ustar jamespagejamespagebork bork: ././@LongLink0000644000000000000000000000017212255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/mixin_bork.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000006012206724733033644 0ustar jamespagejamespage=outer-mixin +error-mixin foo +outer-mixin ././@LongLink0000644000000000000000000000017412255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/nested_bork4.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000001712206724733033646 0ustar jamespagejamespage @import bork4 ././@LongLink0000644000000000000000000000017412255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/line_numbers.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000014712206724733033652 0ustar jamespagejamespagefoo bar: baz =premixin squggle blat: bang $preconst: 12 @import importee umph +crazymixin././@LongLink0000644000000000000000000000020112255653646011651 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/nested_mixin_bork.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000006612206724733033652 0ustar jamespagejamespage =error-mixin width: 1px * 1em @import mixin_bork ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/if.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000015412206724733033650 0ustar jamespagejamespagea @if true branch: if @else branch: else b @if false branch: if @else branch: else ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/basic.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000046212206724733033652 0ustar jamespagejamespage body :font Arial :background blue #page :width 700px :height 100 #header :height 300px h1 :font-size 50px :color blue #content.user.show #container.top #column.left :width 100px #column.right :width 600px #container.bottom :background brown././@LongLink0000644000000000000000000000021012255653646011651 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/_imported_charset_ibm866.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000003712206724733033650 0ustar jamespagejamespage@charset "IBM866" .bar a: ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/units.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000050012206724733033643 0ustar jamespagejamespageb :foo 0.5 * 10px :bar 10zzz * 12px / 5zzz :baz percentage(12.0px / 18px) :many-units 10.0zzz / 3yyy * 12px / 5zzz * 3yyy / 3px * 4em :mm 5mm + 1cm :pc 1pc + 12pt :pt 72pt - 2in :inches 1in + 2.54cm :more-inches 1in + ((72pt * 2in) + (36pt * 1in)) / 2.54cm :mixed (1 + (1em * 6px / 3in)) * 4in / 2em ././@LongLink0000644000000000000000000000017012255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/expanded.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000034112206724733033646 0ustar jamespagejamespage#main :width 15em :color #0000ff p :border :style dotted /* Nested comment More nested stuff :width 2px .cool :width 100px #left :font :size 2em :weight bold :float left ././@LongLink0000644000000000000000000000017512255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/warn_imported.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000010212206724733033641 0ustar jamespagejamespage@warn "Imported" =emits-a-warning @warn "In an imported mixin" ././@LongLink0000644000000000000000000000017412255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/nested_bork2.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000001712206724733033646 0ustar jamespagejamespage @import bork2 ././@LongLink0000644000000000000000000000017512255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/nested_import.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000002512206724733033645 0ustar jamespagejamespage.foo @import basic ././@LongLink0000644000000000000000000000020612255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/_imported_charset_utf8.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000003712206724733033650 0ustar jamespagejamespage@charset "UTF-8" .bar a: щ ././@LongLink0000644000000000000000000000016612255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/mixins.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000161612206724733033654 0ustar jamespagejamespage$yellow: #fc0 =bordered :border :top :width 2px :color $yellow :left :width 1px :color #000 -moz-border-radius: 10px =header-font :color #f00 :font :size 20px =compound +header-font +bordered =complex +header-font text: decoration: none &:after content: "." display: block height: 0 clear: both visibility: hidden * html & height: 1px +header-font =deep a:hover :text-decoration underline +compound #main :width 15em :color #0000ff p +bordered :border :style dotted :width 2px .cool :width 100px #left +bordered :font :size 2em :weight bold :float left #right +bordered +header-font :float right .bordered +bordered .complex +complex .more-complex +complex +deep display: inline -webkit-nonsense: top-right: 1px bottom-left: 1px ././@LongLink0000644000000000000000000000016312255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/alt.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000036312206724733033652 0ustar jamespagejamespageh1 :float left :width 274px height: 75px margin: 0 background: repeat: no-repeat :image none a:hover, a:visited color: green b:hover color: red :background-color green const nosp: 1 + 2 sp : 1 + 2 ././@LongLink0000644000000000000000000000017412255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/nested_bork1.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000001712206724733033646 0ustar jamespagejamespage @import bork1 ././@LongLink0000644000000000000000000000017312255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/scss_import.scssstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000040412206724733033646 0ustar jamespagejamespage$preconst: hello; @mixin premixin {pre-mixin: here} @import "importee.sass", "scss_importee", "basic.sass", "basic.css", "../results/complex.css"; @import "partial.sass"; nonimported { myconst: $preconst; otherconst: $postconst; @include postmixin; } ././@LongLink0000644000000000000000000000017212255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/compressed.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000025712206724733033654 0ustar jamespagejamespage#main :width 15em :color #0000ff p :border :style dotted :width 2px .cool :width 100px #left :font :size 2em :weight bold :float left ././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/warn.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000010512206724733033644 0ustar jamespagejamespage@warn "In the main file" @import warn_imported.sass +emits-a-warning ././@LongLink0000644000000000000000000000016712255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/compact.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000034112206724733033646 0ustar jamespagejamespage#main :width 15em :color #0000ff p :border :style dotted /* Nested comment More nested stuff :width 2px .cool :width 100px #left :font :size 2em :weight bold :float left ././@LongLink0000644000000000000000000000017212255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/parent_ref.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000054512206724733033654 0ustar jamespagejamespagea :color #000 &:hover :color #f00 p, div :width 100em & foo :width 10em &:hover, bar :height 20em #cool :border :style solid :width 2em .ie7 &, .ie6 & :content string("Totally not cool.") .firefox & :content string("Quite cool.") .wow, .snazzy :font-family fantasy &:hover, &:visited :font-weight bold ././@LongLink0000644000000000000000000000016712255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/complex.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000001422512206724733033654 0ustar jamespagejamespagebody :margin 0 :font 0.85em "Lucida Grande", "Trebuchet MS", Verdana, sans-serif :color #fff :background url(/images/global_bg.gif) #page :width 900px :margin 0 auto :background #440008 :border-top :width 5px :style solid :color #ff8500 #header :height 75px :padding 0 h1 :float left :width 274px :height 75px :margin 0 :background :image url(/images/global_logo.gif) /* Crazy nested comment :repeat no-repeat :text-indent -9999px .status :float right :padding :top .5em :left .5em :right .5em :bottom 0 p :float left :margin :top 0 :right 0.5em :bottom 0 :left 0 ul :float left :margin 0 :padding 0 li :list-style-type none :display inline :margin 0 5px a:link, a:visited :color #ff8500 :text-decoration none a:hover :text-decoration underline .search :float right :clear right :margin 12px 0 0 0 form :margin 0 input :margin 0 3px 0 0 :padding 2px :border none #menu :clear both :text-align right :height 20px :border-bottom 5px solid #006b95 :background #00a4e4 .contests ul :margin 0 5px 0 0 :padding 0 li :list-style-type none :margin 0 5px :padding 5px 5px 0 5px :display inline :font-size 1.1em // This comment is properly indented :color #fff :background #00a4e4 a:link, a:visited :color #fff :text-decoration none :font-weight bold a:hover :text-decoration underline //General content information #content :clear both .container :clear both .column :float left .right :float right a:link, a:visited :color #93d700 :text-decoration none a:hover :text-decoration underline // A hard tab: #content p, div :width 40em li, dt, dd :color #ddffdd :background-color #4792bb .container.video .column.left :width 200px .box :margin-top 10px p :margin 0 1em auto 1em .box.participants img :float left :margin 0 1em auto 1em :border 1px solid #6e000d :style solid h2 :margin 0 0 10px 0 :padding 0.5em /* The background image is a gif! :background #6e000d url(/images/hdr_participant.gif) 2px 2px no-repeat /* Okay check this out Multiline comments Wow dude I mean seriously, WOW :text-indent -9999px // And also... Multiline comments that don't output! Snazzy, no? :border :top :width 5px :style solid :color #a20013 :right :width 1px :style dotted .column.middle :width 500px .column.right :width 200px .box :margin-top 0 p :margin 0 1em auto 1em .column p :margin-top 0 #content.contests .container.information .column.right .box :margin 1em 0 .box.videos .thumbnail img :width 200px :height 150px :margin-bottom 5px a:link, a:visited :color #93d700 :text-decoration none a:hover :text-decoration underline .box.votes a :display block :width 200px :height 60px :margin 15px 0 :background url(/images/btn_votenow.gif) no-repeat :text-indent -9999px :outline none :border none h2 :margin 52px 0 10px 0 :padding 0.5em :background #6e000d url(/images/hdr_videostats.gif) 2px 2px no-repeat :text-indent -9999px :border-top 5px solid #a20013 #content.contests .container.video .box.videos h2 :margin 0 :padding 0.5em :background #6e000d url(/images/hdr_newestclips.gif) 2px 2px no-repeat :text-indent -9999px :border-top 5px solid #a20013 table :width 100 td :padding 1em :width 25 :vertical-align top p :margin 0 0 5px 0 a:link, a:visited :color #93d700 :text-decoration none a:hover :text-decoration underline .thumbnail :float left img :width 80px :height 60px :margin 0 10px 0 0 :border 1px solid #6e000d #content .container.comments .column :margin-top 15px .column.left :width 600px .box ol :margin 0 :padding 0 li :list-style-type none :padding 10px :margin 0 0 1em 0 :background #6e000d :border-top 5px solid #a20013 div :margin-bottom 1em ul :text-align right li :display inline :border none :padding 0 .column.right :width 290px :padding-left 10px h2 :margin 0 :padding 0.5em :background #6e000d url(/images/hdr_addcomment.gif) 2px 2px no-repeat :text-indent -9999px :border-top 5px solid #a20013 .box textarea :width 290px :height 100px :border none #footer :margin-top 10px :padding 1.2em 1.5em :background #ff8500 ul :margin 0 :padding 0 :list-style-type none li :display inline :margin 0 0.5em :color #440008 ul.links :float left a:link, a:visited :color #440008 :text-decoration none a:hover :text-decoration underline ul.copyright :float right .clear :clear both .centered :text-align center img :border none button.short :width 60px :height 22px :padding 0 0 2px 0 :color #fff :border none :background url(/images/btn_short.gif) no-repeat table :border-collapse collapse ././@LongLink0000644000000000000000000000016612255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/nested.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000051712206724733033653 0ustar jamespagejamespage#main :width 15em :color #0000ff p :border :style dotted /* Nested comment More nested stuff :width 2px .cool :width 100px #left :font :size 2em :weight bold :float left #right .header :border-style solid .body :border-style dotted .footer :border-style dashed ././@LongLink0000644000000000000000000000017012255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/importee.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000031412206724733033646 0ustar jamespagejamespage$postconst: goodbye =postmixin post-mixin: here imported :otherconst $preconst :myconst $postconst +premixin @import basic midrule :inthe middle =crazymixin foo: bar baz blat: bang ././@LongLink0000644000000000000000000000017012255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/_partial.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000003612206724733033647 0ustar jamespagejamespage#foo :background-color #baf ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/subdir/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000775000175000017500000000000012206724733033646 5ustar jamespagejamespage././@LongLink0000644000000000000000000000020012255653646011650 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/subdir/nested_subdir/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000775000175000017500000000000012206724733033646 5ustar jamespagejamespage././@LongLink0000644000000000000000000000022412255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/subdir/nested_subdir/_nested_partial.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000003112206724733033642 0ustar jamespagejamespage#nested :relative true ././@LongLink0000644000000000000000000000022212255653646011654 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/subdir/nested_subdir/nested_subdir.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000002712206724733033647 0ustar jamespagejamespage#pi :width 314px ././@LongLink0000644000000000000000000000017512255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/subdir/subdir.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000013312206724733033645 0ustar jamespagejamespage@import nested_subdir/nested_partial.sass #subdir :font :size 20px :weight bold ././@LongLink0000644000000000000000000000017112255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/multiline.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000034312206724733033650 0ustar jamespagejamespage#main, #header height: 50px div width: 100px a, em span color: pink #one, #two, #three div.nested, span.nested, p.nested :font :weight bold :border-color red :display block././@LongLink0000644000000000000000000000017612255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/import_charset.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000025612206724733033653 0ustar jamespagejamespage.foo a: b // Even though the imported file is in IBM866, // since the root file is in UTF-8/ASCII // the output will end up being UTF-8. @import "imported_charset_ibm866" ././@LongLink0000644000000000000000000000020512255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/import_charset_ibm866.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000027212206724733033651 0ustar jamespagejamespage@charset "IBM866" .foo a: b // Even though the imported file is in UTF-8, // since the root file is in IBM866 // the output will end up being IBM866. @import "imported_charset_utf8" ././@LongLink0000644000000000000000000000016712255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/options.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000003412206724733033645 0ustar jamespagejamespagefoo style: option("style")././@LongLink0000644000000000000000000000016612255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/script.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000312612206724733033652 0ustar jamespagejamespage$width: 10em + 20 $color: #00ff98 $main_text: #ffa $num: 10 $dec: 10.2 $dec_0: 99.0 $neg: -10 $esc: 10\+12 $str: Hello\! $qstr: "Quo\"ted\"!" $hstr: Hyph-en\! $space: #{5 + 4} hi there $percent: 11% $complex: 1px/1em #main :content $str :qstr $qstr :hstr $hstr :width $width :background-color #000 :color $main_text :short-color #123 :named-color olive :con "foo" bar ($space "boom") :con2 "noquo" quo #sidebar :background-color $color :num :normal $num :dec $dec :dec0 $dec_0 :neg $neg :esc $esc :many 1 + 2 + 3 :order 1 + 2 * 3 :complex ((1 + 2) + 15)+#3a8b9f + (hi+(1 +1+ 2)* 4) #plus :num :num 5+2 :num-un 10em + 15em :num-un2 10 + 13em :num-neg 10 + -.13 :str 100 * 1px :col 13 + #aaa :perc $percent + 20% :str :str "hi" + "\ there" :str2 "hi" + " there" :col "14em solid " + #123 :num "times: " + 13 :col :num #f02 + 123.5 :col #12A + #405162 #minus :num :num 912 - 12 :col :num #fffffa - 5.2 :col #abcdef - #fedcba :unary :num -1 :const -$neg :paren -(5 + 6) :two --12 :many --------12 :crazy -----(5 + ---$neg) #times :num :num 2 * 3.5 :col 2 * #3a4b5c :col :num #12468a * 0.5 :col #121212 * #020304 #div :num :num (10 / 3.0) :num2 (10 / 3) :col :num #12468a / 2 :col #abcdef / #0f0f0f :comp $complex * 1em #mod :num :num 17 % 3 :col :col #5f6e7d % #10200a :num #aaabac % 3 #const :escaped :quote \$foo \!bar :default $str !important #regression :a (3 + 2) - 1 ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/bork2.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000002412206724733033644 0ustar jamespagejamespagebork :bork: bork; ././@LongLink0000644000000000000000000000017412255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/nested_bork3.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000001712206724733033646 0ustar jamespagejamespage @import bork3 ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/bork4.sassstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000001412206724733033643 0ustar jamespagejamespage bork: blah ././@LongLink0000644000000000000000000000017512255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/templates/scss_importee.scssstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/temp0000664000175000017500000000002512206724733033645 0ustar jamespagejamespagescss {imported: yes} ././@LongLink0000644000000000000000000000015712255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/extend_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/exte0000775000175000017500000005243012206724733033657 0ustar jamespagejamespage#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../test_helper' class ExtendTest < Test::Unit::TestCase def test_basic assert_equal < :sass) .foo, .bar { a: b; } CSS .foo a: b .bar @extend .foo SASS assert_equal < :sass) .foo, .bar { a: b; } CSS .foo a: b .bar @extend \#{".foo"} SASS end def test_multiple_targets assert_equal < bar { a: b; } CSS .baz .foo {a: b} foo > bar {@extend .foo} SCSS end def test_nested_extender_finds_common_selectors_around_child_selector assert_equal < b c .c1, a > b c .c2 { a: b; } CSS a > b c .c1 {a: b} a c .c2 {@extend .c1} SCSS assert_equal < b c .c1, a > b c .c2 { a: b; } CSS a > b c .c1 {a: b} b c .c2 {@extend .c1} SCSS end def test_nested_extender_doesnt_find_common_selectors_around_adjacent_sibling_selector assert_equal < .bap .foo, .bip > .bap .grip > .bap .bar, .grip > .bap .bip > .bap .bar { a: b; } CSS .bip > .bap .foo {a: b} .grip > .bap .bar {@extend .foo} SCSS assert_equal < .bip .foo, .bap > .bip .bap > .grip .bar, .bap > .grip .bap > .bip .bar { a: b; } CSS .bap > .bip .foo {a: b} .bap > .grip .bar {@extend .foo} SCSS end def test_nested_extender_with_child_selector_unifies assert_equal < bar.baz { a: b; } CSS .baz.foo {a: b} foo > bar {@extend .foo} SCSS end def test_nested_extender_with_trailing_child_selector assert_raise(Sass::SyntaxError, "bar > can't extend: invalid selector") do render("bar > {@extend .baz}") end end def test_nested_extender_with_sibling_selector assert_equal < > + bar { a: b; } CSS .baz .foo {a: b} foo + > > + bar {@extend .foo} SCSS assert_equal < > bar { a: b; } CSS .baz .foo {a: b} > > bar {@extend .foo} SCSS end def test_nested_extender_merges_with_same_selector assert_equal < .bar .baz, .foo > .bar .bang { a: b; } CSS .foo > .bar .baz {a: b} .foo > .bar .bang {@extend .baz} SCSS end # Loops def test_extend_self_loop assert_equal < :scss}.merge(options)).render end end ././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/more_results/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/more0000775000175000017500000000000012206724733033643 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016712255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/more_results/more1.cssstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/more0000664000175000017500000000054212206724733033646 0ustar jamespagejamespagebody { font: Arial; background: blue; } #page { width: 700px; height: 100; } #page #header { height: 300px; } #page #header h1 { font-size: 50px; color: blue; } #content.user.show #container.top #column.left { width: 100px; } #content.user.show #container.top #column.right { width: 600px; } #content.user.show #container.bottom { background: brown; } ././@LongLink0000644000000000000000000000021212255653646011653 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/more_results/more1_with_line_comments.cssstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/more0000664000175000017500000000127612206724733033653 0ustar jamespagejamespage/* line 3, ../more_templates/more1.sass */ body { font: Arial; background: blue; } /* line 7, ../more_templates/more1.sass */ #page { width: 700px; height: 100; } /* line 10, ../more_templates/more1.sass */ #page #header { height: 300px; } /* line 12, ../more_templates/more1.sass */ #page #header h1 { font-size: 50px; color: blue; } /* line 18, ../more_templates/more1.sass */ #content.user.show #container.top #column.left { width: 100px; } /* line 20, ../more_templates/more1.sass */ #content.user.show #container.top #column.right { width: 600px; } /* line 22, ../more_templates/more1.sass */ #content.user.show #container.bottom { background: brown; } ././@LongLink0000644000000000000000000000017512255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/more_results/more_import.cssstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/more0000664000175000017500000000171712206724733033653 0ustar jamespagejamespageimported { otherconst: hello; myconst: goodbye; pre-mixin: here; } body { font: Arial; background: blue; } #page { width: 700px; height: 100; } #page #header { height: 300px; } #page #header h1 { font-size: 50px; color: blue; } #content.user.show #container.top #column.left { width: 100px; } #content.user.show #container.top #column.right { width: 600px; } #content.user.show #container.bottom { background: brown; } midrule { inthe: middle; } body { font: Arial; background: blue; } #page { width: 700px; height: 100; } #page #header { height: 300px; } #page #header h1 { font-size: 50px; color: blue; } #content.user.show #container.top #column.left { width: 100px; } #content.user.show #container.top #column.right { width: 600px; } #content.user.show #container.bottom { background: brown; } @import url(basic.css); @import url(../results/complex.css); #foo { background-color: #bbaaff; } nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; } ././@LongLink0000644000000000000000000000016312255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/conversion_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/conv0000775000175000017500000004167012206724733033663 0ustar jamespagejamespage#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../test_helper' class ConversionTest < Test::Unit::TestCase def test_basic assert_renders < true foo bar :baz bang :bip bop SASS foo bar { baz: bang; bip: bop; } SCSS end def test_empty_selector assert_renders "foo bar", "foo bar {}" end def test_empty_directive assert_scss_to_sass "@media screen", "@media screen {}" assert_scss_to_scss "@media screen {}" end def test_empty_control_directive assert_renders "@if false", "@if false {}" end def test_nesting assert_renders < true foo bar :baz 12 $bang "bip" SASS foo bar { baz: 12 $bang "bip"; } SCSS end def test_multiline_properties assert_scss_to_sass < true foo :_name val :*name val :#name val :.name val :name val SASS foo { _name: val; *name: val; #name: val; .name: val; name: val; } SCSS end def test_selector_hacks assert_selector_renders = lambda do |s| assert_renders < E'] assert_selector_renders['+ E'] assert_selector_renders['~ E'] assert_selector_renders['> > E'] assert_selector_renders['E*'] assert_selector_renders['E*.foo'] assert_selector_renders['E*:hover'] end def test_disallowed_colon_hack assert_raise_message(Sass::SyntaxError, 'The ":name: val" hack is not allowed in the Sass indented syntax') do to_sass("foo {:name: val;}", :syntax => :scss) end end def test_nested_properties assert_renders < true) @mixin under-scored-mixin($under-scored-arg: $under-scored-default) { bar: $under-scored-arg; } div { foo: under-scored-fn($under-scored-var + "before\#{$another-under-scored-var}after"); @include under-scored-mixin($passed-arg); selector-\#{$under-scored-interp}: bold; } @if $under-scored { @for $for-var from $from-var to $to-var { @while $while-var == true { $while-var: false; } } } SCSS =under_scored_mixin($under_scored_arg: $under_scored_default) bar: $under_scored_arg div foo: under_scored_fn($under_scored_var + "before\#{$another_under_scored_var}after") +under_scored_mixin($passed_arg) selector-\#{$under_scored_interp}: bold @if $under_scored @for $for_var from $from_var to $to_var @while $while_var == true $while_var : false SASS end def test_loud_comment_conversion assert_renders(< :scss)).rstrip, "Expected SCSS to transform to Sass") end def assert_scss_to_scss(scss, in_scss = nil, options = nil) if in_scss.is_a?(Hash) options = in_scss in_scss = nil end in_scss ||= scss options ||= {} assert_equal(scss.rstrip, to_scss(in_scss, options.merge(:syntax => :scss)).rstrip, "Expected SCSS to transform to #{scss == in_scss ? 'itself' : 'SCSS'}k") end def assert_sass_to_scss(scss, sass, options = {}) assert_equal(scss.rstrip, to_scss(sass, options).rstrip, "Expected Sass to transform to SCSS") end def assert_renders(sass, scss, options = {}) assert_sass_to_sass(sass, options) assert_scss_to_sass(sass, scss, options) assert_scss_to_scss(scss, options) assert_sass_to_scss(scss, sass, options) end def to_sass(scss, options = {}) Sass::Util.silence_sass_warnings do Sass::Engine.new(scss, options).to_tree.to_sass(options) end end def to_scss(sass, options = {}) Sass::Util.silence_sass_warnings do Sass::Engine.new(sass, options).to_tree.to_scss(options) end end end ././@LongLink0000644000000000000000000000015512255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/util_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/util0000775000175000017500000001633712206724733033675 0ustar jamespagejamespage#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../test_helper' require 'pathname' class UtilTest < Test::Unit::TestCase include Sass::Util def test_scope assert(File.exist?(scope("Rakefile"))) end def test_to_hash assert_equal({ :foo => 1, :bar => 2, :baz => 3 }, to_hash([[:foo, 1], [:bar, 2], [:baz, 3]])) end def test_map_keys assert_equal({ "foo" => 1, "bar" => 2, "baz" => 3 }, map_keys({:foo => 1, :bar => 2, :baz => 3}) {|k| k.to_s}) end def test_map_vals assert_equal({ :foo => "1", :bar => "2", :baz => "3" }, map_vals({:foo => 1, :bar => 2, :baz => 3}) {|k| k.to_s}) end def test_map_hash assert_equal({ "foo" => "1", "bar" => "2", "baz" => "3" }, map_hash({:foo => 1, :bar => 2, :baz => 3}) {|k, v| [k.to_s, v.to_s]}) end def test_powerset return unless Set[Set[]] == Set[Set[]] # There's a bug in Ruby 1.8.6 that breaks nested set equality assert_equal([[].to_set].to_set, powerset([])) assert_equal([[].to_set, [1].to_set].to_set, powerset([1])) assert_equal([[].to_set, [1].to_set, [2].to_set, [1, 2].to_set].to_set, powerset([1, 2])) assert_equal([[].to_set, [1].to_set, [2].to_set, [3].to_set, [1, 2].to_set, [2, 3].to_set, [1, 3].to_set, [1, 2, 3].to_set].to_set, powerset([1, 2, 3])) end def test_restrict assert_equal(0.5, restrict(0.5, 0..1)) assert_equal(1, restrict(2, 0..1)) assert_equal(1.3, restrict(2, 0..1.3)) assert_equal(0, restrict(-1, 0..1)) end def test_merge_adjacent_strings assert_equal(["foo bar baz", :bang, "biz bop", 12], merge_adjacent_strings(["foo ", "bar ", "baz", :bang, "biz", " bop", 12])) str = "foo" assert_equal(["foo foo foo", :bang, "foo foo", 12], merge_adjacent_strings([str, " ", str, " ", str, :bang, str, " ", str, 12])) end def test_intersperse assert_equal(["foo", " ", "bar", " ", "baz"], intersperse(%w[foo bar baz], " ")) assert_equal([], intersperse([], " ")) end def test_substitute assert_equal(["foo", "bar", "baz", 3, 4], substitute([1, 2, 3, 4], [1, 2], ["foo", "bar", "baz"])) assert_equal([1, "foo", "bar", "baz", 4], substitute([1, 2, 3, 4], [2, 3], ["foo", "bar", "baz"])) assert_equal([1, 2, "foo", "bar", "baz"], substitute([1, 2, 3, 4], [3, 4], ["foo", "bar", "baz"])) assert_equal([1, "foo", "bar", "baz", 2, 3, 4], substitute([1, 2, 2, 2, 3, 4], [2, 2], ["foo", "bar", "baz"])) end def test_strip_string_array assert_equal(["foo ", " bar ", " baz"], strip_string_array([" foo ", " bar ", " baz "])) assert_equal([:foo, " bar ", " baz"], strip_string_array([:foo, " bar ", " baz "])) assert_equal(["foo ", " bar ", :baz], strip_string_array([" foo ", " bar ", :baz])) end def test_paths assert_equal([[1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5]], paths([[1, 2], [3, 4], [5]])) assert_equal([[]], paths([])) assert_equal([[1, 2, 3]], paths([[1], [2], [3]])) end def test_lcs assert_equal([1, 2, 3], lcs([1, 2, 3], [1, 2, 3])) assert_equal([], lcs([], [1, 2, 3])) assert_equal([], lcs([1, 2, 3], [])) assert_equal([1, 2, 3], lcs([5, 1, 4, 2, 3, 17], [0, 0, 1, 2, 6, 3])) assert_equal([1], lcs([1, 2, 3, 4], [4, 3, 2, 1])) assert_equal([1, 2], lcs([1, 2, 3, 4], [3, 4, 1, 2])) end def test_lcs_with_block assert_equal(["1", "2", "3"], lcs([1, 4, 2, 5, 3], [1, 2, 3]) {|a, b| a == b && a.to_s}) assert_equal([-4, 2, 8], lcs([-5, 3, 2, 8], [-4, 1, 8]) {|a, b| (a - b).abs <= 1 && [a, b].max}) end def test_silence_warnings old_stderr, $stderr = $stderr, StringIO.new warn "Out" assert_equal("Out\n", $stderr.string) silence_warnings {warn "In"} assert_equal("Out\n", $stderr.string) ensure $stderr = old_stderr end def test_sass_warn assert_warning("Foo!") {sass_warn "Foo!"} end def test_silence_sass_warnings old_stderr, $stderr = $stderr, StringIO.new silence_sass_warnings {warn "Out"} assert_equal("Out\n", $stderr.string) silence_sass_warnings {sass_warn "In"} assert_equal("Out\n", $stderr.string) ensure $stderr = old_stderr end def test_has assert(has?(:instance_method, String, :chomp!)) assert(has?(:private_instance_method, Sass::Engine, :parse_interp)) end def test_enum_with_index assert_equal(%w[foo0 bar1 baz2], enum_with_index(%w[foo bar baz]).map {|s, i| "#{s}#{i}"}) end def test_enum_cons assert_equal(%w[foobar barbaz], enum_cons(%w[foo bar baz], 2).map {|s1, s2| "#{s1}#{s2}"}) end def test_ord assert_equal(102, ord("f")) assert_equal(98, ord("bar")) end def test_flatten assert_equal([1, 2, 3], flatten([1, 2, 3], 0)) assert_equal([1, 2, 3], flatten([1, 2, 3], 1)) assert_equal([1, 2, 3], flatten([1, 2, 3], 2)) assert_equal([[1, 2], 3], flatten([[1, 2], 3], 0)) assert_equal([1, 2, 3], flatten([[1, 2], 3], 1)) assert_equal([1, 2, 3], flatten([[1, 2], 3], 2)) assert_equal([[[1], 2], [3], 4], flatten([[[1], 2], [3], 4], 0)) assert_equal([[1], 2, 3, 4], flatten([[[1], 2], [3], 4], 1)) assert_equal([1, 2, 3, 4], flatten([[[1], 2], [3], 4], 2)) end def test_set_hash assert(set_hash(Set[1, 2, 3]) == set_hash(Set[3, 2, 1])) assert(set_hash(Set[1, 2, 3]) == set_hash(Set[1, 2, 3])) s1 = Set[] s1 << 1 s1 << 2 s1 << 3 s2 = Set[] s2 << 3 s2 << 2 s2 << 1 assert(set_hash(s1) == set_hash(s2)) end def test_set_eql assert(set_eql?(Set[1, 2, 3], Set[3, 2, 1])) assert(set_eql?(Set[1, 2, 3], Set[1, 2, 3])) s1 = Set[] s1 << 1 s1 << 2 s1 << 3 s2 = Set[] s2 << 3 s2 << 2 s2 << 1 assert(set_eql?(s1, s2)) end def test_caller_info assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle'")) assert_equal(["/tmp/foo.rb", 12, nil], caller_info("/tmp/foo.rb:12")) assert_equal(["(sass)", 12, "blah"], caller_info("(sass):12: in `blah'")) assert_equal(["", 12, "boop"], caller_info(":12: in `boop'")) assert_equal(["/tmp/foo.rb", -12, "fizzle"], caller_info("/tmp/foo.rb:-12: in `fizzle'")) assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle {}'")) end def test_version_gt assert_version_gt("2.0.0", "1.0.0") assert_version_gt("1.1.0", "1.0.0") assert_version_gt("1.0.1", "1.0.0") assert_version_gt("1.0.0", "1.0.0.rc") assert_version_gt("1.0.0.1", "1.0.0.rc") assert_version_gt("1.0.0.rc", "0.9.9") assert_version_gt("1.0.0.beta", "1.0.0.alpha") assert_version_eq("1.0.0", "1.0.0") assert_version_eq("1.0.0", "1.0.0.0") end def assert_version_gt(v1, v2) #assert(version_gt(v1, v2), "Expected #{v1} > #{v2}") assert(!version_gt(v2, v1), "Expected #{v2} < #{v1}") end def assert_version_eq(v1, v2) assert(!version_gt(v1, v2), "Expected #{v1} = #{v2}") assert(!version_gt(v2, v1), "Expected #{v2} = #{v1}") end class FooBar def foo Sass::Util.abstract(self) end end def test_abstract assert_raise_message(NotImplementedError, "UtilTest::FooBar must implement #foo") {FooBar.new.foo} end end ././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/cache_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/cach0000775000175000017500000000474012206724733033611 0ustar jamespagejamespage#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../test_helper' require 'sass/engine' class CacheTest < Test::Unit::TestCase @@cache_dir = "tmp/file_cache" def setup FileUtils.mkdir_p @@cache_dir end def teardown FileUtils.rm_rf @@cache_dir end def test_file_cache_writes_a_file file_store = Sass::CacheStores::Filesystem.new(@@cache_dir) file_store.store("asdf/foo.scssc", "fakesha1", root_node) assert File.exists?("#{@@cache_dir}/asdf/foo.scssc") end def test_file_cache_reads_a_file file_store = Sass::CacheStores::Filesystem.new(@@cache_dir) assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc") file_store.store("asdf/foo.scssc", "fakesha1", root_node) assert File.exists?("#{@@cache_dir}/asdf/foo.scssc") assert_kind_of Sass::Tree::RootNode, file_store.retrieve("asdf/foo.scssc", "fakesha1") end def test_file_cache_miss_returns_nil file_store = Sass::CacheStores::Filesystem.new(@@cache_dir) assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc") assert_nil file_store.retrieve("asdf/foo.scssc", "fakesha1") end def test_sha_change_invalidates_cache_and_cleans_up file_store = Sass::CacheStores::Filesystem.new(@@cache_dir) assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc") file_store.store("asdf/foo.scssc", "fakesha1", root_node) assert File.exists?("#{@@cache_dir}/asdf/foo.scssc") assert_nil file_store.retrieve("asdf/foo.scssc", "differentsha1") assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc") end def test_version_change_invalidates_cache_and_cleans_up file_store = Sass::CacheStores::Filesystem.new(@@cache_dir) assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc") file_store.store("asdf/foo.scssc", "fakesha1", root_node) assert File.exists?("#{@@cache_dir}/asdf/foo.scssc") real_version = Sass::VERSION begin Sass::VERSION.replace("a different version") assert_nil file_store.retrieve("asdf/foo.scssc", "fakesha1") assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc") ensure Sass::VERSION.replace(real_version) end end def test_arbitrary_objects_can_go_into_cache cache = Sass::CacheStores::Memory.new an_object = {:foo => :bar} cache.store("an_object", "", an_object) assert_equal an_object, cache.retrieve("an_object", "") end private def root_node Sass::Engine.new(<<-SCSS, :syntax => :scss).to_tree @mixin color($c) { color: $c} div { @include color(red); } SCSS end end ././@LongLink0000644000000000000000000000014612255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/scss/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/scss0000775000175000017500000000000012206724733033654 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016012255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/scss/rx_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/scss0000775000175000017500000001217312206724733033665 0ustar jamespagejamespage#!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/../../test_helper' require 'sass/engine' class ScssRxTest < Test::Unit::TestCase include Sass::SCSS::RX def test_identifiers assert_match IDENT, "foo" assert_match IDENT, "\xC3\xBFoo" # Initial char can be nonascii assert_match IDENT, "\\123abcoo" # Initial char can be unicode escape assert_match IDENT, "\\f oo" # Unicode escapes can be followed by whitespace assert_match IDENT, "\\fa\too" assert_match IDENT, "\\ff2\roo" assert_match IDENT, "\\f13a\foo" assert_match IDENT, "\\f13abcoo" assert_match IDENT, "\\ oo" # Initial char can be a plain escape as well assert_match IDENT, "\\~oo" assert_match IDENT, "\\\\oo" assert_match IDENT, "\\{oo" assert_match IDENT, "\\\xC3\xBFoo" assert_match IDENT, "-foo" # Can put a - before anything assert_match IDENT, "-\xC3\xBFoo" assert_match IDENT, "-\\f oo" assert_match IDENT, "_foo" # Can put a _ before anything assert_match IDENT, "_\xC3\xBFoo" assert_match IDENT, "_\\f oo" assert_match IDENT, "foo-bar" assert_match IDENT, "f012-23" assert_match IDENT, "foo_-_bar" assert_match IDENT, "f012_23" # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-003.xht assert_match IDENT, "c\\lass" # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-004.xht assert_match IDENT, "c\\00006Cas\\000073" # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-001.xht assert_match IDENT, "IdE6n-3t0_6" # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-006.xht assert_match IDENT, "\\6000ident" # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-007.xht assert_match IDENT, "iden\\6000t\\6000" # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-013.xht assert_match IDENT, "\\-ident" end def test_underscores_in_identifiers assert_match IDENT, "foo_bar" assert_match IDENT, "_\xC3\xBFfoo" assert_match IDENT, "__foo" assert_match IDENT, "_1foo" assert_match IDENT, "-_foo" assert_match IDENT, "_-foo" end def test_invalid_identifiers assert_no_match IDENT, "" assert_no_match IDENT, "1foo" assert_no_match IDENT, "-1foo" assert_no_match IDENT, "--foo" assert_no_match IDENT, "foo bar" assert_no_match IDENT, "foo~bar" # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-008.xht assert_no_match IDENT, "c\\06C ass" assert_no_match IDENT, "back\\67\n round" end def test_double_quote_strings assert_match STRING, '"foo bar"' assert_match STRING, '"foo\\\nbar"' assert_match STRING, "\"\\\"\"" assert_match STRING, '"\t !#$%&(-~()*+,-./0123456789~"' end def test_single_quote_strings assert_match STRING, "'foo bar'" assert_match STRING, "'foo\\\nbar'" assert_match STRING, "'\\''" assert_match STRING, "'\t !#\$%&(-~()*+,-./0123456789~'" end def test_invalid_strings assert_no_match STRING, "\"foo\nbar\"" assert_no_match STRING, "\"foo\"bar\"" assert_no_match STRING, "'foo\nbar'" assert_no_match STRING, "'foo'bar'" end def test_uri assert_match URI, 'url("foo bar)")' assert_match URI, "url('foo bar)')" assert_match URI, 'url( "foo bar)" )' assert_match URI, "url(#\\%&**+,-./0123456789~)" end def test_invalid_uri assert_no_match URI, 'url(foo)bar)' end def test_unicode_range assert_match UNICODERANGE, 'U+00-Ff' assert_match UNICODERANGE, 'u+980-9FF' assert_match UNICODERANGE, 'U+9aF??' assert_match UNICODERANGE, 'U+??' end def test_escape_empty_ident assert_equal "", Sass::SCSS::RX.escape_ident("") end def test_escape_just_prefix_ident assert_equal "\\-", Sass::SCSS::RX.escape_ident("-") assert_equal "\\_", Sass::SCSS::RX.escape_ident("_") end def test_escape_plain_ident assert_equal "foo", Sass::SCSS::RX.escape_ident("foo") assert_equal "foo-1bar", Sass::SCSS::RX.escape_ident("foo-1bar") assert_equal "-foo-bar", Sass::SCSS::RX.escape_ident("-foo-bar") assert_equal "f2oo_bar", Sass::SCSS::RX.escape_ident("f2oo_bar") assert_equal "_foo_bar", Sass::SCSS::RX.escape_ident("_foo_bar") end def test_escape_initial_funky_ident assert_equal "\\000035foo", Sass::SCSS::RX.escape_ident("5foo") assert_equal "-\\000035foo", Sass::SCSS::RX.escape_ident("-5foo") assert_equal "_\\000035foo", Sass::SCSS::RX.escape_ident("_5foo") assert_equal "\\&foo", Sass::SCSS::RX.escape_ident("&foo") assert_equal "-\\&foo", Sass::SCSS::RX.escape_ident("-&foo") assert_equal "-\\ foo", Sass::SCSS::RX.escape_ident("- foo") end def test_escape_mid_funky_ident assert_equal "foo\\&bar", Sass::SCSS::RX.escape_ident("foo&bar") assert_equal "foo\\ \\ bar", Sass::SCSS::RX.escape_ident("foo bar") assert_equal "foo\\00007fbar", Sass::SCSS::RX.escape_ident("foo\177bar") end private def assert_match(rx, str) assert_not_nil(match = rx.match(str)) assert_equal str.size, match[0].size end def assert_no_match(rx, str) match = rx.match(str) assert_not_equal str.size, match && match[0].size end end ././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/scss/test_helper.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/scss0000664000175000017500000000205212206724733033655 0ustar jamespagejamespagerequire File.dirname(__FILE__) + '/../../test_helper' require 'sass/engine' module ScssTestHelper def assert_parses(scss) assert_equal scss.rstrip, render(scss).rstrip end def assert_not_parses(expected, scss) raise "Template must include where an error is expected" unless scss.include?("") after, was = scss.split("") line = after.count("\n") + 1 after.gsub!(/\s*\n\s*$/, '') after.gsub!(/.*\n/, '') after = "..." + after[-15..-1] if after.size > 18 was.gsub!(/^\s*\n\s*/, '') was.gsub!(/\n.*/, '') was = was[0...15] + "..." if was.size > 18 to_render = scss.sub("", "") render(to_render) assert(false, "Expected syntax error for:\n#{to_render}\n") rescue Sass::SyntaxError => err assert_equal("Invalid CSS after \"#{after}\": expected #{expected}, was \"#{was}\"", err.message) assert_equal line, err.sass_line end def render(scss, options = {}) options[:syntax] ||= :scss munge_filename options Sass::Engine.new(scss, options).render end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/scss/css_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/scss0000775000175000017500000004552012206724733033667 0ustar jamespagejamespage#!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/test_helper' require 'sass/scss/css_parser' # These tests just test the parsing of CSS # (both standard and any hacks we intend to support). # Tests of SCSS-specific behavior go in scss_test.rb. class ScssCssTest < Test::Unit::TestCase include ScssTestHelper def test_basic_scss assert_parses < baz {bar: baz} SCSS end if Sass::Util.ruby1_8? def test_unicode assert_parses < F') assert_selector_parses('E + F') assert_selector_parses('E ~ F') end # Taken from http://www.w3.org/TR/css3-selectors/#selectors, # but without the element names def test_lonely_selectors assert_selector_parses('[foo]') assert_selector_parses('[foo="bar"]') assert_selector_parses('[foo~="bar"]') assert_selector_parses('[foo^="bar"]') assert_selector_parses('[foo$="bar"]') assert_selector_parses('[foo*="bar"]') assert_selector_parses('[foo|="en"]') assert_selector_parses(':root') assert_selector_parses(':nth-child(n)') assert_selector_parses(':nth-last-child(n)') assert_selector_parses(':nth-of-type(n)') assert_selector_parses(':nth-last-of-type(n)') assert_selector_parses(':first-child') assert_selector_parses(':last-child') assert_selector_parses(':first-of-type') assert_selector_parses(':last-of-type') assert_selector_parses(':only-child') assert_selector_parses(':only-of-type') assert_selector_parses(':empty') assert_selector_parses(':link') assert_selector_parses(':visited') assert_selector_parses(':active') assert_selector_parses(':hover') assert_selector_parses(':focus') assert_selector_parses(':target') assert_selector_parses(':lang(fr)') assert_selector_parses(':enabled') assert_selector_parses(':disabled') assert_selector_parses(':checked') assert_selector_parses('::first-line') assert_selector_parses('::first-letter') assert_selector_parses('::before') assert_selector_parses('::after') assert_selector_parses('.warning') assert_selector_parses('#myid') assert_selector_parses(':not(s)') end def test_attribute_selectors_with_identifiers assert_selector_parses('[foo~=bar]') assert_selector_parses('[foo^=bar]') assert_selector_parses('[foo$=bar]') assert_selector_parses('[foo*=bar]') assert_selector_parses('[foo|=en]') end def test_nth_selectors assert_selector_parses(':nth-child(-n)') assert_selector_parses(':nth-child(+n)') assert_selector_parses(':nth-child(even)') assert_selector_parses(':nth-child(odd)') assert_selector_parses(':nth-child(50)') assert_selector_parses(':nth-child(-50)') assert_selector_parses(':nth-child(+50)') assert_selector_parses(':nth-child(2n+3)') assert_selector_parses(':nth-child(2n-3)') assert_selector_parses(':nth-child(+2n-3)') assert_selector_parses(':nth-child(-2n+3)') assert_selector_parses(':nth-child(-2n+ 3)') assert_equal(< baz)') assert_selector_parses(':not(h1, h2, h3)') end def test_moz_any_selector assert_selector_parses(':-moz-any(h1, h2, h3)') assert_selector_parses(':-moz-any(.foo)') assert_selector_parses(':-moz-any(foo bar, .baz > .bang)') end def test_namespaced_selectors assert_selector_parses('foo|E') assert_selector_parses('*|E') assert_selector_parses('foo|*') assert_selector_parses('*|*') end def test_namespaced_attribute_selectors assert_selector_parses('[foo|bar=baz]') assert_selector_parses('[*|bar=baz]') assert_selector_parses('[foo|bar|=baz]') end def test_comma_selectors assert_selector_parses('E, F') assert_selector_parses('E F, G H') assert_selector_parses('E > F, G > H') end def test_selectors_with_newlines assert_selector_parses("E,\nF") assert_selector_parses("E\nF") assert_selector_parses("E, F\nG, H") end def test_expression_fallback_selectors assert_selector_parses('0%') assert_selector_parses('60%') assert_selector_parses('100%') assert_selector_parses('12px') assert_selector_parses('"foo"') end def test_functional_pseudo_selectors assert_selector_parses(':foo("bar")') assert_selector_parses(':foo(bar)') assert_selector_parses(':foo(12px)') assert_selector_parses(':foo(+)') assert_selector_parses(':foo(-)') assert_selector_parses(':foo(+"bar")') assert_selector_parses(':foo(-++--baz-"bar"12px)') end def test_selector_hacks assert_selector_parses('> E') assert_selector_parses('+ E') assert_selector_parses('~ E') assert_selector_parses('> > E') assert_equal < > E { a: b; } CSS >> E { a: b; } SCSS assert_selector_parses('E*') assert_selector_parses('E*.foo') assert_selector_parses('E*:hover') end ## Errors def test_invalid_directives assert_not_parses("identifier", '@ import "foo";') assert_not_parses("identifier", '@12 "foo";') end def test_invalid_classes assert_not_parses("class name", 'p. foo {a: b}') assert_not_parses("class name", 'p.1foo {a: b}') end def test_invalid_ids assert_not_parses("id name", 'p# foo {a: b}') end def test_no_properties_at_toplevel assert_not_parses('pseudoclass or pseudoelement', 'a: b;') end def test_no_scss_directives assert_parses('@import "foo.sass";') assert_parses <$var = 12;") assert_not_parses('"}"', "foo { !var = 12; }") end def test_no_parent_selectors assert_not_parses('"{"', "foo &.bar {a: b}") end def test_no_selector_interpolation assert_not_parses('"{"', 'foo #{"bar"}.baz {a: b}') end def test_no_prop_name_interpolation assert_not_parses('":"', 'foo {a#{"bar"}baz: b}') end def test_no_prop_val_interpolation assert_not_parses('"}"', 'foo {a: b #{"bar"} c}') end def test_no_string_interpolation assert_parses <* c}') end def test_no_nested_rules assert_not_parses('":"', 'foo {bar {a: b}}') assert_not_parses('"}"', 'foo {[bar=baz] {a: b}}') end def test_no_nested_properties assert_not_parses('expression (e.g. 1px, bold)', 'foo {bar: {a: b}}') assert_not_parses('expression (e.g. 1px, bold)', 'foo {bar: bang {a: b}}') end def test_no_nested_directives assert_not_parses('"}"', 'foo {@bar {a: b}}') end def test_error_with_windows_newlines render < e assert_equal 'Invalid CSS after "foo {bar": expected ":", was "}"', e.message assert_equal 1, e.sass_line end ## Regressions def test_closing_line_comment_end_with_compact_output assert_equal(< :compact)) /* foo */ bar { baz: bang; } CSS /* * foo */ bar {baz: bang} SCSS end private def assert_selector_parses(selector) assert_parses < e assert_equal < e assert_equal "Mixins may only be defined at the root of a document.", e.message assert_equal 2, e.sass_line end def test_rules_beneath_properties render < e assert_equal 'Illegal nesting: Only properties may be nested beneath properties.', e.message assert_equal 3, e.sass_line end def test_uses_property_exception_with_star_hack render < e assert_equal 'Invalid CSS after " *bar:baz ": expected ";", was "[fail]; }"', e.message assert_equal 2, e.sass_line end def test_uses_property_exception_with_colon_hack render < e assert_equal 'Invalid CSS after " :bar:baz ": expected ";", was "[fail]; }"', e.message assert_equal 2, e.sass_line end def test_uses_rule_exception_with_dot_hack render <; } SCSS assert(false, "Expected syntax error") rescue Sass::SyntaxError => e assert_equal 'Invalid CSS after " .bar:baz ": expected "{", was "; }"', e.message assert_equal 2, e.sass_line end def test_uses_property_exception_with_space_after_name render < e assert_equal 'Invalid CSS after " bar: baz ": expected ";", was "[fail]; }"', e.message assert_equal 2, e.sass_line end def test_uses_property_exception_with_non_identifier_after_name render < e assert_equal 'Invalid CSS after " bar:1px ": expected ";", was "[fail]; }"', e.message assert_equal 2, e.sass_line end def test_uses_property_exception_when_followed_by_open_bracket render < e assert_equal 'Invalid CSS after " bar:{baz: ": expected expression (e.g. 1px, bold), was ".fail} }"', e.message assert_equal 2, e.sass_line end def test_script_error render < e assert_equal 'Invalid CSS after " bar: "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message assert_equal 2, e.sass_line end def test_multiline_script_syntax_error render < e assert_equal 'Invalid CSS after " "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message assert_equal 3, e.sass_line end def test_multiline_script_runtime_error render < e assert_equal "Undefined variable: \"$bang\".", e.message assert_equal 4, e.sass_line end def test_post_multiline_script_runtime_error render < e assert_equal "Undefined variable: \"$bop\".", e.message assert_equal 5, e.sass_line end def test_multiline_property_runtime_error render < e assert_equal "Undefined variable: \"$bang\".", e.message assert_equal 4, e.sass_line end def test_post_resolution_selector_error render "\n\nfoo \#{\") bar\"} {a: b}" assert(false, "Expected syntax error") rescue Sass::SyntaxError => e assert_equal 'Invalid CSS after "foo ": expected selector, was ") bar"', e.message assert_equal 3, e.sass_line end def test_parent_in_mid_selector_error assert_raise_message(Sass::SyntaxError, <:compressed) z a,z b{display:block} CSS a, b { z & { display: block; } } SCSS end def test_if_error_line assert_raise_line(2) {render(< 'Invalid CSS after "1 +": expected expression (e.g. 1px, bold), was ""', "$a: 1 + 2 +" => 'Invalid CSS after "1 + 2 +": expected expression (e.g. 1px, bold), was ""', "$a: 1 + 2 + %" => 'Invalid CSS after "1 + 2 + ": expected expression (e.g. 1px, bold), was "%"', "$a: foo(\"bar\"" => 'Invalid CSS after "foo("bar"": expected ")", was ""', "$a: 1 }" => 'Invalid CSS after "1 ": expected expression (e.g. 1px, bold), was "}"', "$a: 1 }foo\"" => 'Invalid CSS after "1 ": expected expression (e.g. 1px, bold), was "}foo""', ":" => 'Invalid property: ":".', ": a" => 'Invalid property: ": a".', "a\n :b" => < 'Invalid property: "b:" (no value).', "a\n :b: c" => 'Invalid property: ":b: c".', "a\n :b:c d" => 'Invalid property: ":b:c d".', "a\n :b c;" => 'Invalid CSS after "c": expected expression (e.g. 1px, bold), was ";"', "a\n b: c;" => 'Invalid CSS after "c": expected expression (e.g. 1px, bold), was ";"', ".foo ^bar\n a: b" => ['Invalid CSS after ".foo ": expected selector, was "^bar"', 1], "a\n @extend .foo ^bar" => 'Invalid CSS after ".foo ": expected selector, was "^bar"', "a: b" => 'Properties are only allowed within rules, directives, or other properties.', ":a b" => 'Properties are only allowed within rules, directives, or other properties.', "$" => 'Invalid variable: "$".', "$a" => 'Invalid variable: "$a".', "$ a" => 'Invalid variable: "$ a".', "$a b" => 'Invalid variable: "$a b".', "$a: 1b + 2c" => "Incompatible units: 'c' and 'b'.", "$a: 1b < 2c" => "Incompatible units: 'c' and 'b'.", "$a: 1b > 2c" => "Incompatible units: 'c' and 'b'.", "$a: 1b <= 2c" => "Incompatible units: 'c' and 'b'.", "$a: 1b >= 2c" => "Incompatible units: 'c' and 'b'.", "a\n b: 1b * 2c" => "2b*c isn't a valid CSS value.", "a\n b: 1b % 2c" => "Cannot modulo by a number with units: 2c.", "$a: 2px + #ccc" => "Cannot add a number with units (2px) to a color (#cccccc).", "$a: #ccc + 2px" => "Cannot add a number with units (2px) to a color (#cccccc).", "& a\n :b c" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1], "a\n :b\n c" => "Illegal nesting: Only properties may be nested beneath properties.", "$a: b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.", "@import foo.sass" => "File to import not found or unreadable: foo.sass.", "$a: b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.", "@import foo.sass" => < "Illegal nesting: Nothing may be nested beneath import directives.", "foo\n @import foo.css" => "CSS import directives may only be used at the root of a document.", "@if true\n @import foo" => "Import directives may not be used within control directives or mixins.", "@mixin foo\n @import foo" => "Import directives may not be used within control directives or mixins.", '$foo: "bar" "baz" !' => %Q{Invalid CSS after ""bar" "baz" ": expected expression (e.g. 1px, bold), was "!"}, '$foo: "bar" "baz" $' => %Q{Invalid CSS after ""bar" "baz" ": expected expression (e.g. 1px, bold), was "$"}, "=foo\n :color red\n.bar\n +bang" => "Undefined mixin 'bang'.", "=foo\n :color red\n.bar\n +bang_bop" => "Undefined mixin 'bang_bop'.", "=foo\n :color red\n.bar\n +bang-bop" => "Undefined mixin 'bang-bop'.", ".bar\n =foo\n :color red\n" => ["Mixins may only be defined at the root of a document.", 2], "=foo\n :color red\n.bar\n +foo\n :color red" => "Illegal nesting: Nothing may be nested beneath mixin directives.", " a\n b: c" => ["Indenting at the beginning of the document is illegal.", 1], " \n \n\t\n a\n b: c" => ["Indenting at the beginning of the document is illegal.", 4], "a\n b: c\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 3], "a\n b: c\na\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 4], "a\n\t\tb: c\n\tb: c" => ["Inconsistent indentation: 1 tab was used for indentation, but the rest of the document was indented using 2 tabs.", 3], "a\n b: c\n b: c" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces.", 3], "a\n b: c\n a\n d: e" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces.", 4], "a\n b: c\na\n d: e" => ["The line was indented 2 levels deeper than the previous line.", 4], "a\n b: c\n a\n d: e" => ["The line was indented 3 levels deeper than the previous line.", 4], "a\n \tb: c" => ["Indentation can't use both tabs and spaces.", 2], "=a(" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ""', "=a(b)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "b)"', "=a(,)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ",)"', "=a($)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "$)"', "=a($foo bar)" => 'Invalid CSS after "($foo ": expected ")", was "bar)"', "=foo\n bar: baz\n+foo" => ["Properties are only allowed within rules, directives, or other properties.", 2], "a-\#{$b\n c: d" => ['Invalid CSS after "a-#{$b": expected "}", was ""', 1], "=a($b: 1, $c)" => "Required argument $c must come before any optional arguments.", "=a($b: 1)\n a: $b\ndiv\n +a(1,2)" => "Mixin a takes 1 argument but 2 were passed.", "=a($b: 1)\n a: $b\ndiv\n +a(1,$c: 3)" => "Mixin a doesn't have an argument named $c", "=a($b)\n a: $b\ndiv\n +a" => "Mixin a is missing parameter $b.", "@function foo()\n 1 + 2" => "Functions can only contain variable declarations and control directives.", "@function foo()\n foo: bar" => "Functions can only contain variable declarations and control directives.", "@function foo()\n foo: bar\n @return 3" => ["Functions can only contain variable declarations and control directives.", 2], "@function foo\n @return 1" => ['Invalid CSS after "": expected "(", was ""', 1], "@function foo(\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was ""', 1], "@function foo(b)\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was "b)"', 1], "@function foo(,)\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was ",)"', 1], "@function foo($)\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was "$)"', 1], "@function foo()\n @return" => 'Invalid @return: expected expression.', "@function foo()\n @return 1\n $var: val" => 'Illegal nesting: Nothing may be nested beneath return directives.', "foo\n @function bar()\n @return 1" => ['Functions may only be defined at the root of a document.', 2], "@function foo($a)\n @return 1\na\n b: foo()" => 'Function foo is missing parameter $a.', "@function foo()\n @return 1\na\n b: foo(2)" => 'Wrong number of arguments (1 for 0) for `foo\'', "@return 1" => '@return may only be used within a function.', "@if true\n @return 1" => '@return may only be used within a function.', "@mixin foo\n @return 1\n@include foo" => ['@return may only be used within a function.', 2], "@else\n a\n b: c" => ["@else must come after @if.", 1], "@if false\n@else foo" => "Invalid else directive '@else foo': expected 'if '.", "@if false\n@else if " => "Invalid else directive '@else if': expected 'if '.", "a\n $b: 12\nc\n d: $b" => 'Undefined variable: "$b".', "=foo\n $b: 12\nc\n +foo\n d: $b" => 'Undefined variable: "$b".', "c\n d: $b-foo" => 'Undefined variable: "$b-foo".', "c\n d: $b_foo" => 'Undefined variable: "$b_foo".', '@for $a from "foo" to 1' => '"foo" is not an integer.', '@for $a from 1 to "2"' => '"2" is not an integer.', '@for $a from 1 to "foo"' => '"foo" is not an integer.', '@for $a from 1 to 1.232323' => '1.232 is not an integer.', '@for $a from 1px to 3em' => "Incompatible units: 'em' and 'px'.", '@if' => "Invalid if directive '@if': expected expression.", '@while' => "Invalid while directive '@while': expected expression.", '@debug' => "Invalid debug directive '@debug': expected expression.", %Q{@debug "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath debug directives.", '@warn' => "Invalid warn directive '@warn': expected expression.", %Q{@warn "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath warn directives.", "/* foo\n bar\n baz" => "Inconsistent indentation: previous line was indented by 4 spaces, but this line was indented by 2 spaces.", '+foo(1 + 1: 2)' => 'Invalid CSS after "(1 + 1": expected comma, was ": 2)"', '+foo($var: )' => 'Invalid CSS after "($var: ": expected mixin argument, was ")"', '+foo($var: a, $var: b)' => 'Keyword argument "$var" passed more than once', '+foo($var-var: a, $var_var: b)' => 'Keyword argument "$var-var" passed more than once', '+foo($var_var: a, $var-var: b)' => 'Keyword argument "$var_var" passed more than once', "a\n b: foo(1 + 1: 2)" => 'Invalid CSS after "foo(1 + 1": expected comma, was ": 2)"', "a\n b: foo($var: )" => 'Invalid CSS after "foo($var: ": expected function argument, was ")"', "a\n b: foo($var: a, $var: b)" => 'Keyword argument "$var" passed more than once', "a\n b: foo($var-var: a, $var_var: b)" => 'Keyword argument "$var-var" passed more than once', "a\n b: foo($var_var: a, $var-var: b)" => 'Keyword argument "$var_var" passed more than once', "@if foo\n @extend .bar" => ["Extend directives may only be used within rules.", 2], "$var: true\n@while $var\n @extend .bar\n $var: false" => ["Extend directives may only be used within rules.", 3], "@for $i from 0 to 1\n @extend .bar" => ["Extend directives may only be used within rules.", 2], "@mixin foo\n @extend .bar\n@include foo" => ["Extend directives may only be used within rules.", 2], # Regression tests "a\n b:\n c\n d" => ["Illegal nesting: Only properties may be nested beneath properties.", 3], "& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1], "a\n b: c\n& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 3], } def teardown clean_up_sassc end def test_basic_render renders_correctly "basic", { :style => :compact } end def test_empty_render assert_equal "", render("") end def test_multiple_calls_to_render sass = Sass::Engine.new("a\n b: c") assert_equal sass.render, sass.render end def test_alternate_styles renders_correctly "expanded", { :style => :expanded } renders_correctly "compact", { :style => :compact } renders_correctly "nested", { :style => :nested } renders_correctly "compressed", { :style => :compressed } end def test_compile assert_equal "div { hello: world; }\n", Sass.compile("$who: world\ndiv\n hello: $who", :syntax => :sass, :style => :compact) assert_equal "div { hello: world; }\n", Sass.compile("$who: world; div { hello: $who }", :style => :compact) end def test_compile_file FileUtils.mkdir_p(absolutize("tmp")) open(absolutize("tmp/test_compile_file.sass"), "w") {|f| f.write("$who: world\ndiv\n hello: $who")} open(absolutize("tmp/test_compile_file.scss"), "w") {|f| f.write("$who: world; div { hello: $who }")} assert_equal "div { hello: world; }\n", Sass.compile_file(absolutize("tmp/test_compile_file.sass"), :style => :compact) assert_equal "div { hello: world; }\n", Sass.compile_file(absolutize("tmp/test_compile_file.scss"), :style => :compact) ensure FileUtils.rm_rf(absolutize("tmp")) end def test_compile_file_to_css_file FileUtils.mkdir_p(absolutize("tmp")) open(absolutize("tmp/test_compile_file.sass"), "w") {|f| f.write("$who: world\ndiv\n hello: $who")} open(absolutize("tmp/test_compile_file.scss"), "w") {|f| f.write("$who: world; div { hello: $who }")} Sass.compile_file(absolutize("tmp/test_compile_file.sass"), absolutize("tmp/test_compile_file_sass.css"), :style => :compact) Sass.compile_file(absolutize("tmp/test_compile_file.scss"), absolutize("tmp/test_compile_file_scss.css"), :style => :compact) assert_equal "div { hello: world; }\n", File.read(absolutize("tmp/test_compile_file_sass.css")) assert_equal "div { hello: world; }\n", File.read(absolutize("tmp/test_compile_file_scss.css")) ensure FileUtils.rm_rf(absolutize("tmp")) end def test_flexible_tabulation assert_equal("p {\n a: b; }\n p q {\n c: d; }\n", render("p\n a: b\n q\n c: d\n")) assert_equal("p {\n a: b; }\n p q {\n c: d; }\n", render("p\n\ta: b\n\tq\n\t\tc: d\n")) end EXCEPTION_MAP.each do |key, value| define_method("test_exception (#{key.inspect})") do line = 10 begin silence_warnings {Sass::Engine.new(key, :filename => FAKE_FILE_NAME, :line => line).render} rescue Sass::SyntaxError => err value = [value] unless value.is_a?(Array) assert_equal(value.first.rstrip, err.message, "Line: #{key}") assert_equal(FAKE_FILE_NAME, err.sass_filename) assert_equal((value[1] || key.split("\n").length) + line - 1, err.sass_line, "Line: #{key}") assert_match(/#{Regexp.escape(FAKE_FILE_NAME)}:[0-9]+/, err.backtrace[0], "Line: #{key}") else assert(false, "Exception not raised for\n#{key}") end end end def test_exception_line to_render = < err assert_equal(5, err.sass_line) else assert(false, "Exception not raised for '#{to_render}'!") end end def test_exception_location to_render = < FAKE_FILE_NAME, :line => (__LINE__-7)).render rescue Sass::SyntaxError => err assert_equal(FAKE_FILE_NAME, err.sass_filename) assert_equal((__LINE__-6), err.sass_line) else assert(false, "Exception not raised for '#{to_render}'!") end end def test_imported_exception [1, 2, 3, 4].each do |i| begin Sass::Engine.new("@import bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render rescue Sass::SyntaxError => err assert_equal(2, err.sass_line) assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename) assert_hash_has(err.sass_backtrace.first, :filename => err.sass_filename, :line => err.sass_line) assert_nil(err.sass_backtrace[1][:filename]) assert_equal(1, err.sass_backtrace[1][:line]) assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first) assert_equal("(sass):1", err.backtrace[1]) else assert(false, "Exception not raised for imported template: bork#{i}") end end end def test_double_imported_exception [1, 2, 3, 4].each do |i| begin Sass::Engine.new("@import nested_bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render rescue Sass::SyntaxError => err assert_equal(2, err.sass_line) assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename) assert_hash_has(err.sass_backtrace.first, :filename => err.sass_filename, :line => err.sass_line) assert_match(/(\/|^)nested_bork#{i}\.sass$/, err.sass_backtrace[1][:filename]) assert_equal(2, err.sass_backtrace[1][:line]) assert_nil(err.sass_backtrace[2][:filename]) assert_equal(1, err.sass_backtrace[2][:line]) assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first) assert_match(/(\/|^)nested_bork#{i}\.sass:2$/, err.backtrace[1]) assert_equal("(sass):1", err.backtrace[2]) else assert(false, "Exception not raised for imported template: bork#{i}") end end end def test_mixin_exception render(< err assert_equal(2, err.sass_line) assert_equal(filename_for_test, err.sass_filename) assert_equal("error-mixin", err.sass_mixin) assert_hash_has(err.sass_backtrace.first, :line => err.sass_line, :filename => err.sass_filename, :mixin => err.sass_mixin) assert_hash_has(err.sass_backtrace[1], :line => 5, :filename => filename_for_test, :mixin => "outer-mixin") assert_hash_has(err.sass_backtrace[2], :line => 8, :filename => filename_for_test, :mixin => nil) assert_equal("#{filename_for_test}:2:in `error-mixin'", err.backtrace.first) assert_equal("#{filename_for_test}:5:in `outer-mixin'", err.backtrace[1]) assert_equal("#{filename_for_test}:8", err.backtrace[2]) end def test_mixin_callsite_exception render(< err assert_hash_has(err.sass_backtrace.first, :line => 5, :filename => filename_for_test, :mixin => "one-arg-mixin") assert_hash_has(err.sass_backtrace[1], :line => 5, :filename => filename_for_test, :mixin => "outer-mixin") assert_hash_has(err.sass_backtrace[2], :line => 8, :filename => filename_for_test, :mixin => nil) end def test_mixin_exception_cssize render(< err assert_hash_has(err.sass_backtrace.first, :line => 2, :filename => filename_for_test, :mixin => "parent-ref-mixin") assert_hash_has(err.sass_backtrace[1], :line => 6, :filename => filename_for_test, :mixin => "outer-mixin") assert_hash_has(err.sass_backtrace[2], :line => 8, :filename => filename_for_test, :mixin => nil) end def test_mixin_and_import_exception Sass::Engine.new("@import nested_mixin_bork", :load_paths => [File.dirname(__FILE__) + '/templates/']).render assert(false, "Exception not raised") rescue Sass::SyntaxError => err assert_match(/(\/|^)nested_mixin_bork\.sass$/, err.sass_backtrace.first[:filename]) assert_hash_has(err.sass_backtrace.first, :mixin => "error-mixin", :line => 4) assert_match(/(\/|^)mixin_bork\.sass$/, err.sass_backtrace[1][:filename]) assert_hash_has(err.sass_backtrace[1], :mixin => "outer-mixin", :line => 2) assert_match(/(\/|^)mixin_bork\.sass$/, err.sass_backtrace[2][:filename]) assert_hash_has(err.sass_backtrace[2], :mixin => nil, :line => 5) assert_match(/(\/|^)nested_mixin_bork\.sass$/, err.sass_backtrace[3][:filename]) assert_hash_has(err.sass_backtrace[3], :mixin => nil, :line => 6) assert_hash_has(err.sass_backtrace[4], :filename => nil, :mixin => nil, :line => 1) end def test_basic_mixin_loop_exception render < err assert_equal("An @include loop has been found: foo includes itself", err.message) assert_hash_has(err.sass_backtrace[0], :mixin => "foo", :line => 2) end def test_double_mixin_loop_exception render < err assert_equal(< "bar", :line => 4) assert_hash_has(err.sass_backtrace[1], :mixin => "foo", :line => 2) end def test_deep_mixin_loop_exception render < err assert_equal(< "baz", :line => 8) assert_hash_has(err.sass_backtrace[1], :mixin => "bar", :line => 5) assert_hash_has(err.sass_backtrace[2], :mixin => "foo", :line => 2) end def test_exception_css_with_offset opts = {:full_exception => true, :line => 362} render(("a\n b: c\n" * 10) + "d\n e:\n" + ("f\n g: h\n" * 10), opts) rescue Sass::SyntaxError => e assert_equal(< true} render(< e assert_equal(< true} render(< e assert_equal(< :compact, :load_paths => [File.dirname(__FILE__) + "/templates"] } assert File.exists?(sassc_file) end def test_sass_pathname_import sassc_file = sassc_path("importee") assert !File.exists?(sassc_file) renders_correctly("import", :style => :compact, :load_paths => [Pathname.new(File.dirname(__FILE__) + "/templates")]) assert File.exists?(sassc_file) end def test_nonexistent_extensionless_import assert_raise_message(Sass::SyntaxError, < :compact, :cache => false, :load_paths => [File.dirname(__FILE__) + "/templates"], }) assert !File.exists?(sassc_path("importee")) end def test_import_in_rule assert_equal(< [File.dirname(__FILE__) + '/templates/'])) .foo #foo { background-color: #bbaaff; } .bar { a: b; } .bar #foo { background-color: #bbaaff; } CSS .foo @import partial .bar a: b @import partial SASS end def test_nested_import_with_toplevel_constructs Sass::Engine.new(".foo\n @import importee", :load_paths => [File.dirname(__FILE__) + '/templates/']).render rescue Sass::SyntaxError => err assert_equal(3, err.sass_line) assert_match(/(\/|^)importee\.sass$/, err.sass_filename) assert_hash_has(err.sass_backtrace.first, :filename => err.sass_filename, :line => err.sass_line) assert_nil(err.sass_backtrace[1][:filename]) assert_equal(2, err.sass_backtrace[1][:line]) assert_match(/(\/|^)importee\.sass:3$/, err.backtrace.first) assert_equal("(sass):2", err.backtrace[1]) else assert(false, "Exception not raised for importing mixins nested") end def test_units renders_correctly "units" end def test_default_function assert_equal(< :compact)) assert_equal("#foo #bar,#baz #boom{foo:bar}\n", render("#foo #bar,\n#baz #boom\n :foo bar", :style => :compressed)) assert_equal("#foo #bar,\n#baz #boom {\n foo: bar; }\n", render("#foo #bar,,\n,#baz #boom,\n :foo bar")) assert_equal("#bip #bop {\n foo: bar; }\n", render("#bip #bop,, ,\n :foo bar")) end def test_complex_multiline_selector renders_correctly "multiline" end def test_colon_only begin render("a\n b: c", :property_syntax => :old) rescue Sass::SyntaxError => e assert_equal("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.", e.message) assert_equal(2, e.sass_line) else assert(false, "SyntaxError not raised for :property_syntax => :old") end begin render("a\n :b c", :property_syntax => :new) assert_equal(2, e.sass_line) rescue Sass::SyntaxError => e assert_equal("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.", e.message) else assert(false, "SyntaxError not raised for :property_syntax => :new") end end def test_pseudo_elements assert_equal(< :compact)) assert_equal("@a {\n b: c;\n}\n", render("@a\n :b c", :style => :expanded)) assert_equal("@a{b:c}\n", render("@a\n :b c", :style => :compressed)) assert_equal("@a {\n b: c;\n d: e; }\n", render("@a\n :b c\n :d e")) assert_equal("@a { b: c; d: e; }\n", render("@a\n :b c\n :d e", :style => :compact)) assert_equal("@a {\n b: c;\n d: e;\n}\n", render("@a\n :b c\n :d e", :style => :expanded)) assert_equal("@a{b:c;d:e}\n", render("@a\n :b c\n :d e", :style => :compressed)) assert_equal("@a {\n #b {\n c: d; } }\n", render("@a\n #b\n :c d")) assert_equal("@a { #b { c: d; } }\n", render("@a\n #b\n :c d", :style => :compact)) assert_equal("@a {\n #b {\n c: d;\n }\n}\n", render("@a\n #b\n :c d", :style => :expanded)) assert_equal("@a{#b{c:d}}\n", render("@a\n #b\n :c d", :style => :compressed)) assert_equal("@a {\n #b {\n a: b; }\n #b #c {\n d: e; } }\n", render("@a\n #b\n :a b\n #c\n :d e")) assert_equal("@a { #b { a: b; }\n #b #c { d: e; } }\n", render("@a\n #b\n :a b\n #c\n :d e", :style => :compact)) assert_equal("@a {\n #b {\n a: b;\n }\n #b #c {\n d: e;\n }\n}\n", render("@a\n #b\n :a b\n #c\n :d e", :style => :expanded)) assert_equal("@a{#b{a:b}#b #c{d:e}}\n", render("@a\n #b\n :a b\n #c\n :d e", :style => :compressed)) assert_equal("@a {\n #foo,\n #bar {\n b: c; } }\n", render("@a\n #foo, \n #bar\n :b c")) assert_equal("@a { #foo, #bar { b: c; } }\n", render("@a\n #foo, \n #bar\n :b c", :style => :compact)) assert_equal("@a {\n #foo,\n #bar {\n b: c;\n }\n}\n", render("@a\n #foo, \n #bar\n :b c", :style => :expanded)) assert_equal("@a{#foo,#bar{b:c}}\n", render("@a\n #foo, \n #bar\n :b c", :style => :compressed)) to_render = < :compact)) assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed)) end def test_property_hacks assert_equal(< true, :style => :compact)) /* line 2, test_line_annotations_inline.sass */ foo bar { foo: bar; } /* line 5, test_line_annotations_inline.sass */ foo baz { blip: blop; } /* line 9, test_line_annotations_inline.sass */ floodle { flop: blop; } /* line 18, test_line_annotations_inline.sass */ bup { mix: on; } /* line 15, test_line_annotations_inline.sass */ bup mixin { moop: mup; } /* line 22, test_line_annotations_inline.sass */ bip hop, skip hop { a: b; } CSS foo bar foo: bar baz blip: blop floodle flop: blop =mxn mix: on mixin moop: mup bup +mxn bip, skip hop a: b SASS end def test_line_annotations_with_filename renders_correctly "line_numbers", :line_comments => true, :load_paths => [File.dirname(__FILE__) + "/templates"] end def test_debug_info esc_file_name = Sass::SCSS::RX.escape_ident(Sass::Util.scope("test_debug_info_inline.sass")) assert_equal(< true, :style => :compact)) @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000032}} foo bar { foo: bar; } @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000035}} foo baz { blip: blop; } @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000039}} floodle { flop: blop; } @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000318}} bup { mix: on; } @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000315}} bup mixin { moop: mup; } @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000322}} bip hop, skip hop { a: b; } CSS foo bar foo: bar baz blip: blop floodle flop: blop =mxn mix: on mixin moop: mup bup +mxn bip, skip hop a: b SASS end def test_debug_info_without_filename assert_equal(< true).render) @media -sass-debug-info{filename{font-family:}line{font-family:\\000031}} foo { a: b; } CSS foo a: b SASS end def test_debug_info_with_compressed assert_equal(< true, :style => :compressed)) foo{a:b} CSS foo a: b SASS end def test_debug_info_with_line_annotations esc_file_name = Sass::SCSS::RX.escape_ident(Sass::Util.scope("test_debug_info_with_line_annotations_inline.sass")) assert_equal(< true, :line_comments => true)) @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000031}} foo { a: b; } CSS foo a: b SASS end def test_empty_first_line assert_equal("#a {\n b: c; }\n", render("#a\n\n b: c")) end def test_escaped_rule assert_equal(":focus {\n a: b; }\n", render("\\:focus\n a: b")) assert_equal("a {\n b: c; }\n a :focus {\n d: e; }\n", render("\\a\n b: c\n \\:focus\n d: e")) end def test_cr_newline assert_equal("foo {\n a: b;\n c: d;\n e: f; }\n", render("foo\r a: b\r\n c: d\n\r e: f")) end def test_property_with_content_and_nested_props assert_equal(< :expanded } end def test_directive_style_mixins assert_equal < :compressed) foo{color:blue;/* foo * bar */} CSS foo color: blue /*! foo * bar */ SASS end def test_loud_comment_in_silent_comment assert_equal < :compressed) foo{color:blue;/* foo */ /* bar */ /* */ /* bip */ /* baz */} CSS foo color: blue //! foo //! bar //! bip baz SASS end def test_loud_comment_is_evaluated assert_equal < :new)) :focus { outline: 0; } CSS :focus outline: 0 SASS end def test_pseudo_class_with_new_properties assert_equal(< :new)) p :focus { outline: 0; } CSS p :focus outline: 0 SASS end def test_nil_option assert_equal(< nil)) foo { a: b; } CSS foo a: b SASS end def test_interpolation_in_raw_functions assert_equal(< true) CSS @warn "this is a warning" SASS end end def test_warn_with_imports expected_warning = < :compact, :load_paths => [File.dirname(__FILE__) + "/templates"] end end def test_media_bubbling assert_equal < :compact) .foo { a: b; } @media bar { .foo { c: d; } } .foo .baz { e: f; } @media bip { .foo .baz { g: h; } } .other { i: j; } CSS .foo a: b @media bar c: d .baz e: f @media bip g: h .other i: j SASS assert_equal < :expanded) .foo { a: b; } @media bar { .foo { c: d; } } .foo .baz { e: f; } @media bip { .foo .baz { g: h; } } .other { i: j; } CSS .foo a: b @media bar c: d .baz e: f @media bip g: h .other i: j SASS end def test_double_media_bubbling assert_equal < :compressed)) .box{border-style:solid} RESULT .box :border /*:color black :style solid SOURCE end def test_compressed_comment_beneath_directive assert_equal(< :compressed)) @foo{a:b} RESULT @foo a: b /*b: c SOURCE end def test_comment_with_crazy_indentation assert_equal(< e assert_equal(3, e.sass_line) assert_equal('Invalid UTF-8 character "\xFE"', e.message) end def test_ascii_incompatible_encoding_error template = "foo\nbar\nb_z".encode("utf-16le") template[9] = "\xFE".force_encoding("utf-16le") render(template) assert(false, "Expected exception") rescue Sass::SyntaxError => e assert_equal(3, e.sass_line) assert_equal('Invalid UTF-16LE character "\xFE"', e.message) end def test_same_charset_as_encoding assert_renders_encoded(< original_filename, :load_paths => [importer], :syntax => :scss) engine.render assert_equal original_filename, engine.options[:original_filename] assert_equal original_filename, importer.engine("imported").options[:original_filename] end private def assert_hash_has(hash, expected) expected.each {|k, v| assert_equal(v, hash[k])} end def assert_renders_encoded(css, sass) result = render(sass) assert_equal css.encoding, result.encoding assert_equal css, result end def render(sass, options = {}) munge_filename options Sass::Engine.new(sass, options).render end def renders_correctly(name, options={}) sass_file = load_file(name, "sass") css_file = load_file(name, "css") options[:filename] ||= filename(name, "sass") options[:syntax] ||= :sass options[:css_filename] ||= filename(name, "css") css_result = Sass::Engine.new(sass_file, options).render assert_equal css_file, css_result end def load_file(name, type = "sass") @result = '' File.new(filename(name, type)).each_line { |l| @result += l } @result end def filename(name, type) File.dirname(__FILE__) + "/#{type == 'sass' ? 'templates' : 'results'}/#{name}.#{type}" end def sassc_path(template) sassc_path = File.join(File.dirname(__FILE__) + "/templates/#{template}.sass") engine = Sass::Engine.new("", :filename => sassc_path, :importer => Sass::Importers::Filesystem.new(".")) key = engine.send(:sassc_key) File.join(engine.options[:cache_location], key) end end ././@LongLink0000644000000000000000000000014612255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/util/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/util0000775000175000017500000000000012206724733033656 5ustar jamespagejamespage././@LongLink0000644000000000000000000000017012255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/util/subset_map_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/util0000775000175000017500000000521712206724733033670 0ustar jamespagejamespage#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../test_helper' class SubsetMapTest < Test::Unit::TestCase def setup @ssm = Sass::Util::SubsetMap.new @ssm[Set[1, 2]] = "Foo" @ssm[Set["fizz", "fazz"]] = "Bar" @ssm[Set[:foo, :bar]] = "Baz" @ssm[Set[:foo, :bar, :baz]] = "Bang" @ssm[Set[:bip, :bop, :blip]] = "Qux" @ssm[Set[:bip, :bop]] = "Thram" end def test_equal_keys assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2]) assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz"]) end def test_subset_keys assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2, "fuzz"]) assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz", 3]) end def test_superset_keys assert_equal [], @ssm.get(Set[1]) assert_equal [], @ssm.get(Set[2]) assert_equal [], @ssm.get(Set["fizz"]) assert_equal [], @ssm.get(Set["fazz"]) end def test_disjoint_keys assert_equal [], @ssm.get(Set[3, 4]) assert_equal [], @ssm.get(Set["fuzz", "frizz"]) assert_equal [], @ssm.get(Set["gran", 15]) end def test_semi_disjoint_keys assert_equal [], @ssm.get(Set[2, 3]) assert_equal [], @ssm.get(Set["fizz", "fuzz"]) assert_equal [], @ssm.get(Set[1, "fazz"]) end def test_empty_key_set assert_raise(ArgumentError) {@ssm[Set[]] = "Fail"} end def test_empty_key_get assert_equal [], @ssm.get(Set[]) end def test_multiple_subsets assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, "fizz", "fazz"]) assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, 3, "fizz", "fazz", "fuzz"]) assert_equal [["Baz", Set[:foo, :bar]]], @ssm.get(Set[:foo, :bar]) assert_equal [["Baz", Set[:foo, :bar]], ["Bang", Set[:foo, :bar, :baz]]], @ssm.get(Set[:foo, :bar, :baz]) end def test_bracket_bracket assert_equal ["Foo"], @ssm[Set[1, 2, "fuzz"]] assert_equal ["Baz", "Bang"], @ssm[Set[:foo, :bar, :baz]] end def test_order_preserved @ssm[Set[10, 11, 12]] = 1 @ssm[Set[10, 11]] = 2 @ssm[Set[11]] = 3 @ssm[Set[11, 12]] = 4 @ssm[Set[9, 10, 11, 12, 13]] = 5 @ssm[Set[10, 13]] = 6 assert_equal( [[1, Set[10, 11, 12]], [2, Set[10, 11]], [3, Set[11]], [4, Set[11, 12]], [5, Set[9, 10, 11, 12, 13]], [6, Set[10, 13]]], @ssm.get(Set[9, 10, 11, 12, 13])) end def test_multiple_equal_values @ssm[Set[11, 12]] = 1 @ssm[Set[12, 13]] = 2 @ssm[Set[13, 14]] = 1 @ssm[Set[14, 15]] = 1 assert_equal( [[1, Set[11, 12]], [2, Set[12, 13]], [1, Set[13, 14]], [1, Set[14, 15]]], @ssm.get(Set[11, 12, 13, 14, 15])) end end ././@LongLink0000644000000000000000000000015712255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/script_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/scri0000775000175000017500000004505212206724733033654 0ustar jamespagejamespage#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../test_helper' require 'sass/engine' module Sass::Script::Functions::UserFunctions def assert_options(val) val.options[:foo] Sass::Script::String.new("Options defined!") end end class SassScriptTest < Test::Unit::TestCase include Sass::Script def test_color_checks_input assert_raise_message(ArgumentError, "Blue value must be between 0 and 255") {Color.new([1, 2, -1])} assert_raise_message(ArgumentError, "Red value must be between 0 and 255") {Color.new([256, 2, 3])} end def test_color_checks_rgba_input assert_raise_message(ArgumentError, "Alpha channel must be between 0 and 1") {Color.new([1, 2, 3, 1.1])} assert_raise_message(ArgumentError, "Alpha channel must be between 0 and 1") {Color.new([1, 2, 3, -0.1])} end def test_string_escapes assert_equal "'", resolve("\"'\"") assert_equal '"', resolve("\"\\\"\"") assert_equal "\\\\", resolve("\"\\\\\"") assert_equal "\\02fa", resolve("\"\\02fa\"") assert_equal "'", resolve("'\\''") assert_equal '"', resolve("'\"'") assert_equal "\\\\", resolve("'\\\\'") assert_equal "\\02fa", resolve("'\\02fa'") end def test_string_interpolation assert_equal "foo2bar", resolve('\'foo#{1 + 1}bar\'') assert_equal "foo2bar", resolve('"foo#{1 + 1}bar"') assert_equal "foo1bar5baz4bang", resolve('\'foo#{1 + "bar#{2 + 3}baz" + 4}bang\'') end def test_color_names assert_equal "white", resolve("white") assert_equal "white", resolve("#ffffff") assert_equal "#fffffe", resolve("white - #000001") end def test_rgba_color_literals assert_equal Sass::Script::Color.new([1, 2, 3, 0.75]), eval("rgba(1, 2, 3, 0.75)") assert_equal "rgba(1, 2, 3, 0.75)", resolve("rgba(1, 2, 3, 0.75)") assert_equal Sass::Script::Color.new([1, 2, 3, 0]), eval("rgba(1, 2, 3, 0)") assert_equal "rgba(1, 2, 3, 0)", resolve("rgba(1, 2, 3, 0)") assert_equal Sass::Script::Color.new([1, 2, 3]), eval("rgba(1, 2, 3, 1)") assert_equal Sass::Script::Color.new([1, 2, 3, 1]), eval("rgba(1, 2, 3, 1)") assert_equal "#010203", resolve("rgba(1, 2, 3, 1)") assert_equal "white", resolve("rgba(255, 255, 255, 1)") end def test_rgba_color_math assert_equal "rgba(50, 50, 100, 0.35)", resolve("rgba(1, 1, 2, 0.35) * rgba(50, 50, 50, 0.35)") assert_equal "rgba(52, 52, 52, 0.25)", resolve("rgba(2, 2, 2, 0.25) + rgba(50, 50, 50, 0.25)") assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: rgba(1, 2, 3, 0.15) + rgba(50, 50, 50, 0.75)") do resolve("rgba(1, 2, 3, 0.15) + rgba(50, 50, 50, 0.75)") end assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: #123456 * rgba(50, 50, 50, 0.75)") do resolve("#123456 * rgba(50, 50, 50, 0.75)") end assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: rgba(50, 50, 50, 0.75) / #123456") do resolve("rgba(50, 50, 50, 0.75) / #123456") end end def test_rgba_number_math assert_equal "rgba(49, 49, 49, 0.75)", resolve("rgba(50, 50, 50, 0.75) - 1") assert_equal "rgba(100, 100, 100, 0.75)", resolve("rgba(50, 50, 50, 0.75) * 2") end def test_rgba_rounding assert_equal "rgba(10, 1, 0, 0.123)", resolve("rgba(10.0, 1.23456789, 0.0, 0.1234567)") end def test_compressed_colors assert_equal "#123456", resolve("#123456", :style => :compressed) assert_equal "rgba(1,2,3,0.5)", resolve("rgba(1, 2, 3, 0.5)", :style => :compressed) assert_equal "#123", resolve("#112233", :style => :compressed) assert_equal "#000", resolve("black", :style => :compressed) assert_equal "red", resolve("#f00", :style => :compressed) assert_equal "blue", resolve("#00f", :style => :compressed) assert_equal "navy", resolve("#000080", :style => :compressed) assert_equal "navy #fff", resolve("#000080 white", :style => :compressed) assert_equal "This color is #fff", resolve('"This color is #{ white }"', :style => :compressed) end def test_compressed_comma # assert_equal "foo,bar,baz", resolve("foo, bar, baz", :style => :compressed) # assert_equal "foo,#baf,baz", resolve("foo, #baf, baz", :style => :compressed) assert_equal "foo,#baf,red", resolve("foo, #baf, #f00", :style => :compressed) end def test_implicit_strings assert_equal Sass::Script::String.new("foo"), eval("foo") assert_equal Sass::Script::String.new("foo/bar"), eval("foo/bar") end def test_basic_interpolation assert_equal "foo3bar", resolve("foo\#{1 + 2}bar") assert_equal "foo3 bar", resolve("foo\#{1 + 2} bar") assert_equal "foo 3bar", resolve("foo \#{1 + 2}bar") assert_equal "foo 3 bar", resolve("foo \#{1 + 2} bar") assert_equal "foo 35 bar", resolve("foo \#{1 + 2}\#{2 + 3} bar") assert_equal "foo 3 5 bar", resolve("foo \#{1 + 2} \#{2 + 3} bar") assert_equal "3bar", resolve("\#{1 + 2}bar") assert_equal "foo3", resolve("foo\#{1 + 2}") assert_equal "3", resolve("\#{1 + 2}") end def test_interpolation_in_function assert_equal 'flabnabbit(1foo)', resolve('flabnabbit(#{1 + "foo"})') assert_equal 'flabnabbit(foo 1foobaz)', resolve('flabnabbit(foo #{1 + "foo"}baz)') assert_equal('flabnabbit(foo 1foo2bar baz)', resolve('flabnabbit(foo #{1 + "foo"}#{2 + "bar"} baz)')) end def test_interpolation_near_operators assert_equal '3 , 7', resolve('#{1 + 2} , #{3 + 4}') assert_equal '3, 7', resolve('#{1 + 2}, #{3 + 4}') assert_equal '3 ,7', resolve('#{1 + 2} ,#{3 + 4}') assert_equal '3,7', resolve('#{1 + 2},#{3 + 4}') assert_equal '3 / 7', resolve('3 / #{3 + 4}') assert_equal '3 /7', resolve('3 /#{3 + 4}') assert_equal '3/ 7', resolve('3/ #{3 + 4}') assert_equal '3/7', resolve('3/#{3 + 4}') assert_equal '3 * 7', resolve('#{1 + 2} * 7') assert_equal '3* 7', resolve('#{1 + 2}* 7') assert_equal '3 *7', resolve('#{1 + 2} *7') assert_equal '3*7', resolve('#{1 + 2}*7') assert_equal '-3', resolve('-#{1 + 2}') assert_equal '- 3', resolve('- #{1 + 2}') assert_equal '5 + 3 * 7', resolve('5 + #{1 + 2} * #{3 + 4}') assert_equal '5 +3 * 7', resolve('5 +#{1 + 2} * #{3 + 4}') assert_equal '5+3 * 7', resolve('5+#{1 + 2} * #{3 + 4}') assert_equal '3 * 7 + 5', resolve('#{1 + 2} * #{3 + 4} + 5') assert_equal '3 * 7+ 5', resolve('#{1 + 2} * #{3 + 4}+ 5') assert_equal '3 * 7+5', resolve('#{1 + 2} * #{3 + 4}+5') assert_equal '5/3 + 7', resolve('5 / (#{1 + 2} + #{3 + 4})') assert_equal '5/3 + 7', resolve('5 /(#{1 + 2} + #{3 + 4})') assert_equal '5/3 + 7', resolve('5 /( #{1 + 2} + #{3 + 4} )') assert_equal '3 + 7/5', resolve('(#{1 + 2} + #{3 + 4}) / 5') assert_equal '3 + 7/5', resolve('(#{1 + 2} + #{3 + 4})/ 5') assert_equal '3 + 7/5', resolve('( #{1 + 2} + #{3 + 4} )/ 5') assert_equal '3 + 5', resolve('#{1 + 2} + 2 + 3') assert_equal '3 +5', resolve('#{1 + 2} +2 + 3') end def test_string_interpolation assert_equal "foo bar, baz bang", resolve('"foo #{"bar"}, #{"baz"} bang"') assert_equal "foo bar baz bang", resolve('"foo #{"#{"ba" + "r"} baz"} bang"') assert_equal 'foo #{bar baz} bang', resolve('"foo \#{#{"ba" + "r"} baz} bang"') assert_equal 'foo #{baz bang', resolve('"foo #{"\#{" + "baz"} bang"') end def test_rule_interpolation assert_equal(< 2) assert_equal "public_instance_methods()", resolve("public_instance_methods()") end def test_adding_functions_directly_to_functions_module assert !Functions.callable?('nonexistant') Functions.class_eval { def nonexistant; end } assert Functions.callable?('nonexistant') Functions.send :remove_method, :nonexistant end def test_default_functions assert_equal "url(12)", resolve("url(12)") assert_equal 'blam("foo")', resolve('blam("foo")') end def test_function_results_have_options assert_equal "Options defined!", resolve("assert_options(abs(1))") assert_equal "Options defined!", resolve("assert_options(round(1.2))") end def test_funcall_requires_no_whitespace_before_lparen assert_equal "no-repeat 15px", resolve("no-repeat (7px + 8px)") assert_equal "no-repeat(15px)", resolve("no-repeat(7px + 8px)") end def test_dynamic_url assert_equal "url(foo-bar)", resolve("url($foo)", {}, env('foo' => Sass::Script::String.new("foo-bar"))) assert_equal "url(foo-bar baz)", resolve("url($foo $bar)", {}, env('foo' => Sass::Script::String.new("foo-bar"), 'bar' => Sass::Script::String.new("baz"))) assert_equal "url(foo baz)", resolve("url(foo $bar)", {}, env('bar' => Sass::Script::String.new("baz"))) assert_equal "url(foo bar)", resolve("url(foo bar)") end def test_url_with_interpolation assert_equal "url(http://sass-lang.com/images/foo-bar)", resolve("url(http://sass-lang.com/images/\#{foo-bar})") assert_equal 'url("http://sass-lang.com/images/foo-bar")', resolve("url('http://sass-lang.com/images/\#{foo-bar}')") assert_equal 'url("http://sass-lang.com/images/foo-bar")', resolve('url("http://sass-lang.com/images/#{foo-bar}")') assert_unquoted "url(http://sass-lang.com/images/\#{foo-bar})" end def test_hyphenated_variables assert_equal("a-b", resolve("$a-b", {}, env("a-b" => Sass::Script::String.new("a-b")))) end def test_ruby_equality assert_equal eval('"foo"'), eval('"foo"') assert_equal eval('1'), eval('1.0') assert_equal eval('1 2 3.0'), eval('1 2 3') assert_equal eval('1, 2, 3.0'), eval('1, 2, 3') assert_equal eval('(1 2), (3, 4), (5 6)'), eval('(1 2), (3, 4), (5 6)') assert_not_equal eval('1, 2, 3'), eval('1 2 3') assert_not_equal eval('1'), eval('"1"') end def test_booleans assert_equal "true", resolve("true") assert_equal "false", resolve("false") end def test_boolean_ops assert_equal "true", resolve("true and true") assert_equal "true", resolve("false or true") assert_equal "true", resolve("true or false") assert_equal "true", resolve("true or true") assert_equal "false", resolve("false or false") assert_equal "false", resolve("false and true") assert_equal "false", resolve("true and false") assert_equal "false", resolve("false and false") assert_equal "true", resolve("not false") assert_equal "false", resolve("not true") assert_equal "true", resolve("not not true") assert_equal "1", resolve("false or 1") assert_equal "false", resolve("false and 1") assert_equal "2", resolve("2 or 3") assert_equal "3", resolve("2 and 3") end def test_arithmetic_ops assert_equal "2", resolve("1 + 1") assert_equal "0", resolve("1 - 1") assert_equal "8", resolve("2 * 4") assert_equal "0.5", resolve("(2 / 4)") assert_equal "2", resolve("(4 / 2)") assert_equal "-1", resolve("-1") end def test_string_ops assert_equal '"foo" "bar"', resolve('"foo" "bar"') assert_equal "true 1", resolve('true 1') assert_equal '"foo", "bar"', resolve("'foo' , 'bar'") assert_equal "true, 1", resolve('true , 1') assert_equal "foobar", resolve('"foo" + "bar"') assert_equal "true1", resolve('true + 1') assert_equal '"foo"-"bar"', resolve("'foo' - 'bar'") assert_equal "true-1", resolve('true - 1') assert_equal '"foo"/"bar"', resolve('"foo" / "bar"') assert_equal "true/1", resolve('true / 1') assert_equal '-"bar"', resolve("- 'bar'") assert_equal "-true", resolve('- true') assert_equal '/"bar"', resolve('/ "bar"') assert_equal "/true", resolve('/ true') end def test_relational_ops assert_equal "false", resolve("1 > 2") assert_equal "false", resolve("2 > 2") assert_equal "true", resolve("3 > 2") assert_equal "false", resolve("1 >= 2") assert_equal "true", resolve("2 >= 2") assert_equal "true", resolve("3 >= 2") assert_equal "true", resolve("1 < 2") assert_equal "false", resolve("2 < 2") assert_equal "false", resolve("3 < 2") assert_equal "true", resolve("1 <= 2") assert_equal "true", resolve("2 <= 2") assert_equal "false", resolve("3 <= 2") end def test_equals assert_equal("true", resolve('"foo" == $foo', {}, env("foo" => Sass::Script::String.new("foo")))) assert_equal "true", resolve("1 == 1.0") assert_equal "true", resolve("false != true") assert_equal "false", resolve("1em == 1px") assert_equal "false", resolve("12 != 12") assert_equal "true", resolve("(foo bar baz) == (foo bar baz)") assert_equal "true", resolve("(foo, bar, baz) == (foo, bar, baz)") assert_equal "true", resolve('((1 2), (3, 4), (5 6)) == ((1 2), (3, 4), (5 6))') assert_equal "true", resolve('((1 2), (3 4)) == (1 2, 3 4)') assert_equal "false", resolve('((1 2) 3) == (1 2 3)') assert_equal "false", resolve('(1 (2 3)) == (1 2 3)') assert_equal "false", resolve('((1, 2) (3, 4)) == (1, 2 3, 4)') assert_equal "false", resolve('(1 2 3) == (1, 2, 3)') end def test_operation_precedence assert_equal "false true", resolve("true and false false or true") assert_equal "true", resolve("false and true or true and true") assert_equal "true", resolve("1 == 2 or 3 == 3") assert_equal "true", resolve("1 < 2 == 3 >= 3") assert_equal "true", resolve("1 + 3 > 4 - 2") assert_equal "11", resolve("1 + 2 * 3 + 4") end def test_functions assert_equal "#80ff80", resolve("hsl(120, 100%, 75%)") assert_equal "#81ff81", resolve("hsl(120, 100%, 75%) + #010001") end def test_operator_unit_conversion assert_equal "1.1cm", resolve("1cm + 1mm") assert_equal "true", resolve("2mm < 1cm") assert_equal "true", resolve("10mm == 1cm") assert_equal "true", resolve("1 == 1cm") assert_equal "true", resolve("1.1cm == 11mm") end def test_operations_have_options assert_equal "Options defined!", resolve("assert_options(1 + 1)") assert_equal "Options defined!", resolve("assert_options('bar' + 'baz')") end def test_slash_compiles_literally_when_left_alone assert_equal "1px/2px", resolve("1px/2px") assert_equal "1px/2px/3px/4px", resolve("1px/2px/3px/4px") assert_equal "1px/2px redpx bluepx", resolve("1px/2px redpx bluepx") assert_equal "foo 1px/2px/3px bar", resolve("foo 1px/2px/3px bar") end def test_slash_divides_with_parens assert_equal "0.5", resolve("(1px/2px)") assert_equal "0.5", resolve("(1px)/2px") assert_equal "0.5", resolve("1px/(2px)") end def test_slash_divides_with_other_arithmetic assert_equal "0.5px", resolve("1px*1px/2px") assert_equal "0.5px", resolve("1px/2px*1px") assert_equal "0.5", resolve("0+1px/2px") assert_equal "0.5", resolve("1px/2px+0") end def test_slash_divides_with_variable assert_equal "0.5", resolve("$var/2px", {}, env("var" => eval("1px"))) assert_equal "0.5", resolve("1px/$var", {}, env("var" => eval("2px"))) assert_equal "0.5", resolve("$var", {}, env("var" => eval("1px/2px"))) end def test_colors_with_wrong_number_of_digits assert_raise_message(Sass::SyntaxError, "Colors must have either three or six digits: '#0'") {eval("#0")} assert_raise_message(Sass::SyntaxError, "Colors must have either three or six digits: '#12'") {eval("#12")} assert_raise_message(Sass::SyntaxError, "Colors must have either three or six digits: '#abcd'") {eval("#abcd")} assert_raise_message(Sass::SyntaxError, "Colors must have either three or six digits: '#abcdE'") {eval("#abcdE")} assert_raise_message(Sass::SyntaxError, "Colors must have either three or six digits: '#abcdEFA'") {eval("#abcdEFA")} end def test_case_insensitive_color_names assert_equal "blue", resolve("BLUE") assert_equal "red", resolve("rEd") assert_equal "#7f4000", resolve("mix(GrEeN, ReD)") end def test_empty_list assert_equal "1 2 3", resolve("1 2 () 3") assert_equal "1 2 3", resolve("1 2 3 ()") assert_equal "1 2 3", resolve("() 1 2 3") assert_raise_message(Sass::SyntaxError, "() isn't a valid CSS value.") {resolve("()")} assert_raise_message(Sass::SyntaxError, "() isn't a valid CSS value.") {resolve("nth(append((), ()), 1)")} end # Regression Tests def test_funcall_has_higher_precedence_than_color_name assert_equal "teal(12)", resolve("teal(12)") assert_equal "tealbang(12)", resolve("tealbang(12)") assert_equal "teal-bang(12)", resolve("teal-bang(12)") assert_equal "teal\\+bang(12)", resolve("teal\\+bang(12)") end def test_interpolation_after_hash assert_equal "#2", resolve('"##{1 + 1}"') end def test_misplaced_comma_in_funcall assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "foo(bar, ": expected function argument, was ")"') {eval('foo(bar, )')} end def test_color_prefixed_identifier assert_equal "tealbang", resolve("tealbang") assert_equal "teal-bang", resolve("teal-bang") end def test_op_prefixed_identifier assert_equal "notbang", resolve("notbang") assert_equal "not-bang", resolve("not-bang") assert_equal "or-bang", resolve("or-bang") assert_equal "and-bang", resolve("and-bang") end private def resolve(str, opts = {}, environment = env) munge_filename opts val = eval(str, opts, environment) val.is_a?(Sass::Script::String) ? val.value : val.to_s end def assert_unquoted(str, opts = {}, environment = env) munge_filename opts val = eval(str, opts, environment) assert_kind_of Sass::Script::String, val assert_equal :identifier, val.type end def assert_quoted(str, opts = {}, environment = env) munge_filename opts val = eval(str, opts, environment) assert_kind_of Sass::Script::String, val assert_equal :string, val.type end def eval(str, opts = {}, environment = env) munge_filename opts environment.options = opts Sass::Script.parse(str, opts.delete(:line) || 1, opts.delete(:offset) || 0, opts).perform(environment) end def render(sass, options = {}) munge_filename options Sass::Engine.new(sass, options).render end def env(hash = {}) env = Sass::Environment.new hash.each {|k, v| env.set_var(k, v)} env end def test_number_printing assert_equal "1", eval("1") assert_equal "1", eval("1.0") assert_equal "1.121", eval("1.1214") assert_equal "1.122", eval("1.1215") assert_equal "Infinity", eval("1.0/0.0") assert_equal "-Infinity", eval("-1.0/0.0") assert_equal "NaN", eval("0.0/0.0") end end ././@LongLink0000644000000000000000000000017212255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/script_conversion_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/scri0000775000175000017500000002064512206724733033655 0ustar jamespagejamespage#!/usr/bin/env ruby # -*- coding: utf-8 -*- require File.dirname(__FILE__) + '/../test_helper' require 'sass/engine' class SassScriptConversionTest < Test::Unit::TestCase def test_bool assert_renders "true" assert_renders "false" end def test_color assert_renders "#abcdef" assert_renders "blue" assert_renders "rgba(0, 1, 2, 0.2)" assert_equal "#aabbcc", render("#abc") assert_equal "blue", render("#0000ff") end def test_number assert_renders "10" assert_renders "10.35" assert_renders "12px" assert_renders "12.45px" assert_equal "12.346", render("12.345678901") end def test_string assert_renders '"foo"' assert_renders '"bar baz"' assert_equal '"baz bang"', render("'baz bang'") end def test_string_quotes assert_equal "'quote\"quote'", render('"quote\\"quote"') assert_equal '"quote\'quote"', render("'quote\\'quote'") assert_renders '"quote\'quote\\"quote"' assert_equal '"quote\'quote\\"quote"', render("'quote\\'quote\"quote'") end def test_string_escapes assert_renders '"foo\\\\bar"' end def test_funcall assert_renders "foo(true, blue)" assert_renders "hsla(20deg, 30%, 50%, 0.3)" assert_renders "blam()" assert_renders "-\xC3\xBFoo(12px)" assert_renders "-foo(12px)" end def test_funcall_with_keyword_args assert_renders "foo(arg1, arg2, $karg1: val, $karg2: val2)" assert_renders "foo($karg1: val, $karg2: val2)" end def test_url assert_renders "url(foo.gif)" assert_renders "url($var)" assert_renders "url(\#{$var}/flip.gif)" end def test_variable assert_renders "$foo-bar" assert_renders "$flaznicate" end def self.test_precedence(outer, inner) op_outer = Sass::Script::Lexer::OPERATORS_REVERSE[outer] op_inner = Sass::Script::Lexer::OPERATORS_REVERSE[inner] class_eval < { template_loc => tempfile_loc, template_loc(nil,'more_') => tempfile_loc(nil,'more_') } check_for_updates! ['more1', 'more_import'].each { |name| assert_renders_correctly(name, :prefix => 'more_') } end def test_two_template_directories_with_line_annotations set_plugin_opts :line_comments => true, :style => :nested, :template_location => { template_loc => tempfile_loc, template_loc(nil,'more_') => tempfile_loc(nil,'more_') } check_for_updates! assert_renders_correctly('more1_with_line_comments', 'more1', :prefix => 'more_') end def test_doesnt_render_partials assert !File.exists?(tempfile_loc('_partial')) end def test_template_location_array assert_equal [[template_loc, tempfile_loc]], Sass::Plugin.template_location_array end def test_add_template_location Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_")) assert_equal( [[template_loc, tempfile_loc], [template_loc(nil, "more_"), tempfile_loc(nil, "more_")]], Sass::Plugin.template_location_array) touch 'more1', 'more_' touch 'basic' assert_needs_update "more1", "more_" assert_needs_update "basic" check_for_updates! assert_doesnt_need_update "more1", "more_" assert_doesnt_need_update "basic" end def test_remove_template_location Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_")) Sass::Plugin.remove_template_location(template_loc, tempfile_loc) assert_equal( [[template_loc(nil, "more_"), tempfile_loc(nil, "more_")]], Sass::Plugin.template_location_array) touch 'more1', 'more_' touch 'basic' assert_needs_update "more1", "more_" assert_needs_update "basic" check_for_updates! assert_doesnt_need_update "more1", "more_" assert_needs_update "basic" end # Callbacks def test_updating_stylesheets_callback # Should run even when there's nothing to update assert_callback :updating_stylesheets, [] end def test_updating_stylesheets_callback_with_individual_files files = [[template_loc("basic"), tempfile_loc("basic")]] assert_callback(:updating_stylesheets, files) {Sass::Util.silence_sass_warnings{Sass::Plugin.update_stylesheets(files)}} end def test_updating_stylesheets_callback_with_never_update Sass::Plugin.options[:never_update] = true assert_no_callback :updating_stylesheets end def test_updating_stylesheet_callback_for_updated_template Sass::Plugin.options[:always_update] = false touch 'basic' assert_no_callback :updating_stylesheet, template_loc("complex"), tempfile_loc("complex") do assert_callbacks( [:updating_stylesheet, template_loc("basic"), tempfile_loc("basic")], [:updating_stylesheet, template_loc("import"), tempfile_loc("import")]) end end def test_updating_stylesheet_callback_for_fresh_template Sass::Plugin.options[:always_update] = false assert_no_callback :updating_stylesheet end def test_updating_stylesheet_callback_for_error_template Sass::Plugin.options[:always_update] = false touch 'bork1' assert_no_callback :updating_stylesheet end def test_not_updating_stylesheet_callback_for_fresh_template Sass::Plugin.options[:always_update] = false assert_callback :not_updating_stylesheet, template_loc("basic"), tempfile_loc("basic") end def test_not_updating_stylesheet_callback_for_updated_template Sass::Plugin.options[:always_update] = false assert_callback :not_updating_stylesheet, template_loc("complex"), tempfile_loc("complex") do assert_no_callbacks( [:updating_stylesheet, template_loc("basic"), tempfile_loc("basic")], [:updating_stylesheet, template_loc("import"), tempfile_loc("import")]) end end def test_not_updating_stylesheet_callback_with_never_update Sass::Plugin.options[:never_update] = true assert_no_callback :not_updating_stylesheet end def test_not_updating_stylesheet_callback_for_partial Sass::Plugin.options[:always_update] = false assert_no_callback :not_updating_stylesheet, template_loc("_partial"), tempfile_loc("_partial") end def test_not_updating_stylesheet_callback_for_error Sass::Plugin.options[:always_update] = false touch 'bork1' assert_no_callback :not_updating_stylesheet, template_loc("bork1"), tempfile_loc("bork1") end def test_compilation_error_callback Sass::Plugin.options[:always_update] = false touch 'bork1' assert_callback(:compilation_error, lambda {|e| e.message == 'Undefined variable: "$bork".'}, template_loc("bork1"), tempfile_loc("bork1")) end def test_compilation_error_callback_for_file_access Sass::Plugin.options[:always_update] = false assert_callback(:compilation_error, lambda {|e| e.is_a?(Errno::ENOENT)}, template_loc("nonexistent"), tempfile_loc("nonexistent")) do Sass::Plugin.update_stylesheets([[template_loc("nonexistent"), tempfile_loc("nonexistent")]]) end end def test_creating_directory_callback Sass::Plugin.options[:always_update] = false dir = File.join(tempfile_loc, "subdir", "nested_subdir") FileUtils.rm_r dir assert_callback :creating_directory, dir end ## Regression def test_cached_dependencies_update FileUtils.mv(template_loc("basic"), template_loc("basic", "more_")) set_plugin_opts :load_paths => [template_loc(nil, "more_")] touch 'basic', 'more_' assert_needs_update "import" check_for_updates! assert_renders_correctly("import") ensure FileUtils.mv(template_loc("basic", "more_"), template_loc("basic")) end def test_cached_relative_import old_always_update = Sass::Plugin.options[:always_update] Sass::Plugin.options[:always_update] = true check_for_updates! assert_renders_correctly('subdir/subdir') ensure Sass::Plugin.options[:always_update] = old_always_update end def test_cached_if set_plugin_opts :cache_store => Sass::CacheStores::Filesystem.new(tempfile_loc + '/cache') check_for_updates! assert_renders_correctly 'if' check_for_updates! assert_renders_correctly 'if' ensure set_plugin_opts :cache_store => @@cache_store end private def assert_renders_correctly(*arguments) options = arguments.last.is_a?(Hash) ? arguments.pop : {} prefix = options[:prefix] result_name = arguments.shift tempfile_name = arguments.shift || result_name expected_str = File.read(result_loc(result_name, prefix)) actual_str = File.read(tempfile_loc(tempfile_name, prefix)) unless Sass::Util.ruby1_8? expected_str = expected_str.force_encoding('IBM866') if result_name == 'import_charset_ibm866' actual_str = actual_str.force_encoding('IBM866') if tempfile_name == 'import_charset_ibm866' end expected_lines = expected_str.split("\n") actual_lines = actual_str.split("\n") if actual_lines.first == "/*" && expected_lines.first != "/*" assert(false, actual_lines[0..Sass::Util.enum_with_index(actual_lines).find {|l, i| l == "*/"}.last].join("\n")) end expected_lines.zip(actual_lines).each_with_index do |pair, line| message = "template: #{result_name}\nline: #{line + 1}" assert_equal(pair.first, pair.last, message) end if expected_lines.size < actual_lines.size assert(false, "#{actual_lines.size - expected_lines.size} Trailing lines found in #{tempfile_name}.css: #{actual_lines[expected_lines.size..-1].join('\n')}") end end def assert_stylesheet_updated(name) assert_doesnt_need_update name # Make sure it isn't an exception expected_lines = File.read(result_loc(name)).split("\n") actual_lines = File.read(tempfile_loc(name)).split("\n") if actual_lines.first == "/*" && expected_lines.first != "/*" assert(false, actual_lines[0..actual_lines.enum_with_index.find {|l, i| l == "*/"}.last].join("\n")) end end def assert_callback(name, *expected_args) run = false Sass::Plugin.send("on_#{name}") do |*args| run ||= expected_args.zip(args).all? do |ea, a| ea.respond_to?(:call) ? ea.call(a) : ea == a end end if block_given? yield else check_for_updates! end assert run, "Expected #{name} callback to be run with arguments:\n #{expected_args.inspect}" end def assert_no_callback(name, *unexpected_args) Sass::Plugin.send("on_#{name}") do |*a| next unless unexpected_args.empty? || a == unexpected_args msg = "Expected #{name} callback not to be run" if !unexpected_args.empty? msg << " with arguments #{unexpected_args.inspect}" elsif !a.empty? msg << ",\n was run with arguments #{a.inspect}" end flunk msg end if block_given? yield else check_for_updates! end end def assert_callbacks(*args) return check_for_updates! if args.empty? assert_callback(*args.pop) {assert_callbacks(*args)} end def assert_no_callbacks(*args) return check_for_updates! if args.empty? assert_no_callback(*args.pop) {assert_no_callbacks(*args)} end def check_for_updates! Sass::Util.silence_sass_warnings do Sass::Plugin.check_for_updates end end def assert_needs_update(*args) assert(Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)), "Expected #{template_loc(*args)} to need an update.") end def assert_doesnt_need_update(*args) assert(!Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)), "Expected #{template_loc(*args)} not to need an update.") end def touch(*args) FileUtils.touch(template_loc(*args)) end def reset_mtimes Sass::Plugin::StalenessChecker.dependencies_cache = {} atime = Time.now mtime = Time.now - 5 Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each {|f| File.utime(atime, mtime, f)} end def template_loc(name = nil, prefix = nil) if name scss = absolutize "#{prefix}templates/#{name}.scss" File.exists?(scss) ? scss : absolutize("#{prefix}templates/#{name}.sass") else absolutize "#{prefix}templates" end end def tempfile_loc(name = nil, prefix = nil) if name absolutize "#{prefix}tmp/#{name}.css" else absolutize "#{prefix}tmp" end end def result_loc(name = nil, prefix = nil) if name absolutize "#{prefix}results/#{name}.css" else absolutize "#{prefix}results" end end def set_plugin_opts(overrides = {}) Sass::Plugin.options.merge!( :template_location => template_loc, :css_location => tempfile_loc, :style => :compact, :always_update => true, :never_update => false, :full_exception => true, :cache_store => @@cache_store ) Sass::Plugin.options.merge!(overrides) end end class Sass::Engine alias_method :old_render, :render def render raise "bork bork bork!" if @template[0] == "{bork now!}" old_render end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/importer_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/impo0000775000175000017500000000430312206724733033652 0ustar jamespagejamespage#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../test_helper' require File.dirname(__FILE__) + '/test_helper' class ImporterTest < Test::Unit::TestCase class FruitImporter < Sass::Importers::Base def find(name, context = nil) if name =~ %r{fruits/(\w+)(\.s[ac]ss)?} fruit = $1 color = case $1 when "apple" "red" when "orange" "orange" else "blue" end contents = %Q{ $#{fruit}-color: #{color} !default; @mixin #{fruit} { color: $#{fruit}-color; } } Sass::Engine.new(contents, :filename => name, :syntax => :scss, :importer => self) end end def key(name, context) [self.class.name, name] end end # This class proves that you can override the extension scheme for importers class ReversedExtImporter < Sass::Importers::Filesystem def extensions {"sscs" => :scss, "ssas" => :sass} end end def test_can_resolve_generated_imports scss_file = %Q{ $pear-color: green; @import "fruits/apple"; @import "fruits/orange"; @import "fruits/pear"; .apple { @include apple; } .orange { @include orange; } .pear { @include pear; } } css_file = < :compact, :load_paths => [FruitImporter.new], :syntax => :scss} assert_equal css_file, Sass::Engine.new(scss_file, options).render end def test_extension_overrides FileUtils.mkdir_p(absolutize("tmp")) open(absolutize("tmp/foo.ssas"), "w") {|f| f.write(".foo\n reversed: true\n")} open(absolutize("tmp/bar.sscs"), "w") {|f| f.write(".bar {reversed: true}\n")} scss_file = %Q{ @import "foo", "bar"; @import "foo.ssas", "bar.sscs"; } css_file = < :compact, :load_paths => [ReversedExtImporter.new(absolutize("tmp"))], :syntax => :scss} assert_equal css_file, Sass::Engine.new(scss_file, options).render ensure FileUtils.rm_rf(absolutize("tmp")) end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/functions_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/func0000775000175000017500000013157112206724733033651 0ustar jamespagejamespage#!/usr/bin/env ruby require 'test/unit' require File.dirname(__FILE__) + '/../test_helper' require 'sass/script' module Sass::Script::Functions def no_kw_args Sass::Script::String.new("no-kw-args") end def only_var_args(*args) Sass::Script::String.new("only-var-args("+args.map{|a| a.plus(Sass::Script::Number.new(1)).to_s }.join(", ")+")") end declare :only_var_args, [], :var_args => true def only_kw_args(kwargs) Sass::Script::String.new("only-kw-args(" + kwargs.keys.map {|a| a.to_s}.sort.join(", ") + ")") end declare :only_kw_args, [], :var_kwargs => true end module Sass::Script::Functions::UserFunctions def call_options_on_new_literal str = Sass::Script::String.new("foo") str.options[:foo] str end def user_defined Sass::Script::String.new("I'm a user-defined string!") end def _preceding_underscore Sass::Script::String.new("I'm another user-defined string!") end end module Sass::Script::Functions include Sass::Script::Functions::UserFunctions end class SassFunctionTest < Test::Unit::TestCase # Tests taken from: # http://www.w3.org/Style/CSS/Test/CSS3/Color/20070927/html4/t040204-hsl-h-rotating-b.htm # http://www.w3.org/Style/CSS/Test/CSS3/Color/20070927/html4/t040204-hsl-values-b.htm File.read(File.dirname(__FILE__) + "/data/hsl-rgb.txt").split("\n\n").each do |chunk| hsls, rgbs = chunk.strip.split("====") hsls.strip.split("\n").zip(rgbs.strip.split("\n")) do |hsl, rgb| hsl_method = "test_hsl: #{hsl} = #{rgb}" define_method(hsl_method) do assert_equal(evaluate(rgb), evaluate(hsl)) end rgb_to_hsl_method = "test_rgb_to_hsl: #{rgb} = #{hsl}" define_method(rgb_to_hsl_method) do rgb_color = perform(rgb) hsl_color = perform(hsl) white = hsl_color.lightness == 100 black = hsl_color.lightness == 0 grayscale = white || black || hsl_color.saturation == 0 assert_in_delta(hsl_color.hue, rgb_color.hue, 0.0001, "Hues should be equal") unless grayscale assert_in_delta(hsl_color.saturation, rgb_color.saturation, 0.0001, "Saturations should be equal") unless white || black assert_in_delta(hsl_color.lightness, rgb_color.lightness, 0.0001, "Lightnesses should be equal") end end end def test_hsl_kwargs assert_equal "#33cccc", evaluate("hsl($hue: 180, $saturation: 60%, $lightness: 50%)") end def test_hsl_checks_bounds assert_error_message("Saturation -114 must be between 0% and 100% for `hsl'", "hsl(10, -114, 12)"); assert_error_message("Lightness 256 must be between 0% and 100% for `hsl'", "hsl(10, 10, 256%)"); end def test_hsl_checks_types assert_error_message("\"foo\" is not a number for `hsl'", "hsl(\"foo\", 10, 12)"); assert_error_message("\"foo\" is not a number for `hsl'", "hsl(10, \"foo\", 12)"); assert_error_message("\"foo\" is not a number for `hsl'", "hsl(10, 10, \"foo\")"); end def test_hsla assert_equal "rgba(51, 204, 204, 0.4)", evaluate("hsla(180, 60%, 50%, 0.4)") assert_equal "#33cccc", evaluate("hsla(180, 60%, 50%, 1)") assert_equal "rgba(51, 204, 204, 0)", evaluate("hsla(180, 60%, 50%, 0)") assert_equal "rgba(51, 204, 204, 0.4)", evaluate("hsla($hue: 180, $saturation: 60%, $lightness: 50%, $alpha: 0.4)") end def test_hsla_checks_bounds assert_error_message("Saturation -114 must be between 0% and 100% for `hsla'", "hsla(10, -114, 12, 1)"); assert_error_message("Lightness 256 must be between 0% and 100% for `hsla'", "hsla(10, 10, 256%, 0)"); assert_error_message("Alpha channel -0.1 must be between 0 and 1 for `hsla'", "hsla(10, 10, 10, -0.1)"); assert_error_message("Alpha channel 1.1 must be between 0 and 1 for `hsla'", "hsla(10, 10, 10, 1.1)"); end def test_hsla_checks_types assert_error_message("\"foo\" is not a number for `hsla'", "hsla(\"foo\", 10, 12, 0.3)"); assert_error_message("\"foo\" is not a number for `hsla'", "hsla(10, \"foo\", 12, 0)"); assert_error_message("\"foo\" is not a number for `hsla'", "hsla(10, 10, \"foo\", 1)"); assert_error_message("\"foo\" is not a number for `hsla'", "hsla(10, 10, 10, \"foo\")"); end def test_percentage assert_equal("50%", evaluate("percentage(.5)")) assert_equal("100%", evaluate("percentage(1)")) assert_equal("25%", evaluate("percentage(25px / 100px)")) assert_equal("50%", evaluate("percentage($value: 0.5)")) end def test_percentage_checks_types assert_error_message("25px is not a unitless number for `percentage'", "percentage(25px)") assert_error_message("#cccccc is not a unitless number for `percentage'", "percentage(#ccc)") assert_error_message("\"string\" is not a unitless number for `percentage'", %Q{percentage("string")}) end def test_round assert_equal("5", evaluate("round(4.8)")) assert_equal("5px", evaluate("round(4.8px)")) assert_equal("5px", evaluate("round(5.49px)")) assert_equal("5px", evaluate("round($value: 5.49px)")) assert_error_message("#cccccc is not a number for `round'", "round(#ccc)") end def test_floor assert_equal("4", evaluate("floor(4.8)")) assert_equal("4px", evaluate("floor(4.8px)")) assert_equal("4px", evaluate("floor($value: 4.8px)")) assert_error_message("\"foo\" is not a number for `floor'", "floor(\"foo\")") end def test_ceil assert_equal("5", evaluate("ceil(4.1)")) assert_equal("5px", evaluate("ceil(4.8px)")) assert_equal("5px", evaluate("ceil($value: 4.8px)")) assert_error_message("\"a\" is not a number for `ceil'", "ceil(\"a\")") end def test_abs assert_equal("5", evaluate("abs(-5)")) assert_equal("5px", evaluate("abs(-5px)")) assert_equal("5", evaluate("abs(5)")) assert_equal("5px", evaluate("abs(5px)")) assert_equal("5px", evaluate("abs($value: 5px)")) assert_error_message("#aaaaaa is not a number for `abs'", "abs(#aaa)") end def test_rgb assert_equal("#123456", evaluate("rgb(18, 52, 86)")) assert_equal("#beaded", evaluate("rgb(190, 173, 237)")) assert_equal("#00ff7f", evaluate("rgb(0, 255, 127)")) assert_equal("#00ff7f", evaluate("rgb($red: 0, $green: 255, $blue: 127)")) end def test_rgb_percent assert_equal("#123456", evaluate("rgb(7.1%, 20.4%, 34%)")) assert_equal("#beaded", evaluate("rgb(74.7%, 173, 93%)")) assert_equal("#beaded", evaluate("rgb(190, 68%, 237)")) assert_equal("#00ff7f", evaluate("rgb(0%, 100%, 50%)")) end def test_rgb_tests_bounds assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgb'", "rgb(256, 1, 1)") assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgb'", "rgb(1, 256, 1)") assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgb'", "rgb(1, 1, 256)") assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgb'", "rgb(1, 256, 257)") assert_error_message("Color value -1 must be between 0 and 255 inclusive for `rgb'", "rgb(-1, 1, 1)") end def test_rgb_test_percent_bounds assert_error_message("Color value 100.1% must be between 0% and 100% inclusive for `rgb'", "rgb(100.1%, 0, 0)") assert_error_message("Color value -0.1% must be between 0% and 100% inclusive for `rgb'", "rgb(0, -0.1%, 0)") assert_error_message("Color value 101% must be between 0% and 100% inclusive for `rgb'", "rgb(0, 0, 101%)") end def test_rgb_tests_types assert_error_message("\"foo\" is not a number for `rgb'", "rgb(\"foo\", 10, 12)"); assert_error_message("\"foo\" is not a number for `rgb'", "rgb(10, \"foo\", 12)"); assert_error_message("\"foo\" is not a number for `rgb'", "rgb(10, 10, \"foo\")"); end def test_rgba assert_equal("rgba(18, 52, 86, 0.5)", evaluate("rgba(18, 52, 86, 0.5)")) assert_equal("#beaded", evaluate("rgba(190, 173, 237, 1)")) assert_equal("rgba(0, 255, 127, 0)", evaluate("rgba(0, 255, 127, 0)")) assert_equal("rgba(0, 255, 127, 0)", evaluate("rgba($red: 0, $green: 255, $blue: 127, $alpha: 0)")) end def test_rgb_tests_bounds assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgba'", "rgba(256, 1, 1, 0.3)") assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgba'", "rgba(1, 256, 1, 0.3)") assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgba'", "rgba(1, 1, 256, 0.3)") assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgba'", "rgba(1, 256, 257, 0.3)") assert_error_message("Color value -1 must be between 0 and 255 inclusive for `rgba'", "rgba(-1, 1, 1, 0.3)") assert_error_message("Alpha channel -0.2 must be between 0 and 1 inclusive for `rgba'", "rgba(1, 1, 1, -0.2)") assert_error_message("Alpha channel 1.2 must be between 0 and 1 inclusive for `rgba'", "rgba(1, 1, 1, 1.2)") end def test_rgba_tests_types assert_error_message("\"foo\" is not a number for `rgba'", "rgba(\"foo\", 10, 12, 0.2)"); assert_error_message("\"foo\" is not a number for `rgba'", "rgba(10, \"foo\", 12, 0.1)"); assert_error_message("\"foo\" is not a number for `rgba'", "rgba(10, 10, \"foo\", 0)"); assert_error_message("\"foo\" is not a number for `rgba'", "rgba(10, 10, 10, \"foo\")"); end def test_rgba_with_color assert_equal "rgba(16, 32, 48, 0.5)", evaluate("rgba(#102030, 0.5)") assert_equal "rgba(0, 0, 255, 0.5)", evaluate("rgba(blue, 0.5)") assert_equal "rgba(0, 0, 255, 0.5)", evaluate("rgba($color: blue, $alpha: 0.5)") end def test_rgba_with_color_tests_types assert_error_message("\"foo\" is not a color for `rgba'", "rgba(\"foo\", 0.2)"); assert_error_message("\"foo\" is not a number for `rgba'", "rgba(blue, \"foo\")"); end def test_rgba_tests_num_args assert_error_message("wrong number of arguments (0 for 4) for `rgba'", "rgba()"); assert_error_message("wrong number of arguments (1 for 4) for `rgba'", "rgba(blue)"); assert_error_message("wrong number of arguments (3 for 4) for `rgba'", "rgba(1, 2, 3)"); assert_error_message("wrong number of arguments (5 for 4) for `rgba'", "rgba(1, 2, 3, 0.4, 5)"); end def test_red assert_equal("18", evaluate("red(#123456)")) assert_equal("18", evaluate("red($color: #123456)")) end def test_red_exception assert_error_message("12 is not a color for `red'", "red(12)") end def test_green assert_equal("52", evaluate("green(#123456)")) assert_equal("52", evaluate("green($color: #123456)")) end def test_green_exception assert_error_message("12 is not a color for `green'", "green(12)") end def test_blue assert_equal("86", evaluate("blue(#123456)")) assert_equal("86", evaluate("blue($color: #123456)")) end def test_blue_exception assert_error_message("12 is not a color for `blue'", "blue(12)") end def test_hue assert_equal("18deg", evaluate("hue(hsl(18, 50%, 20%))")) assert_equal("18deg", evaluate("hue($color: hsl(18, 50%, 20%))")) end def test_hue_exception assert_error_message("12 is not a color for `hue'", "hue(12)") end def test_saturation assert_equal("52%", evaluate("saturation(hsl(20, 52%, 20%))")) assert_equal("52%", evaluate("saturation(hsl(20, 52, 20%))")) assert_equal("52%", evaluate("saturation($color: hsl(20, 52, 20%))")) end def test_saturation_exception assert_error_message("12 is not a color for `saturation'", "saturation(12)") end def test_lightness assert_equal("86%", evaluate("lightness(hsl(120, 50%, 86%))")) assert_equal("86%", evaluate("lightness(hsl(120, 50%, 86))")) assert_equal("86%", evaluate("lightness($color: hsl(120, 50%, 86))")) end def test_lightness_exception assert_error_message("12 is not a color for `lightness'", "lightness(12)") end def test_alpha assert_equal("1", evaluate("alpha(#123456)")) assert_equal("0.34", evaluate("alpha(rgba(0, 1, 2, 0.34))")) assert_equal("0", evaluate("alpha(hsla(0, 1, 2, 0))")) assert_equal("0", evaluate("alpha($color: hsla(0, 1, 2, 0))")) end def test_alpha_exception assert_error_message("12 is not a color for `alpha'", "alpha(12)") end def test_opacify assert_equal("rgba(0, 0, 0, 0.75)", evaluate("opacify(rgba(0, 0, 0, 0.5), 0.25)")) assert_equal("rgba(0, 0, 0, 0.3)", evaluate("opacify(rgba(0, 0, 0, 0.2), 0.1)")) assert_equal("rgba(0, 0, 0, 0.7)", evaluate("fade-in(rgba(0, 0, 0, 0.2), 0.5px)")) assert_equal("black", evaluate("fade_in(rgba(0, 0, 0, 0.2), 0.8)")) assert_equal("black", evaluate("opacify(rgba(0, 0, 0, 0.2), 1)")) assert_equal("rgba(0, 0, 0, 0.2)", evaluate("opacify(rgba(0, 0, 0, 0.2), 0%)")) assert_equal("rgba(0, 0, 0, 0.2)", evaluate("opacify($color: rgba(0, 0, 0, 0.2), $amount: 0%)")) assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-in($color: rgba(0, 0, 0, 0.2), $amount: 0%)")) end def test_opacify_tests_bounds assert_error_message("Amount -0.001 must be between 0 and 1 for `opacify'", "opacify(rgba(0, 0, 0, 0.2), -0.001)") assert_error_message("Amount 1.001 must be between 0 and 1 for `opacify'", "opacify(rgba(0, 0, 0, 0.2), 1.001)") end def test_opacify_tests_types assert_error_message("\"foo\" is not a color for `opacify'", "opacify(\"foo\", 10%)") assert_error_message("\"foo\" is not a number for `opacify'", "opacify(#fff, \"foo\")") end def test_transparentize assert_equal("rgba(0, 0, 0, 0.3)", evaluate("transparentize(rgba(0, 0, 0, 0.5), 0.2)")) assert_equal("rgba(0, 0, 0, 0.1)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0.1)")) assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-out(rgba(0, 0, 0, 0.5), 0.3px)")) assert_equal("rgba(0, 0, 0, 0)", evaluate("fade_out(rgba(0, 0, 0, 0.2), 0.2)")) assert_equal("rgba(0, 0, 0, 0)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 1)")) assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0)")) assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize($color: rgba(0, 0, 0, 0.2), $amount: 0)")) assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-out($color: rgba(0, 0, 0, 0.2), $amount: 0)")) end def test_transparentize_tests_bounds assert_error_message("Amount -0.001 must be between 0 and 1 for `transparentize'", "transparentize(rgba(0, 0, 0, 0.2), -0.001)") assert_error_message("Amount 1.001 must be between 0 and 1 for `transparentize'", "transparentize(rgba(0, 0, 0, 0.2), 1.001)") end def test_transparentize_tests_types assert_error_message("\"foo\" is not a color for `transparentize'", "transparentize(\"foo\", 10%)") assert_error_message("\"foo\" is not a number for `transparentize'", "transparentize(#fff, \"foo\")") end def test_lighten assert_equal("#4d4d4d", evaluate("lighten(hsl(0, 0, 0), 30%)")) assert_equal("#ee0000", evaluate("lighten(#800, 20%)")) assert_equal("white", evaluate("lighten(#fff, 20%)")) assert_equal("white", evaluate("lighten(#800, 100%)")) assert_equal("#880000", evaluate("lighten(#800, 0%)")) assert_equal("rgba(238, 0, 0, 0.5)", evaluate("lighten(rgba(136, 0, 0, 0.5), 20%)")) assert_equal("rgba(238, 0, 0, 0.5)", evaluate("lighten($color: rgba(136, 0, 0, 0.5), $amount: 20%)")) end def test_lighten_tests_bounds assert_error_message("Amount -0.001 must be between 0% and 100% for `lighten'", "lighten(#123, -0.001)") assert_error_message("Amount 100.001 must be between 0% and 100% for `lighten'", "lighten(#123, 100.001)") end def test_lighten_tests_types assert_error_message("\"foo\" is not a color for `lighten'", "lighten(\"foo\", 10%)") assert_error_message("\"foo\" is not a number for `lighten'", "lighten(#fff, \"foo\")") end def test_darken assert_equal("#ff6a00", evaluate("darken(hsl(25, 100, 80), 30%)")) assert_equal("#220000", evaluate("darken(#800, 20%)")) assert_equal("black", evaluate("darken(#000, 20%)")) assert_equal("black", evaluate("darken(#800, 100%)")) assert_equal("#880000", evaluate("darken(#800, 0%)")) assert_equal("rgba(34, 0, 0, 0.5)", evaluate("darken(rgba(136, 0, 0, 0.5), 20%)")) assert_equal("rgba(34, 0, 0, 0.5)", evaluate("darken($color: rgba(136, 0, 0, 0.5), $amount: 20%)")) end def test_darken_tests_bounds assert_error_message("Amount -0.001 must be between 0% and 100% for `darken'", "darken(#123, -0.001)") assert_error_message("Amount 100.001 must be between 0% and 100% for `darken'", "darken(#123, 100.001)") end def test_darken_tests_types assert_error_message("\"foo\" is not a color for `darken'", "darken(\"foo\", 10%)") assert_error_message("\"foo\" is not a number for `darken'", "darken(#fff, \"foo\")") end def test_saturate assert_equal("#d9f2d9", evaluate("saturate(hsl(120, 30, 90), 20%)")) assert_equal("#9e3f3f", evaluate("saturate(#855, 20%)")) assert_equal("black", evaluate("saturate(#000, 20%)")) assert_equal("white", evaluate("saturate(#fff, 20%)")) assert_equal("#33ff33", evaluate("saturate(#8a8, 100%)")) assert_equal("#88aa88", evaluate("saturate(#8a8, 0%)")) assert_equal("rgba(158, 63, 63, 0.5)", evaluate("saturate(rgba(136, 85, 85, 0.5), 20%)")) assert_equal("rgba(158, 63, 63, 0.5)", evaluate("saturate($color: rgba(136, 85, 85, 0.5), $amount: 20%)")) end def test_saturate_tests_bounds assert_error_message("Amount -0.001 must be between 0% and 100% for `saturate'", "saturate(#123, -0.001)") assert_error_message("Amount 100.001 must be between 0% and 100% for `saturate'", "saturate(#123, 100.001)") end def test_saturate_tests_types assert_error_message("\"foo\" is not a color for `saturate'", "saturate(\"foo\", 10%)") assert_error_message("\"foo\" is not a number for `saturate'", "saturate(#fff, \"foo\")") end def test_desaturate assert_equal("#e3e8e3", evaluate("desaturate(hsl(120, 30, 90), 20%)")) assert_equal("#726b6b", evaluate("desaturate(#855, 20%)")) assert_equal("black", evaluate("desaturate(#000, 20%)")) assert_equal("white", evaluate("desaturate(#fff, 20%)")) assert_equal("#999999", evaluate("desaturate(#8a8, 100%)")) assert_equal("#88aa88", evaluate("desaturate(#8a8, 0%)")) assert_equal("rgba(114, 107, 107, 0.5)", evaluate("desaturate(rgba(136, 85, 85, 0.5), 20%)")) assert_equal("rgba(114, 107, 107, 0.5)", evaluate("desaturate($color: rgba(136, 85, 85, 0.5), $amount: 20%)")) end def test_desaturate_tests_bounds assert_error_message("Amount -0.001 must be between 0% and 100% for `desaturate'", "desaturate(#123, -0.001)") assert_error_message("Amount 100.001 must be between 0% and 100% for `desaturate'", "desaturate(#123, 100.001)") end def test_desaturate_tests_types assert_error_message("\"foo\" is not a color for `desaturate'", "desaturate(\"foo\", 10%)") assert_error_message("\"foo\" is not a number for `desaturate'", "desaturate(#fff, \"foo\")") end def test_adjust_hue assert_equal("#deeded", evaluate("adjust-hue(hsl(120, 30, 90), 60deg)")) assert_equal("#ededde", evaluate("adjust-hue(hsl(120, 30, 90), -60deg)")) assert_equal("#886a11", evaluate("adjust-hue(#811, 45deg)")) assert_equal("black", evaluate("adjust-hue(#000, 45deg)")) assert_equal("white", evaluate("adjust-hue(#fff, 45deg)")) assert_equal("#88aa88", evaluate("adjust-hue(#8a8, 360deg)")) assert_equal("#88aa88", evaluate("adjust-hue(#8a8, 0deg)")) assert_equal("rgba(136, 106, 17, 0.5)", evaluate("adjust-hue(rgba(136, 17, 17, 0.5), 45deg)")) assert_equal("rgba(136, 106, 17, 0.5)", evaluate("adjust-hue($color: rgba(136, 17, 17, 0.5), $degrees: 45deg)")) end def test_adjust_hue_tests_types assert_error_message("\"foo\" is not a color for `adjust-hue'", "adjust-hue(\"foo\", 10%)") assert_error_message("\"foo\" is not a number for `adjust-hue'", "adjust-hue(#fff, \"foo\")") end def test_adjust_color # HSL assert_equal(evaluate("hsl(180, 30, 90)"), evaluate("adjust-color(hsl(120, 30, 90), $hue: 60deg)")) assert_equal(evaluate("hsl(120, 50, 90)"), evaluate("adjust-color(hsl(120, 30, 90), $saturation: 20%)")) assert_equal(evaluate("hsl(120, 30, 60)"), evaluate("adjust-color(hsl(120, 30, 90), $lightness: -30%)")) # RGB assert_equal(evaluate("rgb(15, 20, 30)"), evaluate("adjust-color(rgb(10, 20, 30), $red: 5)")) assert_equal(evaluate("rgb(10, 15, 30)"), evaluate("adjust-color(rgb(10, 20, 30), $green: -5)")) assert_equal(evaluate("rgb(10, 20, 40)"), evaluate("adjust-color(rgb(10, 20, 30), $blue: 10)")) # Alpha assert_equal(evaluate("hsla(120, 30, 90, 0.65)"), evaluate("adjust-color(hsl(120, 30, 90), $alpha: -0.35)")) assert_equal(evaluate("rgba(10, 20, 30, 0.9)"), evaluate("adjust-color(rgba(10, 20, 30, 0.4), $alpha: 0.5)")) # HSL composability assert_equal(evaluate("hsl(180, 20, 90)"), evaluate("adjust-color(hsl(120, 30, 90), $hue: 60deg, $saturation: -10%)")) assert_equal(evaluate("hsl(180, 20, 95)"), evaluate("adjust-color(hsl(120, 30, 90), $hue: 60deg, $saturation: -10%, $lightness: 5%)")) assert_equal(evaluate("hsla(120, 20, 95, 0.3)"), evaluate("adjust-color(hsl(120, 30, 90), $saturation: -10%, $lightness: 5%, $alpha: -0.7)")) # RGB composability assert_equal(evaluate("rgb(15, 20, 29)"), evaluate("adjust-color(rgb(10, 20, 30), $red: 5, $blue: -1)")) assert_equal(evaluate("rgb(15, 45, 29)"), evaluate("adjust-color(rgb(10, 20, 30), $red: 5, $green: 25, $blue: -1)")) assert_equal(evaluate("rgba(10, 25, 29, 0.7)"), evaluate("adjust-color(rgb(10, 20, 30), $green: 5, $blue: -1, $alpha: -0.3)")) # HSL range restriction assert_equal(evaluate("hsl(120, 30, 90)"), evaluate("adjust-color(hsl(120, 30, 90), $hue: 720deg)")) assert_equal(evaluate("hsl(120, 0, 90)"), evaluate("adjust-color(hsl(120, 30, 90), $saturation: -90%)")) assert_equal(evaluate("hsl(120, 30, 100)"), evaluate("adjust-color(hsl(120, 30, 90), $lightness: 30%)")) # RGB range restriction assert_equal(evaluate("rgb(255, 20, 30)"), evaluate("adjust-color(rgb(10, 20, 30), $red: 250)")) assert_equal(evaluate("rgb(10, 0, 30)"), evaluate("adjust-color(rgb(10, 20, 30), $green: -30)")) assert_equal(evaluate("rgb(10, 20, 0)"), evaluate("adjust-color(rgb(10, 20, 30), $blue: -40)")) end def test_adjust_color_tests_types assert_error_message("\"foo\" is not a color for `adjust-color'", "adjust-color(foo, $hue: 10)") # HSL assert_error_message("$hue: \"foo\" is not a number for `adjust-color'", "adjust-color(blue, $hue: foo)") assert_error_message("$saturation: \"foo\" is not a number for `adjust-color'", "adjust-color(blue, $saturation: foo)") assert_error_message("$lightness: \"foo\" is not a number for `adjust-color'", "adjust-color(blue, $lightness: foo)") # RGB assert_error_message("$red: \"foo\" is not a number for `adjust-color'", "adjust-color(blue, $red: foo)") assert_error_message("$green: \"foo\" is not a number for `adjust-color'", "adjust-color(blue, $green: foo)") assert_error_message("$blue: \"foo\" is not a number for `adjust-color'", "adjust-color(blue, $blue: foo)") # Alpha assert_error_message("$alpha: \"foo\" is not a number for `adjust-color'", "adjust-color(blue, $alpha: foo)") end def test_adjust_color_tests_arg_range # HSL assert_error_message("$saturation: Amount 101% must be between -100% and 100% for `adjust-color'", "adjust-color(blue, $saturation: 101%)") assert_error_message("$saturation: Amount -101% must be between -100% and 100% for `adjust-color'", "adjust-color(blue, $saturation: -101%)") assert_error_message("$lightness: Amount 101% must be between -100% and 100% for `adjust-color'", "adjust-color(blue, $lightness: 101%)") assert_error_message("$lightness: Amount -101% must be between -100% and 100% for `adjust-color'", "adjust-color(blue, $lightness: -101%)") # RGB assert_error_message("$red: Amount 256 must be between -255 and 255 for `adjust-color'", "adjust-color(blue, $red: 256)") assert_error_message("$red: Amount -256 must be between -255 and 255 for `adjust-color'", "adjust-color(blue, $red: -256)") assert_error_message("$green: Amount 256 must be between -255 and 255 for `adjust-color'", "adjust-color(blue, $green: 256)") assert_error_message("$green: Amount -256 must be between -255 and 255 for `adjust-color'", "adjust-color(blue, $green: -256)") assert_error_message("$blue: Amount 256 must be between -255 and 255 for `adjust-color'", "adjust-color(blue, $blue: 256)") assert_error_message("$blue: Amount -256 must be between -255 and 255 for `adjust-color'", "adjust-color(blue, $blue: -256)") # Alpha assert_error_message("$alpha: Amount 1.1 must be between -1 and 1 for `adjust-color'", "adjust-color(blue, $alpha: 1.1)") assert_error_message("$alpha: Amount -1.1 must be between -1 and 1 for `adjust-color'", "adjust-color(blue, $alpha: -1.1)") end def test_adjust_color_argument_errors assert_error_message("Unknown argument $hoo (260deg) for `adjust-color'", "adjust-color(blue, $hoo: 260deg)") assert_error_message("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'", "adjust-color(blue, $hue: 120deg, $red: 10)"); assert_error_message("10px is not a keyword argument for `adjust_color'", "adjust-color(blue, 10px)") assert_error_message("10px is not a keyword argument for `adjust_color'", "adjust-color(blue, 10px, 20px)") assert_error_message("10px is not a keyword argument for `adjust_color'", "adjust-color(blue, 10px, $hue: 180deg)") end def test_scale_color # HSL assert_equal(evaluate("hsl(120, 51, 90)"), evaluate("scale-color(hsl(120, 30, 90), $saturation: 30%)")) assert_equal(evaluate("hsl(120, 30, 76.5)"), evaluate("scale-color(hsl(120, 30, 90), $lightness: -15%)")) # RGB assert_equal(evaluate("rgb(157, 20, 30)"), evaluate("scale-color(rgb(10, 20, 30), $red: 60%)")) assert_equal(evaluate("rgb(10, 38.8, 30)"), evaluate("scale-color(rgb(10, 20, 30), $green: 8%)")) assert_equal(evaluate("rgb(10, 20, 20)"), evaluate("scale-color(rgb(10, 20, 30), $blue: -(1/3)*100%)")) # Alpha assert_equal(evaluate("hsla(120, 30, 90, 0.86)"), evaluate("scale-color(hsl(120, 30, 90), $alpha: -14%)")) assert_equal(evaluate("rgba(10, 20, 30, 0.82)"), evaluate("scale-color(rgba(10, 20, 30, 0.8), $alpha: 10%)")) # HSL composability assert_equal(evaluate("hsl(120, 51, 76.5)"), evaluate("scale-color(hsl(120, 30, 90), $saturation: 30%, $lightness: -15%)")) assert_equal(evaluate("hsla(120, 51, 90, 0.2)"), evaluate("scale-color(hsl(120, 30, 90), $saturation: 30%, $alpha: -80%)")) # RGB composability assert_equal(evaluate("rgb(157, 38.8, 30)"), evaluate("scale-color(rgb(10, 20, 30), $red: 60%, $green: 8%)")) assert_equal(evaluate("rgb(157, 38.8, 20)"), evaluate("scale-color(rgb(10, 20, 30), $red: 60%, $green: 8%, $blue: -(1/3)*100%)")) assert_equal(evaluate("rgba(10, 38.8, 20, 0.55)"), evaluate("scale-color(rgba(10, 20, 30, 0.5), $green: 8%, $blue: -(1/3)*100%, $alpha: 10%)")) # Extremes assert_equal(evaluate("hsl(120, 100, 90)"), evaluate("scale-color(hsl(120, 30, 90), $saturation: 100%)")) assert_equal(evaluate("hsl(120, 30, 90)"), evaluate("scale-color(hsl(120, 30, 90), $saturation: 0%)")) assert_equal(evaluate("hsl(120, 0, 90)"), evaluate("scale-color(hsl(120, 30, 90), $saturation: -100%)")) end def test_scale_color_tests_types assert_error_message("\"foo\" is not a color for `scale-color'", "scale-color(foo, $red: 10%)") # HSL assert_error_message("$saturation: \"foo\" is not a number for `scale-color'", "scale-color(blue, $saturation: foo)") assert_error_message("$lightness: \"foo\" is not a number for `scale-color'", "scale-color(blue, $lightness: foo)") # RGB assert_error_message("$red: \"foo\" is not a number for `scale-color'", "scale-color(blue, $red: foo)") assert_error_message("$green: \"foo\" is not a number for `scale-color'", "scale-color(blue, $green: foo)") assert_error_message("$blue: \"foo\" is not a number for `scale-color'", "scale-color(blue, $blue: foo)") # Alpha assert_error_message("$alpha: \"foo\" is not a number for `scale-color'", "scale-color(blue, $alpha: foo)") end def test_scale_color_argument_errors # Range assert_error_message("$saturation: Amount 101% must be between -100% and 100% for `scale-color'", "scale-color(blue, $saturation: 101%)") assert_error_message("$red: Amount -101% must be between -100% and 100% for `scale-color'", "scale-color(blue, $red: -101%)") assert_error_message("$alpha: Amount -101% must be between -100% and 100% for `scale-color'", "scale-color(blue, $alpha: -101%)") # Unit assert_error_message("$saturation: Amount 80 must be a % (e.g. 80%) for `scale-color'", "scale-color(blue, $saturation: 80)") assert_error_message("$alpha: Amount 0.5 must be a % (e.g. 0.5%) for `scale-color'", "scale-color(blue, $alpha: 0.5)") # Unknown argument assert_error_message("Unknown argument $hue (80%) for `scale-color'", "scale-color(blue, $hue: 80%)") # Non-keyword arg assert_error_message("10px is not a keyword argument for `scale_color'", "scale-color(blue, 10px)") # HSL/RGB assert_error_message("Cannot specify HSL and RGB values for a color at the same time for `scale-color'", "scale-color(blue, $lightness: 10%, $red: 20%)"); end def test_change_color # HSL assert_equal(evaluate("hsl(195, 30, 90)"), evaluate("change-color(hsl(120, 30, 90), $hue: 195deg)")) assert_equal(evaluate("hsl(120, 50, 90)"), evaluate("change-color(hsl(120, 30, 90), $saturation: 50%)")) assert_equal(evaluate("hsl(120, 30, 40)"), evaluate("change-color(hsl(120, 30, 90), $lightness: 40%)")) # RGB assert_equal(evaluate("rgb(123, 20, 30)"), evaluate("change-color(rgb(10, 20, 30), $red: 123)")) assert_equal(evaluate("rgb(10, 234, 30)"), evaluate("change-color(rgb(10, 20, 30), $green: 234)")) assert_equal(evaluate("rgb(10, 20, 198)"), evaluate("change-color(rgb(10, 20, 30), $blue: 198)")) # Alpha assert_equal(evaluate("rgba(10, 20, 30, 0.76)"), evaluate("change-color(rgb(10, 20, 30), $alpha: 0.76)")) # HSL composability assert_equal(evaluate("hsl(56, 30, 47)"), evaluate("change-color(hsl(120, 30, 90), $hue: 56deg, $lightness: 47%)")) assert_equal(evaluate("hsla(56, 30, 47, 0.9)"), evaluate("change-color(hsl(120, 30, 90), $hue: 56deg, $lightness: 47%, $alpha: 0.9)")) end def test_change_color_tests_types assert_error_message("\"foo\" is not a color for `change-color'", "change-color(foo, $red: 10%)") # HSL assert_error_message("$saturation: \"foo\" is not a number for `change-color'", "change-color(blue, $saturation: foo)") assert_error_message("$lightness: \"foo\" is not a number for `change-color'", "change-color(blue, $lightness: foo)") # RGB assert_error_message("$red: \"foo\" is not a number for `change-color'", "change-color(blue, $red: foo)") assert_error_message("$green: \"foo\" is not a number for `change-color'", "change-color(blue, $green: foo)") assert_error_message("$blue: \"foo\" is not a number for `change-color'", "change-color(blue, $blue: foo)") # Alpha assert_error_message("$alpha: \"foo\" is not a number for `change-color'", "change-color(blue, $alpha: foo)") end def test_change_color_argument_errors # Range assert_error_message("Saturation must be between 0 and 100 for `change-color'", "change-color(blue, $saturation: 101%)") assert_error_message("Lightness must be between 0 and 100 for `change-color'", "change-color(blue, $lightness: 101%)") assert_error_message("Red value must be between 0 and 255 for `change-color'", "change-color(blue, $red: -1)") assert_error_message("Green value must be between 0 and 255 for `change-color'", "change-color(blue, $green: 256)") assert_error_message("Blue value must be between 0 and 255 for `change-color'", "change-color(blue, $blue: 500)") # Unknown argument assert_error_message("Unknown argument $hoo (80%) for `change-color'", "change-color(blue, $hoo: 80%)") # Non-keyword arg assert_error_message("10px is not a keyword argument for `change_color'", "change-color(blue, 10px)") # HSL/RGB assert_error_message("Cannot specify HSL and RGB values for a color at the same time for `change-color'", "change-color(blue, $lightness: 10%, $red: 120)"); end def test_mix assert_equal("#7f007f", evaluate("mix(#f00, #00f)")) assert_equal("#7f7f7f", evaluate("mix(#f00, #0ff)")) assert_equal("#7f9055", evaluate("mix(#f70, #0aa)")) assert_equal("#3f00bf", evaluate("mix(#f00, #00f, 25%)")) assert_equal("rgba(63, 0, 191, 0.75)", evaluate("mix(rgba(255, 0, 0, 0.5), #00f)")) assert_equal("red", evaluate("mix(#f00, #00f, 100%)")) assert_equal("blue", evaluate("mix(#f00, #00f, 0%)")) assert_equal("rgba(255, 0, 0, 0.5)", evaluate("mix(#f00, transparentize(#00f, 1))")) assert_equal("rgba(0, 0, 255, 0.5)", evaluate("mix(transparentize(#f00, 1), #00f)")) assert_equal("red", evaluate("mix(#f00, transparentize(#00f, 1), 100%)")) assert_equal("blue", evaluate("mix(transparentize(#f00, 1), #00f, 0%)")) assert_equal("rgba(0, 0, 255, 0)", evaluate("mix(#f00, transparentize(#00f, 1), 0%)")) assert_equal("rgba(255, 0, 0, 0)", evaluate("mix(transparentize(#f00, 1), #00f, 100%)")) assert_equal("rgba(255, 0, 0, 0)", evaluate("mix($color-1: transparentize(#f00, 1), $color-2: #00f, $weight: 100%)")) end def test_mix_tests_types assert_error_message("\"foo\" is not a color for `mix'", "mix(\"foo\", #f00, 10%)") assert_error_message("\"foo\" is not a color for `mix'", "mix(#f00, \"foo\", 10%)") assert_error_message("\"foo\" is not a number for `mix'", "mix(#f00, #baf, \"foo\")") end def test_mix_tests_bounds assert_error_message("Weight -0.001 must be between 0% and 100% for `mix'", "mix(#123, #456, -0.001)") assert_error_message("Weight 100.001 must be between 0% and 100% for `mix'", "mix(#123, #456, 100.001)") end def test_grayscale assert_equal("#bbbbbb", evaluate("grayscale(#abc)")) assert_equal("gray", evaluate("grayscale(#f00)")) assert_equal("gray", evaluate("grayscale(#00f)")) assert_equal("white", evaluate("grayscale(white)")) assert_equal("black", evaluate("grayscale(black)")) assert_equal("black", evaluate("grayscale($color: black)")) end def tets_grayscale_tests_types assert_error_message("\"foo\" is not a color for `grayscale'", "grayscale(\"foo\")") end def test_complement assert_equal("#ccbbaa", evaluate("complement(#abc)")) assert_equal("aqua", evaluate("complement(red)")) assert_equal("red", evaluate("complement(aqua)")) assert_equal("white", evaluate("complement(white)")) assert_equal("black", evaluate("complement(black)")) assert_equal("black", evaluate("complement($color: black)")) end def tets_complement_tests_types assert_error_message("\"foo\" is not a color for `complement'", "complement(\"foo\")") end def test_invert assert_equal("#112233", evaluate("invert(#edc)")) assert_equal("rgba(245, 235, 225, 0.5)", evaluate("invert(rgba(10, 20, 30, 0.5))")) end def test_invert_tests_types assert_error_message("\"foo\" is not a color for `invert'", "invert(\"foo\")") end def test_unquote assert_equal('foo', evaluate('unquote("foo")')) assert_equal('foo', evaluate('unquote(foo)')) assert_equal('foo', evaluate('unquote($string: foo)')) end def test_quote assert_equal('"foo"', evaluate('quote(foo)')) assert_equal('"foo"', evaluate('quote("foo")')) assert_equal('"foo"', evaluate('quote($string: "foo")')) end def test_quote_tests_type assert_error_message("#ff0000 is not a string for `quote'", "quote(#f00)") end def test_user_defined_function assert_equal("I'm a user-defined string!", evaluate("user_defined()")) end def test_user_defined_function_with_preceding_underscore assert_equal("I'm another user-defined string!", evaluate("_preceding_underscore()")) assert_equal("I'm another user-defined string!", evaluate("-preceding-underscore()")) end def test_options_on_new_literals_fails assert_error_message(< e assert_equal("Function rgba doesn't take an argument named $extra", e.message) end def test_keyword_args_must_have_signature evaluate("no-kw-args($fake: value)") rescue Sass::SyntaxError => e assert_equal("Function no_kw_args doesn't support keyword arguments", e.message) end def test_keyword_args_with_missing_argument evaluate("rgb($red: 255, $green: 255)") rescue Sass::SyntaxError => e assert_equal("Function rgb requires an argument named $blue", e.message) end def test_only_var_args assert_equal "only-var-args(2px, 3px, 4px)", evaluate("only-var-args(1px, 2px, 3px)") end def test_only_kw_args assert_equal "only-kw-args(a, b, c)", evaluate("only-kw-args($a: 1, $b: 2, $c: 3)") end private def evaluate(value) Sass::Script::Parser.parse(value, 0, 0).perform(Sass::Environment.new).to_s end def perform(value) Sass::Script::Parser.parse(value, 0, 0).perform(Sass::Environment.new) end def assert_error_message(message, value) evaluate(value) flunk("Error message expected but not raised: #{message}") rescue Sass::SyntaxError => e assert_equal(message, e.message) end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/callbacks_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/call0000775000175000017500000000214312206724733033621 0ustar jamespagejamespage#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../test_helper' require 'sass/callbacks' class CallerBack extend Sass::Callbacks define_callback :foo define_callback :bar def do_foo run_foo end def do_bar run_bar 12 end end module ClassLevelCallerBack extend Sass::Callbacks define_callback :foo extend self def do_foo run_foo end end class SassCallbacksTest < Test::Unit::TestCase def test_simple_callback cb = CallerBack.new there = false cb.on_foo {there = true} cb.do_foo assert there, "Expected callback to be called." end def test_multiple_callbacks cb = CallerBack.new str = "" cb.on_foo {str += "first"} cb.on_foo {str += " second"} cb.do_foo assert_equal "first second", str end def test_callback_with_arg cb = CallerBack.new val = nil cb.on_bar {|a| val = a} cb.do_bar assert_equal 12, val end def test_class_level_callback there = false ClassLevelCallerBack.on_foo {there = true} ClassLevelCallerBack.do_foo assert there, "Expected callback to be called." end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/mock_importer.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/mock0000664000175000017500000000161612206724733033640 0ustar jamespagejamespageclass MockImporter < Sass::Importers::Base def initialize(name = "mock") @name = name @imports = Hash.new({}) end def find_relative(uri, base, options) nil end def find(uri, options) contents = @imports[uri][:contents] return unless contents options[:syntax] = @imports[uri][:syntax] options[:filename] = uri options[:importer] = self @imports[uri][:engine] = Sass::Engine.new(contents, options) end def mtime(uri, options) @imports[uri][:mtime] end def key(uri, options) ["mock", uri] end def to_s @name end # Methods for testing def add_import(uri, contents, syntax = :scss, mtime = Time.now - 10) @imports[uri] = { :contents => contents, :mtime => mtime, :syntax => syntax } end def touch(uri) @imports[uri][:mtime] = Time.now end def engine(uri) @imports[uri][:engine] end end ././@LongLink0000644000000000000000000000017012255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/less_conversion_test.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/sass/less0000775000175000017500000002415012206724733033656 0ustar jamespagejamespage#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../test_helper' begin require 'sass/less' class LessConversionTest < Test::Unit::TestCase def test_variable_declarations assert_renders < .bar { a: b; } SCSS .foo > .bar {a: b} LESS end def test_adjacent_selector assert_renders < bar { a: b; } + baz { c: d; } } SCSS foo { > bar {a: b} + baz {c: d} } LESS end def test_nested_pseudo_rules assert_renders < .bar" with "@extend .bar" WARN .foo > .bar { a: b; } .bar { // > .bar; @extend .bar; } SCSS .foo > .bar {a: b} .bar {> .bar;} LESS end # Accessors def test_property_accessor assert_warning(< e unless defined?(Gem) begin require 'rubygems' retry rescue Exception end end puts "\nCouldn't require less, skipping some tests." end ././@LongLink0000644000000000000000000000015212255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/test_helper.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/test/test_help0000664000175000017500000000316112206724733033722 0ustar jamespagejamespagelib_dir = File.dirname(__FILE__) + '/../lib' require 'test/unit' require 'fileutils' $:.unshift lib_dir unless $:.include?(lib_dir) require 'sass' Sass::RAILS_LOADED = true unless defined?(Sass::RAILS_LOADED) module Sass::Script::Functions def option(name) Sass::Script::String.new(@options[name.value.to_sym].to_s) end end class Test::Unit::TestCase def munge_filename(opts = {}) return if opts.has_key?(:filename) opts[:filename] = filename_for_test(opts[:syntax] || :sass) end def filename_for_test(syntax = :sass) test_name = caller. map {|c| Sass::Util.caller_info(c)[2]}. compact. map {|c| c.sub(/^(block|rescue) in /, '')}. find {|c| c =~ /^test_/} "#{test_name}_inline.#{syntax}" end def clean_up_sassc path = File.dirname(__FILE__) + "/../.sass-cache" FileUtils.rm_r(path) if File.exist?(path) end def assert_warning(message) the_real_stderr, $stderr = $stderr, StringIO.new yield if message.is_a?(Regexp) assert_match message, $stderr.string.strip else assert_equal message.strip, $stderr.string.strip end ensure $stderr = the_real_stderr end def silence_warnings(&block) Sass::Util.silence_warnings(&block) end def assert_raise_message(klass, message) yield rescue Exception => e assert_instance_of(klass, e) assert_equal(message, e.message) else flunk "Expected exception #{klass}, none raised" end def assert_raise_line(line) yield rescue Sass::SyntaxError => e assert_equal(line, e.sass_line) else flunk "Expected exception on line #{line}, none raised" end end stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/doc-src/0000775000175000017500000000000012206724733032362 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016012255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/doc-src/SASS_CHANGELOG.mdstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/doc-src/SASS_C0000664000175000017500000021350212206724733033323 0ustar jamespagejamespage# Sass Changelog * Table of contents {:toc} ## 3.1.0 (Unreleased) * Add an {Sass::Script::Functions#invert `invert` function} that takes the inverse of colors. * A new sass function called `if` can be used to emit one of two values based on the truth value of the first argument. For example, `if(true, 1px, 2px)` returns `1px` and `if(false, 1px, 2px)` returns `2px`. * Compass users can now use the `--compass` flag to make the Compass libraries available for import. This will also load the Compass project configuration if run from the project root. * Many performance optimizations have been made by [thedarkone](http://github.com/thedarkone). * Allow selectors to contain extra commas to make them easier to modify. Extra commas will be removed when the selectors are converted to CSS. * `@import` may now be used within CSS or `@media` rules. The imported file will be treated as though it were nested within the rule. Files with mixins may not be imported in nested contexts. * If a comment starts with `!`, that comment will now be interpolated (`#{...}` will be replaced with the resulting value of the expression inside) and the comment will always be printed out in the generated CSS file -- even with compressed output. This is useful for adding copyright notices to your stylesheets. * A new executable named `scss` is now available. It is exactly like the `sass` executable except it defaults to assuming input is in the SCSS syntax. Both programs will use the source file's extension to determine the syntax where possible. ### Sass-based Functions While it has always been possible to add functions to Sass with Ruby, this release adds the ability to define new functions within Sass files directly. For example: $grid-width: 40px; $gutter-width: 10px; @function grid-width($n) { @return $n * $grid-width + ($n - 1) * $gutter-width; } #sidebar { width: grid-width(5); } Becomes: #sidebar { width: 240px; } ### Keyword Arguments Both mixins and Sass functions now support the ability to pass in keyword arguments. For example, with mixins: @mixin border-radius($value, $moz: true, $webkit: true, $css3: true) { @if $moz { -moz-border-radius: $value } @if $webkit { -webkit-border-radius: $value } @if $css3 { border-radius: $value } } @include border-radius(10px, $webkit: false); And with functions: p { color: hsl($hue: 180, $saturation: 78%, $lightness: 57%); } Keyword arguments are of the form `$name: value` and come after normal arguments. They can be used for either optional or required arguments. For mixins, the names are the same as the argument names for the mixins. For functions, the names are defined along with the functions. The argument names for the built-in functions are listed {Sass::Script::Functions in the function documentation}. Sass functions defined in Ruby can use the {Sass::Script::Functions.declare} method to declare the names of the arguments they take. #### New Keyword Functions The new keyword argument functionality enables new Sass color functions that use keywords to encompass a large amount of functionality in one function. * The {Sass::Script::Functions#adjust_color adjust-color} function works like the old `lighten`, `saturate`, and `adjust-hue` methods. It increases and/or decreases the values of a color's properties by fixed amounts. For example, `adjust-color($color, $lightness: 10%)` is the same as `lighten($color, 10%)`: it returns `$color` with its lightness increased by 10%. * The {Sass::Script::Functions#scale_color scale_color} function is similar to {Sass::Script::Functions#adjust adjust}, but instead of increasing and/or decreasing a color's properties by fixed amounts, it scales them fluidly by percentages. The closer the percentage is to 100% (or -100%), the closer the new property value will be to its maximum (or minimum). For example, `scale-color(hsl(120, 70, 80), $lightness: 50%)` will change the lightness from 80% to 90%, because 90% is halfway between 80% and 100%. Similarly, `scale-color(hsl(120, 70, 50), $lightness: 50%)` will change the lightness from 50% to 75%. * The {Sass::Script::Functions#change_color change-color} function simply changes a color's properties regardless of their old values. For example `change-color($color, $lightness: 10%)` returns `$color` with 10% lightness, and `change-color($color, $alpha: 0.7)` returns color with opacity 0.7. Each keyword function accepts `$hue`, `$saturation`, `$value`, `$red`, `$green`, `$blue`, and `$alpha` keywords, with the exception of `scale-color()` which doesn't accept `$hue`. These keywords modify the respective properties of the given color. Each keyword function can modify multiple properties at once. For example, `adjust-color($color, $lightness: 15%, $saturation: -10%)` both lightens and desaturates `$color`. HSL properties cannot be modified at the same time as RGB properties, though. ### Lists Lists are now a first-class data type in Sass, alongside strings, numbers, colors, and booleans. They can be assigned to variables, passed to mixins, and used in CSS declarations. Just like the other data types (except booleans), Sass lists look just like their CSS counterparts. They can be separated either by spaces (e.g. `1px 2px 0 10px`) or by commas (e.g. `Helvetica, Arial, sans-serif`). In addition, individual values count as single-item lists. Lists won't behave any differently in Sass 3.1 than they did in 3.0. However, you can now do more with them using the new {file:Sass/Script/Functions.html#list-functions list functions}: * The {Sass::Script::Functions#nth `nth($list, $n)` function} returns the nth item in a list. For example, `nth(1px 2px 10px, 2)` returns the second item, `2px`. Note that lists in Sass start at 1, not at 0 like they do in some other languages. * The {Sass::Script::Functions#join `join($list1, $list2)` function} joins together two lists into one. For example, `join(1px 2px, 10px 5px)` returns `1px 2px 10px 5px`. * The {Sass::Script::Functions#append `append($list, $val)` function} appends values to the end of a list. For example, `append(1px 2px, 10px)` returns `1px 2px 10px`. * The {Sass::Script::Functions#join `length($list)` function} returns the length of a list. For example, `length(1px 2px 10px 5px)` returns `4`. For more details about lists see {file:SASS_REFERENCE.md#lists the reference}. #### `@each` There's also a new directive that makes use of lists. The {file:SASS_REFERENCE.md#each-directive `@each` directive} assigns a variable to each item in a list in turn, like `@for` does for numbers. This is useful for writing a bunch of similar styles without having to go to the trouble of creating a mixin. For example: @each $animal in puma, sea-slug, egret, salamander { .#{$animal}-icon { background-image: url('/images/#{$animal}.png'); } } is compiled to: .puma-icon { background-image: url('/images/puma.png'); } .sea-slug-icon { background-image: url('/images/sea-slug.png'); } .egret-icon { background-image: url('/images/egret.png'); } .salamander-icon { background-image: url('/images/salamander.png'); } ### `@media` Bubbling Modern stylesheets often use `@media` rules to target styles at certain sorts of devices, screen resolutions, or even orientations. They're also useful for print and aural styling. Unfortunately, it's annoying and repetitive to break the flow of a stylesheet and add a `@media` rule containing selectors you've already written just to tweak the style a little. Thus, Sass 3.1 now allows you to nest `@media` rules within selectors. It will automatically bubble them up to the top level, putting all the selectors on the way inside the rule. For example: .sidebar { width: 300px; @media screen and (orientation: landscape) { width: 500px; } } is compiled to: .sidebar { width: 300px; } @media screen and (orientation: landscape) { .sidebar { width: 500px; } } You can also nest `@media` directives within one another. The queries will then be combined using the `and` operator. For example: @media screen { .sidebar { @media (orientation: landscape) { width: 500px; } } } is compiled to: @media screen and (orientation: landscape) { .sidebar { width: 500px; } } ### Nested `@import` The `@import` statement can now be nested within other structures such as CSS rules and `@media` rules. For example: @media print { @import "print"; } This imports `print.scss` and places all rules so imported within the `@media print` block. This makes it easier to create stylesheets for specific media or sections of the document and distributing those stylesheets across multiple files. ### Backwards Incompatibilities -- Must Read! * When `@import` is given a path without `.sass`, `.scss`, or `.css` extension, and no file exists at that path, it will now throw an error. The old behavior of becoming a plain-CSS `@import` was deprecated and has now been removed. * Get rid of the `--rails` flag for the `sass` executable. This flag hasn't been necessary since Rails 2.0. Existing Rails 2.0 installations will continue to work. * Removed deprecated support for ! prefixed variables. Use $ to prefix variables now. * Removed the deprecated css2sass executable. Use sass-convert now. * Removed support for the equals operator in variable assignment. Use : now. * Removed the sass2 mode from sass-convert. Users who have to migrate from sass2 should install Sass 3.0 and quiet all deprecation warnings before installing Sass 3.1. ### Sass Internals * It is now possible to define a custom importer that can be used to find imports using different import semantics than the default filesystem importer that Sass provides. For instance, you can use this to generate imports on the fly, look them up from a database, or implement different file naming conventions. See the {Sass::Importers::Base Importer Base class} for more information. * It is now possible to define a custom cache store to allow for efficient caching of Sass files using alternative cache stores like memcached in environments where a writable filesystem is not available or where the cache need to be shared across many servers for dynamically generated stylesheet environments. See the {Sass::CacheStores::Base CacheStore Base class} for more information. ## 3.0.26 (Unreleased) * Fix a performance bug in large SCSS stylesheets with many nested selectors. This should dramatically decrease compilation time of such stylesheets. * Upgrade the bundled FSSM to version 0.2.3. This means `sass --watch` will work out of the box with Rubinius. ## 3.0.25 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.25). * When displaying a Sass error in an imported stylesheet, use the imported stylesheet's contents rather than the top-level stylesheet. * Fix a bug that caused some lines with non-ASCII characters to be ignored in Ruby 1.8. * Fix a bug where boolean operators (`and`, `or`, and `not`) wouldn't work at the end of a line in a multiline SassScript expression. * When using `sass --update`, only update individual files when they've changed. ## 3.0.24 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.24). * Raise an error when `@else` appears without an `@if` in SCSS. * Fix some cases where `@if` rules were causing the line numbers in error reports to become incorrect. ## 3.0.23 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.23). * Fix the error message for unloadable modules when running the executables under Ruby 1.9.2. ### `@charset` Change The behavior of `@charset` has changed in version 3.0.23 in order to work around a bug in Safari, where `@charset` declarations placed anywhere other than the beginning of the document cause some CSS rules to be ignored. This change also makes `@charset`s in imported files behave in a more useful way. #### Ruby 1.9 When using Ruby 1.9, which keeps track of the character encoding of the Sass document internally, `@charset` directive in the Sass stylesheet and any stylesheets it imports are no longer directly output to the generated CSS. They're still used for determining the encoding of the input and output stylesheets, but they aren't rendered in the same way other directives are. Instead, Sass adds a single `@charset` directive at the beginning of the output stylesheet if necessary, whether or not the input stylesheet had a `@charset` directive. It will add this directive if and only if the output stylesheet contains non-ASCII characters. By default, the declared charset will be UTF-8, but if the Sass stylesheet declares a different charset then that will be used instead if possible. One important consequence of this scheme is that it's possible for a Sass file to import partials with different encodings (e.g. one encoded as UTF-8 and one as IBM866). The output will then be UTF-8, unless the importing stylesheet declares a different charset. #### Ruby 1.8 Ruby 1.8 doesn't have good support for encodings, so it uses a simpler but less accurate scheme for figuring out what `@charset` declaration to use for the output stylesheet. It just takes the first `@charset` declaration to appear in the stylesheet or any of its imports and moves it to the beginning of the document. This means that under Ruby 1.8 it's *not* safe to import files with different encodings. ## 3.0.22 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.22). * Remove `vendor/sass`, which snuck into the gem by mistake and was causing trouble for Heroku users (thanks to [Jacques Crocker](http://railsjedi.com/)). * `sass-convert` now understands better when it's acceptable to remove parentheses from expressions. ## 3.0.21 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.21). * Fix the permissions errors for good. * Fix more `#options` attribute errors. ## 3.0.20 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.20). * Fix some permissions errors. * Fix `#options` attribute errors when CSS functions were used with commas. ## 3.0.19 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.19). * Make the alpha value for `rgba` colors respect {Sass::Script::Number::PRECISION}. * Remove all newlines in selectors in `:compressed` mode. * Make color names case-insensitive. * Properly detect SCSS files when using `sass -c`. * Remove spaces after commas in `:compressed` mode. * Allow the `--unix-newlines` flag to work on Unix, where it's a no-op. ## 3.0.18 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.18). * Don't require `rake` in the gemspec, for bundler compatibility under JRuby. Thanks to [Gordon McCreight](http://www.gmccreight.com/blog). * Add a command-line option `--stop-on-error` that causes Sass to exit when a file fails to compile using `--watch` or `--update`. * Fix a bug in `haml_tag` that would allow duplicate attributes to be added and make `data-` attributes not work. * Get rid of the annoying RDoc errors on install. * Disambiguate references to the `Rails` module when `haml-rails` is installed. * Allow `@import` in SCSS to import multiple files in the same `@import` rule. ## 3.0.17 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.17). * Disallow `#{}` interpolation in `@media` queries or unrecognized directives. This was never allowed, but now it explicitly throws an error rather than just producing invalid CSS. * Make `sass --watch` not throw an error when passed a single file or directory. * Understand that mingw counts as Windows. * Make `sass --update` return a non-0 exit code if one or more files being updated contained an error. ## 3.0.16 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.16). * Fix a bug where certain sorts of comments would get improperly rendered in the `:compact` style. * Always allow a trailing `*/` in loud comments in the indented syntax. * Fix a performance issue with SCSS parsing in rare cases. Thanks to [Chris Eppstein](http://chriseppstein.github.com). * Use better heuristics for figuring out when someone might be using the wrong syntax with `sass --watch`. ## 3.0.15 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.15). * Fix a bug where `sass --watch` and `sass --update` were completely broken. * Allow `@import`ed values to contain commas. ## 3.0.14 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.14). * Properly parse paths with drive letters on Windows (e.g. `C:\Foo\Bar.sass`) in the Sass executable. * Compile Sass files in a deterministic order. * Fix a bug where comments after `@if` statements in SCSS weren't getting passed through to the output document. ## 3.0.13 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.13). ## CSS `@import` Directives Sass is now more intelligent about when to compile `@import` directives to plain CSS. Any of the following conditions will cause a literal CSS `@import`: * Importing a path with a `.css` extension (e.g. `@import "foo.css"`). * Importing a path with a media type (e.g. `@import "foo" screen;`). * Importing an HTTP path (e.g. `@import "http://foo.com/style.css"`). * Importing any URL (e.g. `@import url(foo)`). The former two conditions always worked, but the latter two are new. ## `-moz-calc` Support The new [`-moz-calc()` function](http://hacks.mozilla.org/2010/06/css3-calc/) in Firefox 4 will now be properly parsed by Sass. `calc()` was already supported, but because the parsing rules are different than for normal CSS functions, this had to be expanded to include `-moz-calc`. In anticipation of wider browser support, in fact, *any* function named `-*-calc` (such as `-webkit-calc` or `-ms-calc`) will be parsed the same as the `calc` function. ## `:-moz-any` Support The [`:-moz-any` pseudoclass selector](http://hacks.mozilla.org/2010/05/moz-any-selector-grouping/) is now parsed by Sass. ## `--require` Flag The Sass command-line executable can now require Ruby files using the `--require` flag (or `-r` for short). ## Rails Support Make sure the default Rails options take precedence over the default non-Rails options. This makes `./script/server --daemon` work again. ### Rails 3 Support Support for Rails 3 versions prior to beta 4 has been removed. Upgrade to Rails 3.0.0.beta4 if you haven't already. ## 3.0.12 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.12). ## Rails 3 Support Apparently the last version broke in new and exciting ways under Rails 3, due to the inconsistent load order caused by certain combinations of gems. 3.0.12 hacks around that inconsistency, and *should* be fully Rails 3-compatible. ### Deprecated: Rails 3 Beta 3 Haml's support for Rails 3.0.0.beta.3 has been deprecated. Haml 3.0.13 will only support 3.0.0.beta.4. ## 3.0.11 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.11). There were no changes made to Haml between versions 3.0.10 and 3.0.11. ## Rails 3 Support Make sure Sass *actually* regenerates stylesheets under Rails 3. The fix in 3.0.10 didn't work because the Rack stack we were modifying wasn't reloaded at the proper time. ## Bug Fixes * Give a decent error message when `--recursive` is used in `sass-convert` without a directory. ## 3.0.10 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.10). ### Appengine-JRuby Support The way we determine the location of the Haml installation no longer breaks the version of JRuby used by [`appengine-jruby`](http://code.google.com/p/appengine-jruby/). ### Rails 3 Support Sass will regenerate stylesheets under Rails 3 even when no controllers are being accessed. ### Other Improvements * When using `sass-convert --from sass2 --to sass --recursive`, suggest the use of `--in-place` as well. ## 3.0.9 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.9). There were no changes made to Sass between versions 3.0.8 and 3.0.9. A bug in Gemcutter caused the gem to be uploaded improperly. ## 3.0.8 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.8). * Fix a bug with Rails versions prior to Rails 3. ## 3.0.7 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.7). ### Encoding Support Sass 3.0.7 adds support for `@charset` for declaring the encoding of a stylesheet. For details see {file:SASS_REFERENCE.md#encodings the reference}. The `sass` and `sass-convert` executables also now take an `-E` option for specifying the encoding of Sass/SCSS/CSS files. ### Bug Fixes * When compiling a file named `.sass` but with SCSS syntax specified, use the latter (and vice versa). * Fix a bug where interpolation would cause some selectors to render improperly. * If a line in a Sass comment starts with `*foo`, render it as `*foo` rather than `* *foo`. ## 3.0.6 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.6). There were no changes made to Sass between versions 3.0.5 and 3.0.6. ## 3.0.5 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.5). ### `#{}` Interpolation in Properties Previously, using `#{}` in some places in properties would cause a syntax error. Now it can be used just about anywhere. Note that when `#{}` is used near operators like `/`, those operators are treated as plain CSS rather than math operators. For example: p { $font-size: 12px; $line-height: 30px; font: #{$font-size}/#{$line-height}; } is compiled to: p { font: 12px/30px; } This is useful, since normally {file:SASS_REFERENCE.md#division-and-slash a slash with variables is treated as division}. ### Recursive Mixins Mixins that include themselves will now print much more informative error messages. For example: @mixin foo {@include bar} @mixin bar {@include foo} @include foo will print: An @include loop has been found: foo includes bar bar includes foo Although it was previously possible to use recursive mixins without causing infinite looping, this is now disallowed, since there's no good reason to do it. ### Rails 3 Support Fix Sass configuration under Rails 3. Thanks [Dan Cheail](http://github.com/codeape). ### `sass --no-cache` Make the `--no-cache` flag properly forbid Sass from writing `.sass-cache` files. ## 3.0.4 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.4). * Raise an informative error when function arguments have a mispaced comma, as in `foo(bar, )`. * Fix a performance problem when using long function names such as `-moz-linear-gradient`. ## 3.0.3 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.3). ### Rails 3 Support Make sure Sass is loaded properly when using Rails 3 along with non-Rails-3-compatible plugins like some versions of `will_paginate`. Also, In order to make some Rails loading errors like the above easier to debug, Sass will now raise an error if `Rails.root` is `nil` when Sass is loading. Previously, this would just cause the paths to be mis-set. ### Merb Support Merb, including 1.1.0 as well as earlier versions, should *really* work with this release. ### Bug Fixes * Raise an informative error when mixin arguments have a mispaced comma, as in `@include foo(bar, )`. * Make sure SassScript subtraction happens even when nothing else dynamic is going on. * Raise an error when colors are used with the wrong number of digits. ## 3.0.2 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.2). ### Merb 1.1.0 Support Fixed a bug inserting the Sass plugin into the Merb 1.1.0 Rack application. ### Bug Fixes * Allow identifiers to begin with multiple underscores. * Don't raise an error when using `haml --rails` with older Rails versions. ## 3.0.1 [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.1). ### Installation in Rails `haml --rails` is no longer necessary for installing Sass in Rails. Now all you need to do is add `gem "haml"` to the Gemfile for Rails 3, or add `config.gem "haml"` to `config/environment.rb` for previous versions. `haml --rails` will still work, but it has been deprecated and will print an error message. It will not work in the next version of Sass. ### Rails 3 Beta Integration * Make sure manually importing the Sass Rack plugin still works with Rails, even though it's not necessary now. * Allow Sass to be configured in Rails even when it's being lazy-loaded. ### `:template_location` Methods The {file:SASS_REFERENCE.md#template_location-option `:template_location` option} can be either a String, a Hash, or an Array. This makes it difficult to modify or use with confidence. Thus, three new methods have been added for handling it: * {Sass::Plugin::Configuration#template_location_array Sass::Plugin#template_location_array} -- Returns the template locations and CSS locations formatted as an array. * {Sass::Plugin::Configuration#add_template_location Sass::Plugin#add_template_location} -- Converts the template location option to an array and adds a new location. * {Sass::Plugin::Configuration#remove_template_location Sass::Plugin#remove_template_location} -- Converts the template location option to an array and removes an existing location. ## 3.0.0 {#3-0-0} [Tagged on GitHub](http://github.com/nex3/haml/commit/3.0.0). ### Deprecations -- Must Read! {#3-0-0-deprecations} * Using `=` for SassScript properties and variables is deprecated, and will be removed in Sass 3.2. Use `:` instead. See also [this changelog entry](#3-0-0-sass-script-context) * Because of the above, property values using `:` will be parsed more thoroughly than they were before. Although all valid CSS3 properties as well as most hacks and proprietary syntax should be supported, it's possible that some properties will break. If this happens, please report it to [the Sass mailing list](http://groups.google.com/group/haml). * In addition, setting the default value of variables with `||=` is now deprecated and will be removed in Sass 3.2. Instead, add `!default` to the end of the value. See also [this changelog entry](#3-0-0-default-flag) * The `!` prefix for variables is deprecated, and will be removed in Sass 3.2. Use `$` as a prefix instead. See also [this changelog entry](#3-0-0-dollar-prefix). * The `css2sass` command-line tool has been deprecated, and will be removed in Sass 3.2. Use the new `sass-convert` tool instead. See also [this changelog entry](#3-0-0-sass-convert). * Selector parent references using `&` can now only be used where element names are valid. This is because Sass 3 fully parses selectors to support the new [`@extend` directive](#3-0-0-extend), and it's possible that the `&` could be replaced by an element name. ### SCSS (Sassy CSS) Sass 3 introduces a new syntax known as SCSS which is fully compatible with the syntax of CSS3, while still supporting the full power of Sass. This means that every valid CSS3 stylesheet is a valid SCSS file with the same meaning. In addition, SCSS understands most CSS hacks and vendor-specific syntax, such as [IE's old `filter` syntax](http://msdn.microsoft.com/en-us/library/ms533754%28VS.85%29.aspx). SCSS files use the `.scss` extension. They can import `.sass` files, and vice-versa. Their syntax is fully described in the {file:SASS_REFERENCE.md Sass reference}; if you're already familiar with Sass, though, you may prefer the {file:SCSS_FOR_SASS_USERS.md intro to SCSS for Sass users}. Since SCSS is a much more approachable syntax for those new to Sass, it will be used as the default syntax for the reference, as well as for most other Sass documentation. The indented syntax will continue to be fully supported, however. Sass files can be converted to SCSS using the new `sass-convert` command-line tool. For example: # Convert a Sass file to SCSS $ sass-convert style.sass style.scss **Note that if you're converting a Sass file written for Sass 2**, you should use the `--from sass2` flag. For example: # Convert a Sass file to SCSS $ sass-convert --from sass2 style.sass style.scss # Convert all Sass files to SCSS $ sass-convert --recursive --in-place --from sass2 --to scss stylesheets/ ### Syntax Changes {#3-0-0-syntax-changes} #### SassScript Context {#3-0-0-sass-script-context} The `=` character is no longer required for properties that use SassScript (that is, variables and operations). All properties now use SassScript automatically; this means that `:` should be used instead. Variables should also be set with `:`. For example, what used to be // Indented syntax .page color = 5px + 9px should now be // Indented syntax .page color: 5px + 9px This means that SassScript is now an extension of the CSS3 property syntax. All valid CSS3 properties are valid SassScript, and will compile without modification (some invalid properties work as well, such as Microsoft's proprietary `filter` syntax). This entails a few changes to SassScript to make it fully CSS3-compatible, which are detailed below. This also means that Sass will now be fully parsing all property values, rather than passing them through unchanged to the CSS. Although care has been taken to support all valid CSS3, as well as hacks and proprietary syntax, it's possible that a property that worked in Sass 2 won't work in Sass 3. If this happens, please report it to [the Sass mailing list](http://groups.google.com/group/haml). Note that if `=` is used, SassScript will be interpreted as backwards-compatibly as posssible. In particular, the changes listed below don't apply in an `=` context. The `sass-convert` command-line tool can be used to upgrade Sass files to the new syntax using the `--in-place` flag. For example: # Upgrade style.sass: $ sass-convert --in-place style.sass # Upgrade all Sass files: $ sass-convert --recursive --in-place --from sass2 --to sass stylesheets/ ##### Quoted Strings Quoted strings (e.g. `"foo"`) in SassScript now render with quotes. In addition, unquoted strings are no longer deprecated, and render without quotes. This means that almost all strings that had quotes in Sass 2 should not have quotes in Sass 3. Although quoted strings render with quotes when used with `:`, they do not render with quotes when used with `#{}`. This allows quoted strings to be used for e.g. selectors that are passed to mixins. Strings can be forced to be quoted and unquoted using the new \{Sass::Script::Functions#unquote unquote} and \{Sass::Script::Functions#quote quote} functions. ##### Division and `/` Two numbers separated by a `/` character are allowed as property syntax in CSS, e.g. for the `font` property. SassScript also uses `/` for division, however, which means it must decide what to do when it encounters numbers separated by `/`. For CSS compatibility, SassScript does not perform division by default. However, division will be done in almost all cases where division is intended. In particular, SassScript will perform division in the following three situations: 1. If the value, or any part of it, is stored in a variable. 2. If the value is surrounded by parentheses. 3. If the value is used as part of another arithmetic expression. For example: p font: 10px/8px $width: 1000px width: $width/2 height: (500px/2) margin-left: 5px + 8px/2px is compiled to: p { font: 10px/8px; width: 500px; height: 250px; margin-left: 9px; } ##### Variable Defaults Since `=` is no longer used for variable assignment, assigning defaults to variables with `||=` no longer makes sense. Instead, the `!default` flag should be added to the end of the variable value. This syntax is meant to be similar to CSS's `!important` flag. For example: $var: 12px !default; #### Variable Prefix Character {#3-0-0-dollar-prefix} The Sass variable character has been changed from `!` to the more aesthetically-appealing `$`. For example, what used to be !width = 13px .icon width = !width should now be $width: 13px .icon width: $width The `sass-convert` command-line tool can be used to upgrade Sass files to the new syntax using the `--in-place` flag. For example: # Upgrade style.sass: $ sass-convert --in-place style.sass # Upgrade all Sass files: $ sass-convert --recursive --in-place --from sass2 --to sass stylesheets/ `!` may still be used, but it's deprecated and will print a warning. It will be removed in the next version of Sass, 3.2. #### Variable and Mixin Names SassScript variable and mixin names may now contain hyphens. In fact, they may be any valid CSS3 identifier. For example: $prettiest-color: #542FA9 =pretty-text color: $prettiest-color In order to allow frameworks like [Compass](http://compass-style.org) to use hyphens in variable names while maintaining backwards-compatibility, variables and mixins using hyphens may be referred to with underscores, and vice versa. For example: $prettiest-color: #542FA9 .pretty // Using an underscore instead of a hyphen works color: $prettiest_color #### Single-Quoted Strings SassScript now supports single-quoted strings. They behave identically to double-quoted strings, except that single quotes need to be backslash-escaped and double quotes do not. #### Mixin Definition and Inclusion Sass now supports the `@mixin` directive as a way of defining mixins (like `=`), as well as the `@include` directive as a way of including them (like `+`). The old syntax is *not* deprecated, and the two are fully compatible. For example: @mixin pretty-text color: $prettiest-color a @include pretty-text is the same as: =pretty-text color: $prettiest-color a +pretty-text #### Sass Properties New-style properties (with the colon after the name) in indented syntax now allow whitespace before the colon. For example: foo color : blue #### Sass `@import` The Sass `@import` statement now allows non-CSS files to be specified with quotes, for similarity with the SCSS syntax. For example, `@import "foo.sass"` will now import the `foo.sass` file, rather than compiling to `@import "foo.sass";`. ### `@extend` {#3-0-0-extend} There are often cases when designing a page when one class should have all the styles of another class, as well as its own specific styles. The most common way of handling this is to use both the more general class and the more specific class in the HTML. For example, suppose we have a design for a normal error and also for a serious error. We might write our markup like so:
    Oh no! You've been hacked!
    And our styles like so: .error { border: 1px #f00; background-color: #fdd; } .seriousError { border-width: 3px; } Unfortunately, this means that we have to always remember to use `.error` with `.seriousError`. This is a maintenance burden, leads to tricky bugs, and can bring non-semantic style concerns into the markup. The `@extend` directive avoids these problems by telling Sass that one selector should inherit the styles of another selector. For example: .error { border: 1px #f00; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; } This means that all styles defined for `.error` are also applied to `.seriousError`, in addition to the styles specific to `.seriousError`. In effect, everything with class `.seriousError` also has class `.error`. Other rules that use `.error` will work for `.seriousError` as well. For example, if we have special styles for errors caused by hackers: .error.intrusion { background-image: url("/image/hacked.png"); } Then `
    ` will have the `hacked.png` background image as well. #### How it Works `@extend` works by inserting the extending selector (e.g. `.seriousError`) anywhere in the stylesheet that the extended selector (.e.g `.error`) appears. Thus the example above: .error { border: 1px #f00; background-color: #fdd; } .error.intrusion { background-image: url("/image/hacked.png"); } .seriousError { @extend .error; border-width: 3px; } is compiled to: .error, .seriousError { border: 1px #f00; background-color: #fdd; } .error.intrusion, .seriousError.intrusion { background-image: url("/image/hacked.png"); } .seriousError { border-width: 3px; } When merging selectors, `@extend` is smart enough to avoid unnecessary duplication, so something like `.seriousError.seriousError` gets translated to `.seriousError`. In addition, it won't produce selectors that can't match anything, like `#main#footer`. See also {file:SASS_REFERENCE.md#extend the `@extend` reference documentation}. ### Colors SassScript color values are much more powerful than they were before. Support was added for alpha channels, and most of Chris Eppstein's [compass-colors](http://chriseppstein.github.com/compass-colors) plugin was merged in, providing color-theoretic functions for modifying colors. One of the most interesting of these functions is {Sass::Script::Functions#mix mix}, which mixes two colors together. This provides a much better way of combining colors and creating themes than standard color arithmetic. #### Alpha Channels Sass now supports colors with alpha channels, constructed via the {Sass::Script::Functions#rgba rgba} and {Sass::Script::Functions#hsla hsla} functions. Alpha channels are unaffected by color arithmetic. However, the {Sass::Script::Functions#opacify opacify} and {Sass::Script::Functions#transparentize transparentize} functions allow colors to be made more and less opaque, respectively. Sass now also supports functions that return the values of the {Sass::Script::Functions#red red}, {Sass::Script::Functions#blue blue}, {Sass::Script::Functions#green green}, and {Sass::Script::Functions#alpha alpha} components of colors. #### HSL Colors Sass has many new functions for using the HSL values of colors. For an overview of HSL colors, check out [the CSS3 Spec](http://www.w3.org/TR/css3-color/#hsl-color). All these functions work just as well on RGB colors as on colors constructed with the {Sass::Script::Functions#hsl hsl} function. * The {Sass::Script::Functions#lighten lighten} and {Sass::Script::Functions#darken darken} functions adjust the lightness of a color. * The {Sass::Script::Functions#saturate saturate} and {Sass::Script::Functions#desaturate desaturate} functions adjust the saturation of a color. * The {Sass::Script::Functions#adjust_hue adjust-hue} function adjusts the hue of a color. * The {Sass::Script::Functions#hue hue}, {Sass::Script::Functions#saturation saturation}, and {Sass::Script::Functions#lightness lightness} functions return the corresponding HSL values of the color. * The {Sass::Script::Functions#grayscale grayscale} function converts a color to grayscale. * The {Sass::Script::Functions#complement complement} function returns the complement of a color. ### Other New Functions Several other new functions were added to make it easier to have more flexible arguments to mixins and to enable deprecation of obsolete APIs. * {Sass::Script::Functions#type_of `type-of`} -- Returns the type of a value. * {Sass::Script::Functions#unit `unit`} -- Returns the units associated with a number. * {Sass::Script::Functions#unitless `unitless`} -- Returns whether a number has units or not. * {Sass::Script::Functions#comparable `comparable`} -- Returns whether two numbers can be added or compared. ### Watching for Updates {#3-0-0-watch} The `sass` command-line utility has a new flag: `--watch`. `sass --watch` monitors files or directories for updated Sass files and compiles those files to CSS automatically. This will allow people not using Ruby or [Compass](http://compass-style.org) to use Sass without having to manually recompile all the time. Here's the syntax for watching a directory full of Sass files: sass --watch app/stylesheets:public/stylesheets This will watch every Sass file in `app/stylesheets`. Whenever one of them changes, the corresponding CSS file in `public/stylesheets` will be regenerated. Any files that import that file will be regenerated, too. The syntax for watching individual files is the same: sass --watch style.sass:out.css You can also omit the output filename if you just want it to compile to name.css. For example: sass --watch style.sass This will update `style.css` whenever `style.sass` changes. You can list more than one file and/or directory, and all of them will be watched: sass --watch foo/style:public/foo bar/style:public/bar sass --watch screen.sass print.sass awful-hacks.sass:ie.css sass --watch app/stylesheets:public/stylesheets public/stylesheets/test.sass File and directory watching is accessible from Ruby, using the {Sass::Plugin::Compiler#watch Sass::Plugin#watch} function. #### Bulk Updating Another new flag for the `sass` command-line utility is `--update`. It checks a group of Sass files to see if their CSS needs to be updated, and updates if so. The syntax for `--update` is just like watch: sass --update app/stylesheets:public/stylesheets sass --update style.sass:out.css sass --watch screen.sass print.sass awful-hacks.sass:ie.css In fact, `--update` work exactly the same as `--watch`, except that it doesn't continue watching the files after the first check. ### `sass-convert` (née `css2sass`) {#3-0-0-sass-convert} The `sass-convert` tool, which used to be known as `css2sass`, has been greatly improved in various ways. It now uses a full-fledged CSS3 parser, so it should be able to handle any valid CSS3, as well as most hacks and proprietary syntax. `sass-convert` can now convert between Sass and SCSS. This is normally inferred from the filename, but it can also be specified using the `--from` and `--to` flags. For example: $ generate-sass | sass-convert --from sass --to scss | consume-scss It's also now possible to convert a file in-place -- that is, overwrite the old file with the new file. This is useful for converting files in the [Sass 2 syntax](#3-0-0-deprecations) to the new Sass 3 syntax, e.g. by doing `sass-convert --in-place --from sass2 style.sass`. #### `--recursive` The `--recursive` option allows `sass-convert` to convert an entire directory of files. `--recursive` requires both the `--from` and `--to` flags to be specified. For example: # Convert all .sass files in stylesheets/ to SCSS. # "sass2" means that these files are assumed to use the Sass 2 syntax. $ sass-convert --recursive --from sass2 --to scss stylesheets/ #### `--dasherize` The `--dasherize` options converts all underscores to hyphens, which are now allowed as part of identifiers in Sass. Note that since underscores may still be used in place of hyphens when referring to mixins and variables, this won't cause any backwards-incompatibilities. #### Convert Less to SCSS `sass-convert` can also convert [Less](http://lesscss.org) files to SCSS (or the indented syntax, although I anticipate less interest in that). For example: # Convert all .less files in the current directory into .scss files sass-convert --from less --to scss --recursive . This is done using the Less parser, so it requires that the `less` RubyGem be installed. ##### Incompatibilities Because of the reasonably substantial differences between Sass and Less, there are some things that can't be directly translated, and one feature that can't be translated at all. In the tests I've run on open-source Less stylesheets, none of these have presented issues, but it's good to be aware of them. First, Less doesn't distinguish fully between mixins and selector inheritance. In Less, all classes and some other selectors may be used as mixins, alongside more Sass-like mixins. If a class is being used as a mixin, it may also be used directly in the HTML, so it's not safe to translate it into a Sass mixin. What `sass-convert` does instead is leave the class in the stylesheet as a class, and use {file:SASS_REFERENCE.md#extend `@extend`} rather than {file:SASS_REFERENCE.md#including_a_mixin `@include`} to take on the styles of that class. Although `@extend` and mixins work quite differently, using `@extend` here doesn't actually seem to make a difference in practice. Another issue with Less mixins is that Less allows nested selectors (such as `.body .button` or `.colors > .teal`) to be used as a means of "namespacing" mixins. Sass's `@extend` doesn't work that way, so it does away with the namespacing and just extends the base class (so `.colors > .teal` becomes simply `@extend .teal`). In practice, this feature doesn't seem to be widely-used, but `sass-convert` will print a warning and leave a comment when it encounters it just in case. Finally, Less has the ability to directly access variables and property values defined in other selectors, which Sass does not support. Whenever such an accessor is used, `sass-convert` will print a warning and comment it out in the SCSS output. Like namespaced mixins, though, this does not seem to be a widely-used feature. ### `@warn` Directive A new directive `@warn` has been added that allows Sass libraries to emit warnings. This can be used to issue deprecation warnings, discourage sloppy use of mixins, etc. `@warn` takes a single argument: a SassScript expression that will be displayed on the console along with a stylesheet trace for locating the warning. For example: @mixin blue-text { @warn "The blue-text mixin is deprecated. Use new-blue-text instead."; color: #00f; } Warnings may be silenced with the new `--quiet` command line option, or the corresponding {file:SASS_REFERENCE.md#quiet-option `:quiey` Sass option}. This option will also affect warnings printed by Sass itself. Warnings are off by default in the Rails, Rack, and Merb production environments. ### Sass::Plugin API {Sass::Plugin} now has a large collection of callbacks that allow users to run code when various actions are performed. For example: Sass::Plugin.on_updating_stylesheet do |template, css| puts "#{template} has been compiled to #{css}!" end For a full list of callbacks and usage notes, see the {Sass::Plugin} documentation. {Sass::Plugin} also has a new method, {Sass::Plugin#force_update_stylesheets force_update_stylesheets}. This works just like {Sass::Plugin#update_stylesheets}, except that it doesn't check modification times and doesn't use the cache; all stylesheets are always compiled anew. ### Output Formatting Properties with a value and *also* nested properties are now rendered with the nested properties indented. For example: margin: auto top: 10px bottom: 20px is now compiled to: margin: auto; margin-top: 10px; margin-bottom: 20px; #### `:compressed` Style When the `:compressed` style is used, colors will be output as the minimal possible representation. This means whichever is smallest of the HTML4 color name and the hex representation (shortened to the three-letter version if possible). ### Stylesheet Updating Speed Several caching layers were added to Sass's stylesheet updater. This means that it should run significantly faster. This benefit will be seen by people using Sass in development mode with Rails, Rack, and Merb, as well as people using `sass --watch` from the command line, and to a lesser (but still significant) extent `sass --update`. Thanks to [thedarkone](http://github.com/thedarkone). ### Error Backtraces Numerous bugs were fixed with the backtraces given for Sass errors, especially when importing files and using mixins. All imports and mixins will now show up in the Ruby backtrace, with the proper filename and line number. In addition, when the `sass` executable encounters an error, it now prints the filename where the error occurs, as well as a backtrace of Sass imports and mixins. ### Ruby 1.9 Support * Sass and `css2sass` now produce more descriptive errors when given a template with invalid byte sequences for that template's encoding, including the line number and the offending character. * Sass and `css2sass` now accept Unicode documents with a [byte-order-mark](http://en.wikipedia.org/wiki/Byte_order_mark). ### Firebug Support A new {file:SASS_REFERENCE.md#debug_info-option `:debug_info` option} has been added that emits line-number and filename information to the CSS file in a browser-readable format. This can be used with the new [FireSass Firebug extension](https://addons.mozilla.org/en-US/firefox/addon/103988) to report the Sass filename and line number for generated CSS files. This is also available via the `--debug-info` command-line flag. ### Minor Improvements * If a CSS or Sass function is used that has the name of a color, it will now be parsed as a function rather than as a color. For example, `fuchsia(12)` now renders as `fuchsia(12)` rather than `fuchsia 12`, and `tealbang(12)` now renders as `tealbang(12)` rather than `teal bang(12)`. * The Sass Rails and Merb plugins now use Rack middleware by default. * Haml is now compatible with the [Rip](http://hellorip.com/) package management system. Thanks to [Josh Peek](http://joshpeek.com/). * Indented-syntax `/*` comments may now include `*` on lines beyond the first. * A {file:SASS_REFERENCE.md#read_cache-option `:read_cache`} option has been added to allow the Sass cache to be read from but not written to. * Stylesheets are no longer checked during each request when running tests in Rails. This should speed up some tests significantly. ## 2.2.24 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.24). * Parent references -- the `&` character -- may only be placed at the beginning of simple selector sequences in Sass 3. Placing them elsewhere is deprecated in 2.2.24 and will print a warning. For example, `foo &.bar` is allowed, but `foo .bar&` is not. ## 2.2.23 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.23). * Don't crash when `rake gems` is run in Rails with Sass installed. Thanks to [Florian Frank](http://github.com/flori). * When raising a file-not-found error, add a list of load paths that were checked. * If an import isn't found for a cached Sass file and the {file:SASS_REFERENCE.md#full_exception `:full_exception option`} is enabled, print the full exception rather than raising it. * Fix a bug with a weird interaction with Haml, DataMapper, and Rails 3 that caused some tag helpers to go into infinite recursion. ## 2.2.22 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.22). * Add a railtie so Haml and Sass will be automatically loaded in Rails 3. Thanks to [Daniel Neighman](http://pancakestacks.wordpress.com/). * Make loading the gemspec not crash on read-only filesystems like Heroku's. ## 2.2.21 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.21). * Fix a few bugs in the git-revision-reporting in {Sass::Version#version}. In particular, it will still work if `git gc` has been called recently, or if various files are missing. * Always use `__FILE__` when reading files within the Haml repo in the `Rakefile`. According to [this bug report](http://github.com/carlhuda/bundler/issues/issue/44), this should make Sass work better with Bundler. ## 2.2.20 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.20). * If the cache file for a given Sass file is corrupt because it doesn't have enough content, produce a warning and read the Sass file rather than letting the exception bubble up. This is consistent with other sorts of sassc corruption handling. * Calls to `defined?` shouldn't interfere with Rails' autoloading in very old versions (1.2.x). ## 2.2.19 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.18). There were no changes made to Sass between versions 2.2.18 and 2.2.19. ## 2.2.18 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.18). * Use `Rails.env` rather than `RAILS_ENV` when running under Rails 3.0. Thanks to [Duncan Grazier](http://duncangrazier.com/). * Support `:line_numbers` as an alias for {file:SASS_REFERENCE.md#line_numbers-option `:line_comments`}, since that's what the docs have said forever. Similarly, support `--line-numbers` as a command-line option. * Add a `--unix-newlines` flag to all executables for outputting Unix-style newlines on Windows. * Add a {file:SASS_REFERENCE.md#unix_newlines-option `:unix_newlines` option} for {Sass::Plugin} for outputting Unix-style newlines on Windows. * Fix the `--cache-location` flag, which was previously throwing errors. Thanks to [tav](http://tav.espians.com/). * Allow comments at the beginning of the document to have arbitrary indentation, just like comments elsewhere. Similarly, comment parsing is a little nicer than before. ## 2.2.17 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.16). * When the {file:SASS_REFERENCE.md#full_exception-option `:full_exception` option} is false, raise the error in Ruby code rather than swallowing it and printing something uninformative. * Fixed error-reporting when something goes wrong when loading Sass using the `sass` executable. This used to raise a NameError because `Sass::SyntaxError` wasn't defined. Now it'll raise the correct exception instead. * Report the filename in warnings about selectors without properties. * `nil` values for Sass options are now ignored, rather than raising errors. * Fix a bug that appears when Plugin template locations have multiple trailing slashes. Thanks to [Jared Grippe](http://jaredgrippe.com/). ### Must Read! * When `@import` is given a filename without an extension, the behavior of rendering a CSS `@import` if no Sass file is found is deprecated. In future versions, `@import foo` will either import the template or raise an error. ## 2.2.16 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.16). * Fixed a bug where modules containing user-defined Sass functions weren't made available when simply included in {Sass::Script::Functions} ({Sass::Script::Functions Functions} needed to be re-included in {Sass::Script::Functions::EvaluationContext Functions::EvaluationContext}). Now the module simply needs to be included in {Sass::Script::Functions}. ## 2.2.15 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.15). * Added {Sass::Script::Color#with} for a way of setting color channels that's easier than manually constructing a new color and is forwards-compatible with alpha-channel colors (to be introduced in Sass 2.4). * Added a missing require in Sass that caused crashes when it was being run standalone. ## 2.2.14 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.14). * All Sass functions now raise explicit errors if their inputs are of the incorrect type. * Allow the SassScript `rgb()` function to take percentages in addition to numerical values. * Fixed a bug where SassScript strings with `#` followed by `#{}` interpolation didn't evaluate the interpolation. ### SassScript Ruby API These changes only affect people defining their own Sass functions using {Sass::Script::Functions}. * Sass::Script::Color#value attribute is deprecated. Use {Sass::Script::Color#rgb} instead. The returned array is now frozen as well. * Add an `assert_type` function that's available to {Sass::Script::Functions}. This is useful for typechecking the inputs to functions. ### Rack Support Sass 2.2.14 includes Rack middleware for running Sass, meaning that all Rack-enabled frameworks can now use Sass. To activate this, just add require 'sass/plugin/rack' use Sass::Plugin::Rack to your `config.ru`. See the {Sass::Plugin::Rack} documentation for more details. ## 2.2.13 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.13). There were no changes made to Sass between versions 2.2.12 and 2.2.13. ## 2.2.12 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.12). * Fix a stupid bug introduced in 2.2.11 that broke the Sass Rails plugin. ## 2.2.11 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.11). * Added a note to errors on properties that could be pseudo-classes (e.g. `:focus`) indicating that they should be backslash-escaped. * Automatically interpret properties that could be pseudo-classes as such if {file:SASS_REFERENCE.md.html#property_syntax-option `:property_syntax`} is set to `:new`. * Fixed `css2sass`'s generation of pseudo-classes so that they're backslash-escaped. * Don't crash if the Haml plugin skeleton is installed and `rake gems:install` is run. * Don't use `RAILS_ROOT` directly. This no longer exists in Rails 3.0. Instead abstract this out as `Haml::Util.rails_root`. This changes makes Haml fully compatible with edge Rails as of this writing. * Make use of a Rails callback rather than a monkeypatch to check for stylesheet updates in Rails 3.0+. ## 2.2.10 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.10). * Add support for attribute selectors with spaces around the `=`. For example: a[href = http://google.com] color: blue ## 2.2.9 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.9). There were no changes made to Sass between versions 2.2.8 and 2.2.9. ## 2.2.8 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.8). There were no changes made to Sass between versions 2.2.7 and 2.2.8. ## 2.2.7 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.7). There were no changes made to Sass between versions 2.2.6 and 2.2.7. ## 2.2.6 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.6). * Don't crash when the `__FILE__` constant of a Ruby file is a relative path, as apparently happens sometimes in TextMate (thanks to [Karl Varga](http://github.com/kjvarga)). * Add "Sass" to the `--version` string for the executables. ## 2.2.5 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.5). There were no changes made to Sass between versions 2.2.4 and 2.2.5. ## 2.2.4 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.4). * Don't add `require 'rubygems'` to the top of init.rb when installed via `sass --rails`. This isn't necessary, and actually gets clobbered as soon as haml/template is loaded. * Document the previously-undocumented {file:SASS_REFERENCE.md#line-option `:line` option}, which allows the number of the first line of a Sass file to be set for error reporting. ## 2.2.3 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.3). Sass 2.2.3 prints line numbers for warnings about selectors with no properties. ## 2.2.2 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.2). Sass 2.2.2 is a minor bug-fix release. Notable changes include better parsing of mixin definitions and inclusions and better support for Ruby 1.9. ## 2.2.1 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.1). Sass 2.2.1 is a minor bug-fix release. ### Must Read! * It used to be acceptable to use `-` immediately following variable names, without any whitespace in between (for example, `!foo-!bar`). This is now deprecated, so that in the future variables with hyphens can be supported. Surround `-` with spaces. ## 2.2.0 [Tagged on GitHub](http://github.com/nex3/haml/commit/2.2.0). The 2.2 release marks a significant step in the evolution of the Sass language. The focus has been to increase the power of Sass to keep your stylesheets maintainable by allowing new forms of abstraction to be created within your stylesheets and the stylesheets provided by others that you can download and import into your own. The fundamental units of abstraction in Sass are variables and mixins. Please read below for a list of changes: ### Must Read! * Sass Comments (//) used to only comment out a single line. This was deprecated in 2.0.10 and starting in 2.2, Sass comments will comment out any lines indented under them. Upgrade to 2.0.10 in order to see deprecation warnings where this change affects you. * Implicit Strings within SassScript are now deprecated and will be removed in 2.4. For example: `border= !width solid #00F` should now be written as `border: #{!width} solid #00F` or as `border= !width "solid" #00F`. After upgrading to 2.2, you will see deprecation warnings if you have sass files that use implicit strings. ### Sass Syntax Changes #### Flexible Indentation The indentation of Sass documents is now flexible. The first indent that is detected will determine the indentation style for that document. Tabs and spaces may never be mixed, but within a document, you may choose to use tabs or a flexible number of spaces. #### Multiline Sass Comments Sass Comments (//) will now comment out whatever is indented beneath them. Previously they were single line when used at the top level of a document. Upgrading to the latest stable version will give you deprecation warnings if you have silent comments with indentation underneath them. #### Mixin Arguments Sass Mixins now accept any number of arguments. To define a mixin with arguments, specify the arguments as a comma-delimited list of variables like so: =my-mixin(!arg1, !arg2, !arg3) As before, the definition of the mixin is indented below the mixin declaration. The variables declared in the argument list may be used and will be bound to the values passed to the mixin when it is invoked. Trailing arguments may have default values as part of the declaration: =my-mixin(!arg1, !arg2 = 1px, !arg3 = blue) In the example above, the mixin may be invoked by passing 1, 2 or 3 arguments to it. A similar syntax is used to invoke a mixin that accepts arguments: div.foo +my-mixin(1em, 3px) When a mixin has no required arguments, the parenthesis are optional. The default values for mixin arguments are evaluated in the global context at the time when the mixin is invoked, they may also reference the previous arguments in the declaration. For example: !default_width = 30px =my-fancy-mixin(!width = !default_width, !height = !width) width= !width height= !height .default-box +my-fancy-mixin .square-box +my-fancy-mixin(50px) .rectangle-box +my-fancy-mixin(25px, 75px) !default_width = 10px .small-default-box +my-fancy-mixin compiles to: .default-box { width: 30px; height: 30px; } .square-box { width: 50px; height: 50px; } .rectangle-box { width: 25px; height: 75px; } .small-default-box { width: 10px; height: 10px; } ### Sass, Interactive The sass command line option -i now allows you to quickly and interactively experiment with SassScript expressions. The value of the expression you enter will be printed out after each line. Example: $ sass -i >> 5px 5px >> 5px + 10px 15px >> !five_pixels = 5px 5px >> !five_pixels + 10px 15px ### SassScript The features of SassScript have been greatly enhanced with new control directives, new fundamental data types, and variable scoping. #### New Data Types SassScript now has four fundamental data types: 1. Number 2. String 3. Boolean (New in 2.2) 4. Colors #### More Flexible Numbers Like JavaScript, SassScript numbers can now change between floating point and integers. No explicit casting or decimal syntax is required. When a number is emitted into a CSS file it will be rounded to the nearest thousandth, however the internal representation maintains much higher precision. #### Improved Handling of Units While Sass has long supported numbers with units, it now has a much deeper understanding of them. The following are examples of legal numbers in SassScript: 0, 1000, 6%, -2px, 5pc, 20em, or 2foo. Numbers of the same unit may always be added and subtracted. Numbers that have units that Sass understands and finds comparable, can be combined, taking the unit of the first number. Numbers that have non-comparable units may not be added nor subtracted -- any attempt to do so will cause an error. However, a unitless number takes on the unit of the other number during a mathematical operation. For example: >> 3mm + 4cm 43mm >> 4cm + 3mm 4.3cm >> 3cm + 2in 8.08cm >> 5foo + 6foo 11foo >> 4% + 5px SyntaxError: Incompatible units: 'px' and '%'. >> 5 + 10px 15px Sass allows compound units to be stored in any intermediate form, but will raise an error if you try to emit a compound unit into your css file. >> !em_ratio = 1em / 16px 0.063em/px >> !em_ratio * 32px 2em >> !em_ratio * 40px 2.5em #### Colors A color value can be declared using a color name, hexadecimal, shorthand hexadecimal, the rgb function, or the hsl function. When outputting a color into css, the color name is used, if any, otherwise it is emitted as hexadecimal value. Examples: > #fff white >> white white >> #FFFFFF white >> hsl(180, 100, 100) white >> rgb(255, 255, 255) white >> #AAA #aaaaaa Math on color objects is performed piecewise on the rgb components. However, these operations rarely have meaning in the design domain (mostly they make sense for gray-scale colors). >> #aaa + #123 #bbccdd >> #333 * 2 #666666 #### Booleans Boolean objects can be created by comparison operators or via the `true` and `false` keywords. Booleans can be combined using the `and`, `or`, and `not` keywords. >> true true >> true and false false >> 5 < 10 true >> not (5 < 10) false >> not (5 < 10) or not (10 < 5) true >> 30mm == 3cm true >> 1px == 1em false #### Strings Unicode escapes are now allowed within SassScript strings. ### Control Directives New directives provide branching and looping within a sass stylesheet based on SassScript expressions. See the [Sass Reference](SASS_REFERENCE.md.html#control_directives) for complete details. #### @for The `@for` directive loops over a set of numbers in sequence, defining the current number into the variable specified for each loop. The `through` keyword means that the last iteration will include the number, the `to` keyword means that it will stop just before that number. @for !x from 1px through 5px .border-#{!x} border-width= !x compiles to: .border-1px { border-width: 1px; } .border-2px { border-width: 2px; } .border-3px { border-width: 3px; } .border-4px { border-width: 4px; } .border-5px { border-width: 5px; } #### @if / @else if / @else The branching directives `@if`, `@else if`, and `@else` let you select between several branches of sass to be emitted, based on the result of a SassScript expression. Example: !type = "monster" p @if !type == "ocean" color: blue @else if !type == "matador" color: red @else if !type == "monster" color: green @else color: black is compiled to: p { color: green; } #### @while The `@while` directive lets you iterate until a condition is met. Example: !i = 6 @while !i > 0 .item-#{!i} width = 2em * !i !i = !i - 2 is compiled to: .item-6 { width: 12em; } .item-4 { width: 8em; } .item-2 { width: 4em; } ### Variable Scoping The term "constant" has been renamed to "variable." Variables can be declared at any scope (a.k.a. nesting level) and they will only be visible to the code until the next outdent. However, if a variable is already defined in a higher level scope, setting it will overwrite the value stored previously. In this code, the `!local_var` variable is scoped and hidden from other higher level scopes or sibling scopes: .foo .bar !local_var = 1px width= !local_var .baz // this will raise an undefined variable error. width= !local_var // as will this width= !local_var In this example, since the `!global_var` variable is first declared at a higher scope, it is shared among all lower scopes: !global_var = 1px .foo .bar !global_var = 2px width= !global_var .baz width= !global_var width= !global_var compiles to: .foo { width: 2px; } .foo .bar { width: 2px; } .foo .baz { width: 2px; } ### Interpolation Interpolation has been added. This allows SassScript to be used to create dynamic properties and selectors. It also cleans up some uses of dynamic values when dealing with compound properties. Using interpolation, the result of a SassScript expression can be placed anywhere: !x = 1 !d = 3 !property = "border" div.#{!property} #{!property}: #{!x + !d}px solid #{!property}-color: blue is compiled to: div.border { border: 4px solid; border-color: blue; } ### Sass Functions SassScript defines some useful functions that are called using the normal CSS function syntax: p color = hsl(0, 100%, 50%) is compiled to: #main { color: #ff0000; } The following functions are provided: `hsl`, `percentage`, `round`, `ceil`, `floor`, and `abs`. You can define additional functions in ruby. See {Sass::Script::Functions} for more information. ### New Options #### `:line_comments` To aid in debugging, You may set the `:line_comments` option to `true`. This will cause the sass engine to insert a comment before each selector saying where that selector was defined in your sass code. #### `:template_location` The {Sass::Plugin} `:template_location` option now accepts a hash of sass paths to corresponding css paths. Please be aware that it is possible to import sass files between these separate locations -- they are not isolated from each other. ### Miscellaneous Features #### `@debug` Directive The `@debug` directive accepts a SassScript expression and emits the value of that expression to the terminal (stderr). Example: @debug 1px + 2px During compilation the following will be printed: Line 1 DEBUG: 3px #### Ruby 1.9 Support Sass now fully supports Ruby 1.9.1. #### Sass Cache By default, Sass caches compiled templates and [partials](SASS_REFERENCE.md.html#partials). This dramatically speeds up re-compilation of large collections of Sass files, and works best if the Sass templates are split up into separate files that are all [`@import`](SASS_REFERENCE.md.html#import)ed into one large file. Without a framework, Sass puts the cached templates in the `.sass-cache` directory. In Rails and Merb, they go in `tmp/sass-cache`. The directory can be customized with the [`:cache_location`](#cache_location-option) option. If you don't want Sass to use caching at all, set the [`:cache`](#cache-option) option to `false`. stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/doc-src/FAQ.md0000664000175000017500000000260012206724733033311 0ustar jamespagejamespage# Frequently Asked Questions * Table of contents {:toc} ## Can I use a variable from my controller in my Sass file? {#q-ruby-code} No. Sass files aren't views. They're compiled once into static CSS files, then left along until they're changed and need to be compiled again. Not only don't you want to be running a full request cycle every time someone requests a stylesheet, but it's not a great idea to put much logic in there anyway due to how browsers handle them. If you really need some sort of dynamic CSS, you can define your own {Sass::Script::Functions Sass functions} using Ruby that can access the database or other configuration. *Be aware when doing this that Sass files are by default only compiled once and then served statically.* If you really, really need to compile Sass on each request, first make sure you have adequate caching set up. Then you can use {Sass::Engine} to render the code, using the {file:SASS_REFERENCE.md#custom-option `:custom` option} to pass in data that {Sass::Script::Functions::EvaluationContext#options can be accessed} from your Sass functions. # You still haven't answered my question! Sorry! Try looking at the [Sass](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html) reference, If you can't find an answer there, feel free to ask in `#sass` on irc.freenode.net or send an email to the [mailing list](http://groups.google.com/group/sass-lang). ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/doc-src/SCSS_FOR_SASS_USERS.mdstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/doc-src/SCSS_F0000664000175000017500000001026212206724733033326 0ustar jamespagejamespage# Intro to SCSS for Sass Users Sass 3 introduces a new syntax known as SCSS which is fully compatible with the syntax of CSS3, while still supporting the full power of Sass. This means that every valid CSS3 stylesheet is a valid SCSS file with the same meaning. In addition, SCSS understands most CSS hacks and vendor-specific syntax, such as [IE's old `filter` syntax](http://msdn.microsoft.com/en-us/library/ms533754%28VS.85%29.aspx). Since SCSS is a CSS extension, everything that works in CSS works in SCSS. This means that for a Sass user to understand it, they need only understand how the Sass extensions work. Most of these, such as variables, parent references, and directives work the same; the only difference is that SCSS requires semicolons and brackets instead of newlines and indentation. For example, a simple rule in Sass: #sidebar width: 30% background-color: #faa could be converted to SCSS just by adding brackets and semicolons: #sidebar { width: 30%; background-color: #faa; } In addition, SCSS is completely whitespace-insensitive. That means the above could also be written as: #sidebar {width: 30%; background-color: #faa} There are some differences that are slightly more complicated. These are detailed below. Note, though, that SCSS uses all the {file:SASS_CHANGELOG.md#3-0-0-syntax-changes syntax changes in Sass 3}, so make sure you understand those before going forward. ## Nested Selectors To nest selectors, simply define a new ruleset inside an existing ruleset: #sidebar { a { text-decoration: none; } } Of course, white space is insignificant and the last trailing semicolon is optional so you can also do it like this: #sidebar { a { text-decoration: none } } ## Nested Properties To nest properties, simply create a new property set after an existing property's colon: #footer { border: { width: 1px; color: #ccc; style: solid; } } This compiles to: #footer { border-width: 1px; border-color: #cccccc; border-style: solid; } ## Mixins A mixin is declared with the `@mixin` directive: @mixin rounded($amount) { -moz-border-radius: $amount; -webkit-border-radius: $amount; border-radius: $amount; } A mixin is used with the `@include` directive: .box { border: 3px solid #777; @include rounded(0.5em); } This syntax is also available in the indented syntax, although the old `=` and `+` syntax still works. This is rather verbose compared to the `=` and `+` characters used in Sass syntax. This is because the SCSS format is designed for CSS compatibility rather than conciseness, and creating new syntax when the CSS directive syntax already exists adds new syntax needlessly and could create incompatibilities with future versions of CSS. ## Comments Like Sass, SCSS supports both comments that are preserved in the CSS output and comments that aren't. However, SCSS's comments are significantly more flexible. It supports standard multiline CSS comments with `/* */`, which are preserved where possible in the output. These comments can have whatever formatting you like; Sass will do its best to format them nicely. SCSS also uses `//` for comments that are thrown away, like Sass. Unlike Sass, though, `//` comments in SCSS may appear anywhere and last only until the end of the line. For example: /* This comment is * several lines long. * since it uses the CSS comment syntax, * it will appear in the CSS output. */ body { color: black; } // These comments are only one line long each. // They won't appear in the CSS output, // since they use the single-line comment syntax. a { color: green; } is compiled to: /* This comment is * several lines long. * since it uses the CSS comment syntax, * it will appear in the CSS output. */ body { color: black; } a { color: green; } ## `@import` The `@import` directive in SCSS functions just like that in Sass, except that it takes a quoted string to import. For example, this Sass: @import themes/dark @import font.sass would be this SCSS: @import "themes/dark"; @import "font.sass"; ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/doc-src/INDENTED_SYNTAX.mdstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/doc-src/INDENT0000664000175000017500000001221012206724733033262 0ustar jamespagejamespage# Sass Indented Syntax * Table of contents {:toc} Sass's indented syntax (also known simply as "Sass") is designed to provide a more concise and, for some, more aesthetically appealing alternative to the CSS-based SCSS syntax. It's not compatible with CSS; instead of using `{` and `}` to delimit blocks of styles, it uses indentation, and instead of using semicolons to separate statements it uses newlines. This usually leads to substantially less text when saying the same thing. Each statement in Sass, such as property declarations and selectors, must be placed on its own line. In addition, everything that would be within `{` and `}` after a statement must be on a new line and indented one level deeper than that statement. For example, this CSS: #main { color: blue; font-size: 0.3em; } would be this Sass: #main color: blue font-size: 0.3em Similarly, this SCSS: #main { color: blue; font-size: 0.3em; a { font: { weight: bold; family: serif; } &:hover { background-color: #eee; } } } would be this Sass: #main color: blue font-size: 0.3em a font: weight: bold family: serif &:hover background-color: #eee ## Sass Syntax Differences In general, most CSS and SCSS syntax works straightforwardly in Sass by using newlines instead of semicolons and indentation instead of braces. However, there are some cases where there are differences or subtleties, which are detailed below. ## Property Synax The indented syntax supports two ways of declaring CSS properties. The first is just like CSS, except without the semicolon. The second, however, places the colon *before* the property name. For example: #main :color blue :font-size 0.3em By default, both ways may be used. However, the {file:SASS_REFERENCE.md#property_syntax-option `:property_syntax` option} may be used to specify that only one property syntax is allowed. ### Multiline Selectors Normally in the indented syntax, a single selector must take up a single line. There is one exception, however: selectors can contain newlines as long as they only appear after commas. For example: .users #userTab, .posts #postTab width: 100px height: 30px ### Comments Like everything else in the indented syntax, comments are line-based. This means that they don't work the same way as in SCSS. They must take up an entire line, and they also encompass all text nested beneath them. Like SCSS, the indented syntax supports two kinds of comments. Comments beginning with `/*` are preserved in the CSS output, although unlike SCSS they don't require a closing `*/`. Comments beginning with `//` are removed entirely. For example: /* This comment will appear in the CSS output. This is nested beneath the comment, so it's part of it body color: black // This comment will not appear in the CSS output. This is nested beneath the comment as well, so it also won't appear a color: green is compiled to: /* This comment will appear in the CSS output. * This is nested beneath the comment, * so it's part of it */ body { color: black; } a { color: green; } ### `@import` The `@import` directive in Sass does not require quotes, although they may be used. For example, this SCSS: @import "themes/dark"; @import "font.sass"; would be this Sass: @import themes/dark @import font.sass ### Mixin Directives Sass supports shorthands for the `@mixin` and `@include` directives. Instead of writing `@mixin`, you can use the character `=`; instead of writing `@include`, you can use the character `+`. For example: =large-text font: family: Arial size: 20px weight: bold color: #ff0000 h1 +large-text is the same as: @mixin large-text font: family: Arial size: 20px weight: bold color: #ff0000 h1 @include large-text ## Deprecated Syntax Since the indented syntax has been around for a while, previous versions have made some syntactic decisions that have since been changed. Some of the old syntax still works, though, so it's documented here. **Note that this syntax is not recommended for use in new Sass files**. It will print a warning if it's used, and it will be removed in a future version. ### `=` for Properties and Variables `=` used to be used instead of `:` when setting variables and when setting properties to SassScript values. It has slightly different semantics than `:`; see {file:SASS_CHANGELOG.md#3-0-0-sass-script-context this changelog entry} for details. ### `||=` for Default Variables `||=` used to be used instead of `:` when setting the default value of a variable. The `!default` flag was not used. The variable value has the same semantics as `=`; see {file:SASS_CHANGELOG.md#3-0-0-sass-script-context this changelog entry} for details. ### `!` Prefix for Variables `!` used to be used as the variable prefix instead of `$`. This had no difference in functionality; it was a purely aesthetic change. ././@LongLink0000644000000000000000000000016012255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/doc-src/SASS_REFERENCE.mdstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/doc-src/SASS_R0000664000175000017500000016020712206724733033345 0ustar jamespagejamespage# Sass (Syntactically Awesome StyleSheets) * Table of contents {:toc} Sass is an extension of CSS that adds power and elegance to the basic language. It allows you to use [variables](#variables_), [nested rules](#nested_rules), [mixins](#mixins), [inline imports](#import), and more, all with a fully CSS-compatible syntax. Sass helps keep large stylesheets well-organized, and get small stylesheets up and running quickly, particularly with the help of [the Compass style library](http://compass-style.org). ## Features * Fully CSS3-compatible * Language extensions such as variables, nesting, and mixins * Many {Sass::Script::Functions useful functions} for manipulating colors and other values * Advanced features like [control directives](#control_directives) for libraries * Well-formatted, customizable output * [Firebug integration](https://addons.mozilla.org/en-US/firefox/addon/103988) ## Syntax There are two syntaxes available for Sass. The first, known as SCSS (Sassy CSS) and used throughout this reference, is an extension of the syntax of CSS3. This means that every valid CSS3 stylesheet is a valid SCSS file with the same meaning. In addition, SCSS understands most CSS hacks and vendor-specific syntax, such as [IE's old `filter` syntax](http://msdn.microsoft.com/en-us/library/ms533754%28VS.85%29.aspx). This syntax is enhanced with the Sass features described below. Files using this syntax have the `.scss` extension. The second and older syntax, known as the indented syntax (or sometimes just "Sass"), provides a more concise way of writing CSS. It uses indentation rather than brackets to indicate nesting of selectors, and newlines rather than semicolons to separate properties. Some people find this to be easier to read and quicker to write than SCSS. The indented syntax has all the same features, although some of them have slightly different syntax; this is described in {file:INDENTED_SYNTAX.md the indented syntax reference}. Files using this syntax have the `.sass` extension. Either syntax can [import](#import) files written in the other. Files can be automatically converted from one syntax to the other using the `sass-convert` command line tool: # Convert Sass to SCSS $ sass-convert style.sass style.scss # Convert SCSS to Sass $ sass-convert style.scss style.sass ## Using Sass Sass can be used in three ways: as a command-line tool, as a standalone Ruby module, and as a plugin for any Rack-enabled framework, including Ruby on Rails and Merb. The first step for all of these is to install the Sass gem: gem install sass If you're using Windows, you may need to [install Ruby](http://rubyinstaller.org/download.html) first. To run Sass from the command line, just use sass input.scss output.css You can also tell Sass to watch the file and update the CSS every time the Sass file changes: sass --watch input.scss:output.css If you have a directory with many Sass files, you can also tell Sass to watch the entire directory: sass --watch app/sass:public/stylesheets Use `sass --help` for full documentation. Using Sass in Ruby code is very simple. After installing the Sass gem, you can use it by running `require "sass"` and using {Sass::Engine} like so: engine = Sass::Engine.new("#main {background-color: #0000ff}", :syntax => :scss) engine.render #=> "#main { background-color: #0000ff; }\n" ### Rack/Rails/Merb Plugin To enable Sass in Rails versions before Rails 3, add the following line to `environment.rb`: config.gem "sass" For Rails 3, instead add the following line to the Gemfile: gem "sass" To enable Sass in Merb, add the following line to `config/dependencies.rb`: dependency "merb-haml" To enable Sass in a Rack application, add require 'sass/plugin/rack' use Sass::Plugin::Rack to `config.ru`. Sass stylesheets don't work the same as views. They don't contain dynamic content, so the CSS only needs to be generated when the Sass file has been updated. By default, `.sass` and `.scss` files are placed in public/stylesheets/sass (this can be customized with the [`:template_location`](#template_location-option) option). Then, whenever necessary, they're compiled into corresponding CSS files in public/stylesheets. For instance, public/stylesheets/sass/main.scss would be compiled to public/stylesheets/main.css. ### Caching By default, Sass caches compiled templates and [partials](#partials). This dramatically speeds up re-compilation of large collections of Sass files, and works best if the Sass templates are split up into separate files that are all [`@import`](#import)ed into one large file. Without a framework, Sass puts the cached templates in the `.sass-cache` directory. In Rails and Merb, they go in `tmp/sass-cache`. The directory can be customized with the [`:cache_location`](#cache_location-option) option. If you don't want Sass to use caching at all, set the [`:cache`](#cache-option) option to `false`. ### Options Options can be set by setting the {Sass::Plugin::Configuration#options Sass::Plugin#options} hash in `environment.rb` in Rails or `config.ru` in Rack... Sass::Plugin.options[:style] = :compact ...or by setting the `Merb::Plugin.config[:sass]` hash in `init.rb` in Merb... Merb::Plugin.config[:sass][:style] = :compact ...or by passing an options hash to {Sass::Engine#initialize}. All relevant options are also available via flags to the `sass` and `scss` command-line executables. Available options are: {#style-option} `:style` : Sets the style of the CSS output. See [Output Style](#output_style). {#syntax-option} `:syntax` : The syntax of the input file, `:sass` for the indented syntax and `:scss` for the CSS-extension syntax. This is only useful when you're constructing {Sass::Engine} instances yourself; it's automatically set properly when using {Sass::Plugin}. Defaults to `:sass`. {#property_syntax-option} `:property_syntax` : Forces indented-syntax documents to use one syntax for properties. If the correct syntax isn't used, an error is thrown. `:new` forces the use of a colon or equals sign after the property name. For example: `color: #0f3` or `width: $main_width`. `:old` forces the use of a colon before the property name. For example: `:color #0f3` or `:width $main_width`. By default, either syntax is valid. This has no effect on SCSS documents. {#cache-option} `:cache` : Whether parsed Sass files should be cached, allowing greater speed. Defaults to true. {#read_cache-option} `:read_cache` : If this is set and `:cache` is not, only read the Sass cache if it exists, don't write to it if it doesn't. {#cache_store-option} `:cache_store` : If this is set to an instance of a subclass of {Sass::CacheStores::Base}, that cache store will be used to store and retrieve cached compilation results. Defaults to a {Sass::CacheStores::Filesystem} that is initialized using the [`:cache_location` option](#cache_location-option). {#never_update-option} `:never_update` : Whether the CSS files should never be updated, even if the template file changes. Setting this to true may give small performance gains. It always defaults to false. Only has meaning within Rack, Ruby on Rails, or Merb. {#always_update-option} `:always_update` : Whether the CSS files should be updated every time a controller is accessed, as opposed to only when the template has been modified. Defaults to false. Only has meaning within Rack, Ruby on Rails, or Merb. {#always_check-option} `:always_check` : Whether a Sass template should be checked for updates every time a controller is accessed, as opposed to only when the server starts. If a Sass template has been updated, it will be recompiled and will overwrite the corresponding CSS file. Defaults to false in production mode, true otherwise. Only has meaning within Rack, Ruby on Rails, or Merb. {#full_exception-option} `:full_exception` : Whether an error in the Sass code should cause Sass to provide a detailed description within the generated CSS file. If set to true, the error will be displayed along with a line number and source snippet both as a comment in the CSS file and at the top of the page (in supported browsers). Otherwise, an exception will be raised in the Ruby code. Defaults to false in production mode, true otherwise. Only has meaning within Rack, Ruby on Rails, or Merb. {#template_location-option} `:template_location` : A path to the root sass template directory for your application. If a hash, `:css_location` is ignored and this option designates a mapping between input and output directories. May also be given a list of 2-element lists, instead of a hash. Defaults to `css_location + "/sass"`. Only has meaning within Rack, Ruby on Rails, or Merb. Note that if multiple template locations are specified, all of them are placed in the import path, allowing you to import between them. **Note that due to the many possible formats it can take, this option should only be set directly, not accessed or modified. Use the {Sass::Plugin::Configuration#template_location_array Sass::Plugin#template_location_array}, {Sass::Plugin::Configuration#add_template_location Sass::Plugin#add_template_location}, and {Sass::Plugin::Configuration#remove_template_location Sass::Plugin#remove_template_location} methods instead**. {#css_location-option} `:css_location` : The path where CSS output should be written to. This option is ignored when `:template_location` is a Hash. Defaults to `"./public/stylesheets"`. Only has meaning within Rack, Ruby on Rails, or Merb. {#cache_location-option} `:cache_location` : The path where the cached `sassc` files should be written to. Defaults to `"./tmp/sass-cache"` in Rails and Merb, or `"./.sass-cache"` otherwise. If the [`:cache_store` option](#cache_location-option) is set, this is ignored. {#unix_newlines-option} `:unix_newlines` : If true, use Unix-style newlines when writing files. Only has meaning on Windows, and only when Sass is writing the files (in Rack, Rails, or Merb, when using {Sass::Plugin} directly, or when using the command-line executable). {#filename-option} `:filename` : The filename of the file being rendered. This is used solely for reporting errors, and is automatically set when using Rack, Rails, or Merb. {#line-option} `:line` : The number of the first line of the Sass template. Used for reporting line numbers for errors. This is useful to set if the Sass template is embedded in a Ruby file. {#load_paths-option} `:load_paths` : An array of filesystem paths or importers which should be searched for Sass templates imported with the [`@import`](#import) directive. These may be strings, `Pathname` objects, or subclasses of {Sass::Importers::Base}. This defaults to the working directory and, in Rack, Rails, or Merb, whatever `:template_location` is. {#filesystem_importer-option} `:filesystem_importer` : A {Sass::Importers::Base} subclass used to handle plain string load paths. This should import files from the filesystem. It should be a Class object inheriting from {Sass::Importers::Base} with a constructor that takes a single string argument (the load path). Defaults to {Sass::Importers::Filesystem}. {#line_numbers-option} `:line_numbers` : When set to true, causes the line number and file where a selector is defined to be emitted into the compiled CSS as a comment. Useful for debugging, especially when using imports and mixins. This option may also be called `:line_comments`. Automatically disabled when using the `:compressed` output style or the `:debug_info` option. {#debug_info-option} `:debug_info` : When set to true, causes the line number and file where a selector is defined to be emitted into the compiled CSS in a format that can be understood by the browser. Useful in conjunction with [the FireSass Firebug extension](https://addons.mozilla.org/en-US/firefox/addon/103988) for displaying the Sass filename and line number. Automatically disabled when using the `:compressed` output style. {#custom-option} `:custom` : An option that's available for individual applications to set to make data available to {Sass::Script::Functions custom Sass functions}. {#quiet-option} `:quiet` : When set to true, causes warnings to be disabled. ### Syntax Selection The Sass command-line tool will use the file extension to determine which syntax you are using, but there's not always a filename. The `sass` command-line program defaults to the indented syntax but you can pass the `--scss` option to it if the input should be interpreted as SCSS syntax. Alternatively, you can use the `scss` command-line program which is exactly like the `sass` program but it defaults to assuming the syntax is SCSS. ### Encodings When running on Ruby 1.9 and later, Sass is aware of the character encoding of documents and will handle them the same way that CSS would. By default, Sass assumes that all stylesheets are encoded using whatever coding system your operating system defaults to. For many users this will be `UTF-8`, the de facto standard for the web. For some users, though, it may be a more local encoding. If you want to use a different encoding for your stylesheet than your operating system default, you can use the `@charset` declaration just like in CSS. Add `@charset "encoding-name";` at the beginning of the stylesheet (before any whitespace or comments) and Sass will interpret it as the given encoding. Note that whatever encoding you use, it must be convertible to Unicode. Sass will also respect any Unicode BOMs and non-ASCII-compatible Unicode encodings [as specified by the CSS spec](http://www.w3.org/TR/CSS2/syndata.html#charset), although this is *not* the recommended way to specify the character set for a document. Note that Sass does not support the obscure `UTF-32-2143`, `UTF-32-3412`, `EBCDIC`, `IBM1026`, and `GSM 03.38` encodings, since Ruby does not have support for them and they're highly unlikely to ever be used in practice. #### Output Encoding In general, Sass will try to encode the output stylesheet using the same encoding as the input stylesheet. In order for it to do this, though, the input stylesheet must have a `@charset` declaration; otherwise, Sass will default to encoding the output stylesheet as UTF-8. In addition, it will add a `@charset` declaration to the output if it's not plain ASCII. When other stylesheets with `@charset` declarations are `@import`ed, Sass will convert them to the same encoding as the main stylesheet. Note that Ruby 1.8 does not have good support for character encodings, and so Sass behaves somewhat differently when running under it than under Ruby 1.9 and later. In Ruby 1.8, Sass simply uses the first `@charset` declaration in the stylesheet or any of the other stylesheets it `@import`s. ## CSS Extensions ### Nested Rules Sass allows CSS rules to be nested within one another. The inner rule then only applies within the outer rule's selector. For example: #main p { color: #00ff00; width: 97%; .redbox { background-color: #ff0000; color: #000000; } } is compiled to: #main p { color: #00ff00; width: 97%; } #main p .redbox { background-color: #ff0000; color: #000000; } This helps avoid repetition of parent selectors, and makes complex CSS layouts with lots of nested selectors much simpler. For example: #main { width: 97%; p, div { font-size: 2em; a { font-weight: bold; } } pre { font-size: 3em; } } is compiled to: #main { width: 97%; } #main p, #main div { font-size: 2em; } #main p a, #main div a { font-weight: bold; } #main pre { font-size: 3em; } ### Referencing Parent Selectors: `&` Sometimes it's useful to use a nested rule's parent selector in other ways than the default. For instance, you might want to have special styles for when that selector is hovered over or for when the body element has a certain class. In these cases, you can explicitly specify where the parent selector should be inserted using the `&` character. For example: a { font-weight: bold; text-decoration: none; &:hover { text-decoration: underline; } body.firefox & { font-weight: normal; } } is compiled to: a { font-weight: bold; text-decoration: none; } a:hover { text-decoration: underline; } body.firefox a { font-weight: normal; } `&` will be replaced with the parent selector as it appears in the CSS. This means that if you have a deeply nested rule, the parent selector will be fully resolved before the `&` is replaced. For example: #main { color: black; a { font-weight: bold; &:hover { color: red; } } } is compiled to: #main { color: black; } #main a { font-weight: bold; } #main a:hover { color: red; } ### Nested Properties CSS has quite a few properties that are in "namespaces;" for instance, `font-family`, `font-size`, and `font-weight` are all in the `font` namespace. In CSS, if you want to set a bunch of properties in the same namespace, you have to type it out each time. Sass provides a shortcut for this: just write the namespace one, then nest each of the sub-properties within it. For example: .funky { font: { family: fantasy; size: 30em; weight: bold; } } is compiled to: .funky { font-family: fantasy; font-size: 30em; font-weight: bold; } The property namespace itself can also have a value. For example: .funky { font: 2px/3px { family: fantasy; size: 30em; weight: bold; } } is compiled to: .funky { font: 2px/3px; font-family: fantasy; font-size: 30em; font-weight: bold; } ## Comments: `/* */` and `//` {#comments} Sass supports standard multiline CSS comments with `/* */`, as well as single-line comments with `//`. The multiline comments are preserved in the CSS output where possible, while the single-line comments are removed. For example: /* This comment is * several lines long. * since it uses the CSS comment syntax, * it will appear in the CSS output. */ body { color: black; } // These comments are only one line long each. // They won't appear in the CSS output, // since they use the single-line comment syntax. a { color: green; } is compiled to: /* This comment is * several lines long. * since it uses the CSS comment syntax, * it will appear in the CSS output. */ body { color: black; } a { color: green; } When the first letter of a comment is `!`, the comment will be interpolated and always rendered into css output even in compressed output modes. This is useful for adding Copyright notices to your generated CSS. ## SassScript {#sassscript} In addition to the plain CSS property syntax, Sass supports a small set of extensions called SassScript. SassScript allows properties to use variables, arithmetic, and extra functions. SassScript can be used in any property value. SassScript can also be used to generate selectors and property names, which is useful when writing [mixins](#mixins). This is done via [interpolation](#interpolation_). ### Interactive Shell You can easily experiment with SassScript using the interactive shell. To launch the shell run the sass command-line with the `-i` option. At the prompt, enter any legal SassScript expression to have it evaluated and the result printed out for you: $ sass -i >> "Hello, Sassy World!" "Hello, Sassy World!" >> 1px + 1px + 1px 3px >> #777 + #777 #eeeeee >> #777 + #888 white ### Variables: `$` {#variables_} The most straightforward way to use SassScript is to use variables. Variables begin with dollar signs, and are set like CSS properties: $width: 5em; You can then refer to them in properties: #main { width: $width; } Variables are only available within the level of nested selectors where they're defined. If they're defined outside of any nested selectors, they're available everywhere. Variables used to use the prefix character `!`; this still works, but it's deprecated and prints a warning. `$` is the recommended syntax. Variables also used to be defined with `=` rather than `:`; this still works, but it's deprecated and prints a warning. `:` is the recommended syntax. ### Data Types SassScript supports four main data types: * numbers (e.g. `1.2`, `13`, `10px`) * strings of text, with and without quotes (e.g. `"foo"`, `'bar'`, `baz`) * colors (e.g. `blue`, `#04a3f9`, `rgba(255, 0, 0, 0.5)`) * booleans (e.g. `true`, `false`) * lists of values, separated by spaces or commas (e.g. `1.5em 1em 0 2em`, `Helvetica, Arial, sans-serif`) SassScript also supports all other types of CSS property value, such as Unicode ranges and `!important` declarations. However, it has no special handling for these types. They're treated just like unquoted strings. #### Strings {#sass-script-strings} CSS specifies two kinds of strings: those with quotes, such as `"Lucida Grande"` or `'http://sass-lang.com'`, and those without quotes, such as `sans-serif` or `bold`. SassScript recognizes both kinds, and in general if one kind of string is used in the Sass document, that kind of string will be used in the resulting CSS. There is one exception to this, though: when using [`#{}` interpolation](#interpolation_), quoted strings are unquoted. This makes it easier to use e.g. selector names in [mixins](#mixins). For example: @mixin firefox-message($selector) { body.firefox #{$selector}:before { content: "Hi, Firefox users!"; } } @include firefox-message(".header"); is compiled to: body.firefox .header:before { content: "Hi, Firefox users!"; } It's also worth noting that when using the [deprecated `=` property syntax](#sassscript), all strings are interpreted as unquoted, regardless of whether or not they're written with quotes. #### Lists Lists are how Sass represents the values of CSS declarations like `margin: 10px 15px 0 0` or `font-face: Helvetica, Arial, sans-serif`. Lists are just a series of other values, separated by either spaces or commas. In fact, individual values count as lists, too: they're just lists with one item. On their own, lists don't do much, but the {file:Sass/Script/Functions.html#list-functions Sass list functions} make them useful. The {Sass::Script::Functions#nth nth function} can access items in a list, the {Sass::Script::Functions#join join function} can join multiple lists together, and the {Sass::Script::Functions#append append function} can add items to lists. The [`@each` rule](#each-directive) can also add styles for each item in a list. In addition to containing simple values, lists can contain other lists. For example, `1px 2px, 5px 6px` is a two-item list containing the list `1px 2px` and the list `5px 6px`. If the inner lists have the same separator as the outer list, you'll need to use parentheses to make it clear where the inner lists start and stop. For example, `(1px 2px) (5px 6px)` is also a two-item list containing the list `1px 2px` and the list `5px 6px`. The difference is that the outer list is space-separated, where before it was comma-separated. When lists are turned into plain CSS, Sass doesn't add any parentheses, since CSS doesn't understand them. That means that `(1px 2px) (5px 6px)` and `1px 2px 5px 6px` will look the same when they become CSS. However, they aren't the same when they're Sass: the first is a list containing two lists, while the second is a list containing four numbers. Lists can also have no items in them at all. These lists are represented as `()`. They can't be output directly to CSS; if you try to do e.g. `font-family: ()`, Sass will raise an error. If a list contains empty lists, as in `1px 2px () 3px`, the empty list will be removed before it's turned into CSS. ### Operations All types support equality operations (`==` and `!=`). In addition, each type has its own operations that it has special support for. #### Number Operations SassScript supports the standard arithmetic operations on numbers (`+`, `-`, `*`, `/`, `%`), and will automatically convert between units if it can: p { width: 1in + 8pt; } is compiled to: p { width: 1.111in; } Relational operators (`<`, `>`, `<=`, `>=`) are also supported for numbers, and equality operators (`==`, `!=`) are supported for all types. ##### Division and `/` {#division-and-slash} CSS allows `/` to appear in property values as a way of separating numbers. Since SassScript is an extension of the CSS property syntax, it must support this, while also allowing `/` to be used for division. This means that by default, if two numbers are separated by `/` in SassScript, then they will appear that way in the resulting CSS. However, there are three situations where the `/` will be interpreted as division. These cover the vast majority of cases where division is actually used. They are: 1. If the value, or any part of it, is stored in a variable. 2. If the value is surrounded by parentheses. 3. If the value is used as part of another arithmetic expression. For example: p { font: 10px/8px; // Plain CSS, no division $width: 1000px; width: $width/2; // Uses a variable, does division height: (500px/2); // Uses parentheses, does division margin-left: 5px + 8px/2px; // Uses +, does division } is compiled to: p { font: 10px/8px; width: 500px; height: 250px; margin-left: 9px; } If you want to use variables along with a plain CSS `/`, you can use `#{}` to insert them. For example: p { $font-size: 12px; $line-height: 30px; font: #{$font-size}/#{$line-height}; } is compiled to: p { font: 12px/30px; } #### Color Operations All arithmetic operations are supported for color values, where they work piecewise. This means that the operation is performed on the red, green, and blue components in turn. For example: p { color: #010203 + #040506; } computes `01 + 04 = 05`, `02 + 05 = 07`, and `03 + 06 = 09`, and is compiled to: p { color: #050709; } Often it's more useful to use {Sass::Script::Functions color functions} than to try to use color arithmetic to achieve the same effect. Arithmetic operations also work between numbers and colors, also piecewise. For example: p { color: #010203 * 2; } computes `01 * 2 = 02`, `02 * 2 = 04`, and `03 * 2 = 06`, and is compiled to: p { color: #020406; } Note that colors with an alpha channel (those created with the {Sass::Script::Functions#rgba rgba} or {Sass::Script::Functions#hsla hsla} functions) must have the same alpha value in order for color arithmetic to be done with them. The arithmetic doesn't affect the alpha value. For example: p { color: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75); } is compiled to: p { color: rgba(255, 255, 0, 0.75); } The alpha channel of a color can be adjusted using the {Sass::Script::Functions#opacify opacify} and {Sass::Script::Functions#transparentize transparentize} functions. For example: $translucent-red: rgba(255, 0, 0, 0.5); p { color: opacify($translucent-red, 0.8); background-color: transparentize($translucent-red, 50%); } is compiled to: p { color: rgba(255, 0, 0, 0.9); background-color: rgba(255, 0, 0, 0.25); } #### String Operations The `+` operation can be used to concatenate strings: p { cursor: e + -resize; } is compiled to: p { cursor: e-resize; } Note that if a quoted string is added to an unquoted string (that is, the quoted string is to the left of the `+`), the result is a quoted string. Likewise, if an unquoted string is added to a quoted string (the unquoted string is to the left of the `+`), the result is an unquoted string. For example: p:before { content: "Foo " + Bar; font-family: sans- + "serif"; } is compiled to: p:before { content: "Foo Bar"; font-family: sans-serif; } By default, if two values are placed next to one another, they are concatenated with a space: p { margin: 3px + 4px auto; } is compiled to: p { margin: 7px auto; } Within a string of text, #{} style interpolation can be used to place dynamic values within the string: p:before { content: "I ate #{5 + 10} pies!"; } is compiled to: p:before { content: "I ate 15 pies!"; } #### Boolean Operations SassScript supports `and`, `or`, and `not` operators for boolean values. #### List Operations Lists don't support any special operations. Instead, they're manipulated using the {file:Sass/Script/Functions.html#list-functions list functions}. ### Parentheses Parentheses can be used to affect the order of operations: p { width: 1em + (2em * 3); } is compiled to: p { width: 7em; } ### Functions SassScript defines some useful functions that are called using the normal CSS function syntax: p { color: hsl(0, 100%, 50%); } is compiled to: p { color: #ff0000; } #### Keyword Arguments Sass functions can also be called using explicit keyword arguments. The above example can also be written as: p { color: hsl($hue: 0, $saturation: 100%, $lightness: 50%); } While this is less concise, it can make the stylesheet easier to read. It also allows functions to present more flexible interfaces, providing many arguments without becoming difficult to call. Named arguments can be passed in any order, and arguments with default values can be omitted. Since the named arguments are variable names, underscores and dashes can be used interchangeably. See {Sass::Script::Functions} for a full listing of Sass functions and their argument names, as well as instructions on defining your own in Ruby. ### Interpolation: `#{}` {#interpolation_} You can also use SassScript variables in selectors and property names using #{} interpolation syntax: $name: foo; $attr: border; p.#{$name} { #{$attr}-color: blue } is compiled to: p.foo { border-color: blue; } It's also possible to use `#{}` to put SassScript into property values. In most cases this isn't any better than using a variable, but using `#{}` does mean that any operations near it will be treated as plain CSS. For example: p { $font-size: 12px; $line-height: 30px; font: #{$font-size}/#{$line-height}; } is compiled to: p { font: 12px/30px; } ### Variable Defaults: `!default` You can assign to variables if they aren't already assigned by adding the `!default` flag to the end of the value. This means that if the variable has already been assigned to, it won't be re-assigned, but if it doesn't have a value yet, it will be given one. For example: $content: "First content"; $content: "Second content?" !default; $new_content: "First time reference" !default; #main { content: $content; new-content: $new_content; } is compiled to: #main { content: "First content"; new-content: "First time reference"; } ## `@`-Rules and Directives {#directives} Sass supports all CSS3 `@`-rules, as well as some additional Sass-specific ones known as "directives." These have various effects in Sass, detailed below. See also [control directives](#control-directives) and [mixin directives](#mixins). ### `@import` {#import} Sass extends the CSS `@import` rule to allow it to import SCSS and Sass files. All imported SCSS and Sass files will be merged together into a single CSS output file. In addition, any variables or [mixins](#mixins) defined in imported files can be used in the main file. Sass looks for other Sass files in the current directory, and the Sass file directory under Rack, Rails, or Merb. Additional search directories may be specified using the [`:load_paths`](#load_paths-option) option, or the `--load-path` option on the command line. `@import` takes a filename to import. By default, it looks for a Sass file to import directly, but there are a few circumstances under which it will compile to a CSS `@import` rule: * If the file's extension is `.css`. * If the filename begins with `http://`. * If the filename is a `url()`. * If the `@import` has any media queries. If none of the above conditions are met and the extension is `.scss` or `.sass`, then the named Sass or SCSS file will be imported. If there is no extension, Sass will try to find a file with that name and the `.scss` or `.sass` extension and import it. For example, @import "foo.scss"; or @import "foo"; would both import the file `foo.scss`, whereas @import "foo.css"; @import "foo" screen; @import "http://foo.com/bar"; @import url(foo); would all compile to @import "foo.css"; @import "foo" screen; @import "http://foo.com/bar"; @import url(foo); It's also possible to import multiple files in one `@import`. For example: @import "rounded-corners", "text-shadow"; would import both the `rounded-corners` and the `text-shadow` files. #### Partials {#partials} If you have a SCSS or Sass file that you want to import but don't want to compile to a CSS file, you can add an underscore to the beginning of the filename. This will tell Sass not to compile it to a normal CSS file. You can then import these files without using the underscore. For example, you might have `_colors.scss`. Then no `_colors.css` file would be created, and you can do @import "colors"; and `_colors.scss` would be imported. #### Nested `@import` {#nested-import} Although most of the time it's most useful to just have `@import`s at the top level of the document, it is possible to include them within CSS rules and `@media` rules. Like a base-level `@import`, this includes the contents of the `@import`ed file. However, the imported rules will be nested in the same place as the original `@import`. For example, if `example.scss` contains .example { color: red; } then #main { @import "example"; } would compile to #main .example { color: red; } Directives that are only allowed at the base level of a document, like `@mixin` or `@charset`, are not allowed in files that are `@import`ed in a nested context. It's not possible to nest `@import` within mixins or control directives. ### `@media` {#media} `@media` directives in Sass behave just like they do in plain CSS, with one extra capability: they can be nested in CSS rules. If a `@media` directive appears within a CSS rule, it will be bubbled up to the top level of the stylesheet, putting all the selectors on the way inside the rule. This makes it easy to add media-specific styles without having to repeat selectors or break the flow of the stylesheet. For example: .sidebar { width: 300px; @media screen and (orientation: landscape) { width: 500px; } } is compiled to: .sidebar { width: 300px; } @media screen and (orientation: landscape) { .sidebar { width: 500px; } } `@media` queries can also be nested within one another. The queries will then be combined using the `and` operator. For example: @media screen { .sidebar { @media (orientation: landscape) { width: 500px; } } } is compiled to: @media screen and (orientation: landscape) { .sidebar { width: 500px; } } ### `@extend` {#extend} There are often cases when designing a page when one class should have all the styles of another class, as well as its own specific styles. The most common way of handling this is to use both the more general class and the more specific class in the HTML. For example, suppose we have a design for a normal error and also for a serious error. We might write our markup like so:
    Oh no! You've been hacked!
    And our styles like so: .error { border: 1px #f00; background-color: #fdd; } .seriousError { border-width: 3px; } Unfortunately, this means that we have to always remember to use `.error` with `.seriousError`. This is a maintenance burden, leads to tricky bugs, and can bring non-semantic style concerns into the markup. The `@extend` directive avoids these problems by telling Sass that one selector should inherit the styles of another selector. For example: .error { border: 1px #f00; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; } This means that all styles defined for `.error` are also applied to `.seriousError`, in addition to the styles specific to `.seriousError`. In effect, everything with class `.seriousError` also has class `.error`. Other rules that use `.error` will work for `.seriousError` as well. For example, if we have special styles for errors caused by hackers: .error.intrusion { background-image: url("/image/hacked.png"); } Then `
    ` will have the `hacked.png` background image as well. #### How it Works `@extend` works by inserting the extending selector (e.g. `.seriousError`) anywhere in the stylesheet that the extended selector (.e.g `.error`) appears. Thus the example above: .error { border: 1px #f00; background-color: #fdd; } .error.intrusion { background-image: url("/image/hacked.png"); } .seriousError { @extend .error; border-width: 3px; } is compiled to: .error, .seriousError { border: 1px #f00; background-color: #fdd; } .error.intrusion, .seriousError.intrusion { background-image: url("/image/hacked.png"); } .seriousError { border-width: 3px; } When merging selectors, `@extend` is smart enough to avoid unnecessary duplication, so something like `.seriousError.seriousError` gets translated to `.seriousError`. In addition, it won't produce selectors that can't match anything, like `#main#footer`. #### Extending Complex Selectors Class selectors aren't the only things that can be extended. It's possible to extend any selector involving only a single element, such as `.special.cool`, `a:hover`, or `a.user[href^="http://"]`. For example: .hoverlink {@extend a:hover} Just like with classes, this means that all styles defined for `a:hover` are also applied to `.hoverlink`. For example: .hoverlink {@extend a:hover} a:hover {text-decoration: underline} is compiled to: a:hover, .hoverlink {text-decoration: underline} Just like with `.error.intrusion` above, any rule that uses `a:hover` will also work for `.hoverlink`, even if they have other selectors as well. For example: .hoverlink {@extend a:hover} .comment a.user:hover {font-weight: bold} is compiled to: .comment a.user:hover, .comment .hoverlink.user {font-weight: bold} #### Multiple Extends A single selector can extend more than one selector. This means that it inherits the styles of all the extended selectors. For example: .error { border: 1px #f00; background-color: #fdd; } .attention { font-size: 3em; background-color: #ff0; } .seriousError { @extend .error; @extend .attention; border-width: 3px; } is compiled to: .error, .seriousError { border: 1px #f00; background-color: #fdd; } .attention, .seriousError { font-size: 3em; background-color: #ff0; } .seriousError { border-width: 3px; } In effect, everything with class `.seriousError` also has class `.error` *and* class `.attention`. Thus, the styles defined later in the document take precedence: `.seriousError` has background color `#ff0` rather than `#fdd`, since `.attention` is defined later than `.error`. #### Chaining Extends It's possible for one selector to extend another selector that in turn extends a third. For example: .error { border: 1px #f00; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; } .criticalError { @extend .seriousError; position: fixed; top: 10%; bottom: 10%; left: 10%; right: 10%; } Now everything with class `.seriousError` also has class `.error`, and everything with class `.criticalError` has class `.seriousError` *and* class `.error`. It's compiled to: .error, .seriousError, .criticalError { border: 1px #f00; background-color: #fdd; } .seriousError, .criticalError { border-width: 3px; } .criticalError { position: fixed; top: 10%; bottom: 10%; left: 10%; right: 10%; } #### Selector Sequences Selector sequences, such as `.foo .bar` or `.foo + .bar`, currently can't be extended. However, it is possible for nested selectors themselves to use `@extend`. For example: #fake-links .link {@extend a} a { color: blue; &:hover {text-decoration: underline} } is compiled to a, #fake-links .link { color: blue; } a:hover, #fake-links .link:hover { text-decoration: underline; } ##### Merging Selector Sequences Sometimes a selector sequence extends another selector that appears in another sequence. In this case, the two sequences need to be merged. For example: #admin .tabbar a {font-weight: bold} #demo .overview .fakelink {@extend a} While it would technically be possible to generate all selectors that could possibly match either sequence, this would make the stylesheet far too large. The simple example above, for instance, would require ten selectors. Instead, Sass generates only selectors that are likely to be useful. When the two sequences being merged have no selectors in common, then two new selectors are generated: one with the first sequence before the second, and one with the second sequence before the first. For example: #admin .tabbar a {font-weight: bold} #demo .overview .fakelink {@extend a} is compiled to: #admin .tabbar a, #admin .tabbar #demo .overview .fakelink, #demo .overview #admin .tabbar .fakelink { font-weight: bold; } If the two sequences do share some selectors, then those selectors will be merged together and only the differences (if any still exist) will alternate. In this example, both sequences contain the id `#admin`, so the resulting selectors will merge those two ids: #admin .tabbar a {font-weight: bold} #admin .overview .fakelink {@extend a} This is compiled to: #admin .tabbar a, #admin .tabbar .overview .fakelink, #admin .overview .tabbar .fakelink { font-weight: bold; } ### `@debug` The `@debug` directive prints the value of a SassScript expression to the standard error output stream. It's useful for debugging Sass files that have complicated SassScript going on. For example: @debug 10em + 12em; outputs: Line 1 DEBUG: 22em ### `@warn` The `@warn` directive prints the value of a SassScript expression to the standard error output stream. It's useful for libraries that need to warn users of deprecations or recovering from minor mixin usage mistakes. There are two major distinctions between `@warn` and `@debug`: 1. You can turn warnings off with the `--quiet` command-line option or the `:quiet` Sass option. 2. A stylesheet trace will be printed out along with the message so that the user being warned can see where their styles caused the warning. Usage Example: @mixin adjust-location($x, $y) { @if unitless($x) { @warn "Assuming #{$x} to be in pixels"; $x: 1px * $x; } @if unitless($y) { @warn "Assuming #{$y} to be in pixels"; $y: 1px * $y; } position: relative; left: $x; top: $y; } ## Control Directives SassScript supports basic control directives for including styles only under some conditions or including the same style several times with variations. **Note that control directives are an advanced feature, and are not recommended in the course of day-to-day styling**. They exist mainly for use in [mixins](#mixins), particularly those that are part of libraries like [Compass](http://compass-style.org), and so require substantial flexibility. ### `@if` The `@if` directive takes a SassScript expression and uses the styles nested beneath it if the expression returns anything other than `false`: p { @if 1 + 1 == 2 { border: 1px solid; } @if 5 < 3 { border: 2px dotted; } } is compiled to: p { border: 1px solid; } The `@if` statement can be followed by several `@else if` statements and one `@else` statement. If the `@if` statement fails, the `@else if` statements are tried in order until one succeeds or the `@else` is reached. For example: $type: monster; p { @if $type == ocean { color: blue; } @else if $type == matador { color: red; } @else if $type == monster { color: green; } @else { color: black; } } is compiled to: p { color: green; } ### `@for` The `@for` directive has two forms: `@for $var from to ` or `@for $var from through `. `$var` can be any variable name, like `$i`, and `` and `` are SassScript expressions that should return integers. The `@for` statement sets `$var` to each number from `` to ``, including `` if `through` is used. Then it outputs the nested styles using that value of `$var`. For example: @for $i from 1 through 3 { .item-#{$i} { width: 2em * $i; } } is compiled to: .item-1 { width: 2em; } .item-2 { width: 4em; } .item-3 { width: 6em; } ### `@each` {#each-directive} The `@each` rule has the form `@each $var in `. `$var` can be any variable name, like `$length` or `$name`, and `` is a SassScript expression that returns a list. The `@each` rule sets `$var` to each item in the list, then outputs the styles it contains using that value of `$var`. For example: @each $animal in puma, sea-slug, egret, salamander { .#{$animal}-icon { background-image: url('/images/#{$animal}.png'); } } is compiled to: .puma-icon { background-image: url('/images/puma.png'); } .sea-slug-icon { background-image: url('/images/sea-slug.png'); } .egret-icon { background-image: url('/images/egret.png'); } .salamander-icon { background-image: url('/images/salamander.png'); } ### `@while` The `@while` directive takes a SassScript expression and repeatedly outputs the nested styles until the statement evaluates to `false`. This can be used to achieve more complex looping than the `@for` statement is capable of, although this is rarely necessary. For example: $i: 6; @while $i > 0 { .item-#{$i} { width: 2em * $i; } $i: $i - 2; } is compiled to: .item-6 { width: 12em; } .item-4 { width: 8em; } .item-2 { width: 4em; } ## Mixin Directives {#mixins} Mixins allow you to define styles that can be re-used throughout the stylesheet without needing to resort to non-semantic classes like `.float-left`. Mixins can also contain full CSS rules, and anything else allowed elsewhere in a Sass document. They can even take [arguments](#mixin-arguments) which allows you to produce a wide variety of styles with very few mixins. ### Defining a Mixin: `@mixin` {#defining_a_mixin} Mixins are defined with the `@mixin` directive. It's followed by the name of the mixin and optionally the [arguments](#mixin-arguments), and a block containing the contents of the mixin. For example, the `large-text` mixin is defined as follows: @mixin large-text { font: { family: Arial; size: 20px; weight: bold; } color: #ff0000; } Mixins may also contain selectors, possibly mixed with properties. The selectors can even contain [parent references](#referencing_parent_selectors_). For example: @mixin clearfix { display: inline-block; &:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } * html & { height: 1px } } ### Including a Mixin: `@include` {#including_a_mixin} Mixins are included in the document with the `@include` directive. This takes the name of a mixin and optionally [arguments to pass to it](#mixin-arguments), and includes the styles defined by that mixin into the current rule. For example: .page-title { @include large-text; padding: 4px; margin-top: 10px; } is compiled to: .page-title { font-family: Arial; font-size: 20px; font-weight: bold; color: #ff0000; padding: 4px; margin-top: 10px; } Mixins may also be included outside of any rule (that is, at the root of the document) as long as they don't directly define any properties or use any parent references. For example: @mixin silly-links { a { color: blue; background-color: red; } } @include silly-links; is compiled to: a { color: blue; background-color: red; } Mixin definitions can also include other mixins. For example: @mixin compound { @include highlighted-background; @include header-text; } @mixin highlighted-background { background-color: #fc0; } @mixin header-text { font-size: 20px; } Mixins that only define descendent selectors, can be safely mixed into the top most level of a document. ### Arguments {#mixin-arguments} Mixins can take arguments SassScript values as arguments, which are given when the mixin is included and made available within the mixin as variables. When defining a mixin, the arguments are written as variable names separated by commas, all in parentheses after the name. Then when including the mixin, values can be passed in in the same manner. For example: @mixin sexy-border($color, $width) { border: { color: $color; width: $width; style: dashed; } } p { @include sexy-border(blue, 1in); } is compiled to: p { border-color: blue; border-width: 1in; border-style: dashed; } Mixins can also specify default values for their arguments using the normal variable-setting syntax. Then when the mixin is included, if it doesn't pass in that argument, the default value will be used instead. For example: @mixin sexy-border($color, $width: 1in) { border: { color: $color; width: $width; style: dashed; } } p { @include sexy-border(blue); } h1 { @include sexy-border(blue, 2in); } is compiled to: p { border-color: blue; border-width: 1in; border-style: dashed; } h1 { border-color: blue; border-width: 2in; border-style: dashed; } #### Keyword Arguments Mixins can also be included using explicit keyword arguments. For instance, we the above example could be written as: p { @include sexy-border($color: blue); } h1 { @include sexy-border($color: blue, $width: 2in); } While this is less concise, it can make the stylesheet easier to read. It also allows functions to present more flexible interfaces, providing many arguments without becoming difficult to call. Named arguments can be passed in any order, and arguments with default values can be omitted. Since the named arguments are variable names, underscores and dashes can be used interchangeably. ## Function Directives {#functions} It is possible to define your own functions in sass and use them in any value or script context. For example: $grid-width: 40px; $gutter-width: 10px; @function grid-width($n) { @return $n * $grid-width + ($n - 1) * $gutter-width; } #sidebar { width: grid-width(5); } Becomes: #sidebar { width: 240px; } As you can see functions can access any globally defined variables as well as accept arguments just like a mixin. A function may have several statements contained within it, and you must call `@return` to set the return value of the function. As with mixins, you can call Sass-defined functions using keyword arguments. In the above example we could have called the function like this: #sidebar { width: grid-width($n: 5); } It is recommended that you prefix your functions to avoid naming conflicts and so that readers of your stylesheets know they are not part of Sass or CSS. For example, if you work for ACME Corp, you might have named the function above `-acme-grid-width`. ## Output Style Although the default CSS style that Sass outputs is very nice and reflects the structure of the document, tastes and needs vary and so Sass supports several other styles. Sass allows you to choose between four different output styles by setting the [`:style` option](#style-option) or using the `--style` command-line flag. ### `:nested` Nested style is the default Sass style, because it reflects the structure of the CSS styles and the HTML document they're styling. Each property has its own line, but the indentation isn't constant. Each rule is indented based on how deeply it's nested. For example: #main { color: #fff; background-color: #000; } #main p { width: 10em; } .huge { font-size: 10em; font-weight: bold; text-decoration: underline; } Nested style is very useful when looking at large CSS files: it allows you to easily grasp the structure of the file without actually reading anything. ### `:expanded` Expanded is a more typical human-made CSS style, with each property and rule taking up one line. Properties are indented within the rules, but the rules aren't indented in any special way. For example: #main { color: #fff; background-color: #000; } #main p { width: 10em; } .huge { font-size: 10em; font-weight: bold; text-decoration: underline; } ### `:compact` Compact style takes up less space than Nested or Expanded. It also draws the focus more to the selectors than to their properties. Each CSS rule takes up only one line, with every property defined on that line. Nested rules are placed next to each other with no newline, while separate groups of rules have newlines between them. For example: #main { color: #fff; background-color: #000; } #main p { width: 10em; } .huge { font-size: 10em; font-weight: bold; text-decoration: underline; } ### `:compressed` Compressed style takes up the minimum amount of space possible, having no whitespace except that necessary to separate selectors and a newline at the end of the file. It also includes some other minor compressions, such as choosing the smallest representation for colors. It's not meant to be human-readable. For example: #main{color:#fff;background-color:#000}#main p{width:10em}.huge{font-size:10em;font-weight:bold;text-decoration:underline} ## Extending Sass Sass provides a number of advanced customizations for users with unique requirements. Using these features requires a strong understanding of Ruby. ### Defining Custom Sass Functions Users can define their own Sass functions using the Ruby API. For more information, see the [source documentation](Sass/Script/Functions.html#adding_custom_functions). ### Cache Stores Sass caches parsed documents so that they can be reused without parsing them again unless they have changed. By default, Sass will write these cache files to a location on the filesystem indicated by [`:cache_location`](#cache_location-option). If you cannot write to the filesystem or need to share cache across ruby processes or machines, then you can define your own cache store and set the[`:cache_store` option](#cache_store-option). For details on creating your own cache store, please see the {Sass::CacheStores::Base source documentation}. ### Custom Importers Sass importers are in charge of taking paths passed to `@import` and finding the appropriate Sass code for those paths. By default, this code is loaded from the {Sass::Importers::Filesystem filesystem}, but importers could be added to load from a database, over HTTP, or use a different file naming scheme than what Sass expects. Each importer is in charge of a single load path (or whatever the corresponding notion is for the backend). Importers can be placed in the {file:SASS_REFERENCE.md#load_paths-option `:load_paths` array} alongside normal filesystem paths. When resolving an `@import`, Sass will go through the load paths looking for an importer that successfully imports the path. Once one is found, the imported file is used. User-created importers must inherit from {Sass::Importers::Base}. stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/bin/0000775000175000017500000000000012206724733031600 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/bin/scss0000775000175000017500000000025012206724733032476 0ustar jamespagejamespage#!/usr/bin/env ruby # The command line Sass parser. require File.dirname(__FILE__) + '/../lib/sass' require 'sass/exec' opts = Sass::Exec::Scss.new(ARGV) opts.parse! stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/bin/sass0000775000175000017500000000025012206724733032474 0ustar jamespagejamespage#!/usr/bin/env ruby # The command line Sass parser. require File.dirname(__FILE__) + '/../lib/sass' require 'sass/exec' opts = Sass::Exec::Sass.new(ARGV) opts.parse! ././@LongLink0000644000000000000000000000014712255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/bin/sass-convertstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/bin/sass-conve0000775000175000017500000000021712206724733033607 0ustar jamespagejamespage#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../lib/sass' require 'sass/exec' opts = Sass::Exec::SassConvert.new(ARGV) opts.parse! stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/0000775000175000017500000000000012206724733031576 5ustar jamespagejamespagestapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass.rb0000664000175000017500000000526012206724733033077 0ustar jamespagejamespagedir = File.dirname(__FILE__) $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir) # This is necessary to set so that the Haml code that tries to load Sass # knows that Sass is indeed loading, # even if there's some crazy autoload stuff going on. SASS_BEGUN_TO_LOAD = true unless defined?(SASS_BEGUN_TO_LOAD) require 'sass/version' # The module that contains everything Sass-related: # # * {Sass::Engine} is the class used to render Sass/SCSS within Ruby code. # * {Sass::Plugin} is interfaces with web frameworks (Rails and Merb in particular). # * {Sass::SyntaxError} is raised when Sass encounters an error. # * {Sass::CSS} handles conversion of CSS to Sass. # # Also see the {file:SASS_REFERENCE.md full Sass reference}. module Sass # Compile a Sass or SCSS string to CSS. # Defaults to SCSS. # # @param contents [String] The contents of the Sass file. # @param options [{Symbol => Object}] An options hash; # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation} # @raise [Sass::SyntaxError] if there's an error in the document # @raise [Encoding::UndefinedConversionError] if the source encoding # cannot be converted to UTF-8 # @raise [ArgumentError] if the document uses an unknown encoding with `@charset` def self.compile(contents, options = {}) options[:syntax] ||= :scss Engine.new(contents, options).to_css end # Compile a file on disk to CSS. # # @param filename [String] The path to the Sass, SCSS, or CSS file on disk. # @param options [{Symbol => Object}] An options hash; # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation} # @raise [Sass::SyntaxError] if there's an error in the document # @raise [Encoding::UndefinedConversionError] if the source encoding # cannot be converted to UTF-8 # @raise [ArgumentError] if the document uses an unknown encoding with `@charset` # # @overload compile_file(filename, options = {}) # Return the compiled CSS rather than writing it to a file. # # @return [String] The compiled CSS. # # @overload compile_file(filename, css_filename, options = {}) # Write the compiled CSS to a file. # # @param css_filename [String] The location to which to write the compiled CSS. def self.compile_file(filename, *args) options = args.last.is_a?(Hash) ? args.pop : {} css_filename = args.shift result = Sass::Engine.for_file(filename, options).render if css_filename options[:css_filename] ||= css_filename open(css_filename,"w") {|css_file| css_file.write(result)} nil else result end end end require 'sass/util' require 'sass/engine' require 'sass/plugin' if defined?(Merb::Plugins) require 'sass/railtie' stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/0000775000175000017500000000000012206724733032547 5ustar jamespagejamespage././@LongLink0000644000000000000000000000014712255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugin/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugi0000775000175000017500000000000012206724733033610 5ustar jamespagejamespage././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugin/rack.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugi0000664000175000017500000000340212206724733033611 0ustar jamespagejamespagemodule Sass module Plugin # Rack middleware for compiling Sass code. # # ## Activate # # require 'sass/plugin/rack' # use Sass::Plugin::Rack # # ## Customize # # Sass::Plugin.options.merge( # :cache_location => './tmp/sass-cache', # :never_update => environment != :production, # :full_exception => environment != :production) # # {file:SASS_REFERENCE.md#options See the Reference for more options}. # # ## Use # # Put your Sass files in `public/stylesheets/sass`. # Your CSS will be generated in `public/stylesheets`, # and regenerated every request if necessary. # The locations and frequency {file:SASS_REFERENCE.md#options can be customized}. # That's all there is to it! class Rack # The delay, in seconds, between update checks. # Useful when many resources are requested for a single page. # `nil` means no delay at all. # # @return [Float] attr_accessor :dwell # Initialize the middleware. # # @param app [#call] The Rack application # @param dwell [Float] See \{#dwell} def initialize(app, dwell = 1.0) @app = app @dwell = dwell @check_after = Time.now.to_f end # Process a request, checking the Sass stylesheets for changes # and updating them if necessary. # # @param env The Rack request environment # @return [(#to_i, {String => String}, Object)] The Rack response def call(env) if @dwell.nil? || Time.now.to_f > @check_after Sass::Plugin.check_for_updates @check_after = Time.now.to_f + @dwell if @dwell end @app.call(env) end end end end require 'sass/plugin' ././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugin/merb.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugi0000664000175000017500000000261112206724733033612 0ustar jamespagejamespageunless defined?(Sass::MERB_LOADED) Sass::MERB_LOADED = true module Sass::Plugin::Configuration # Different default options in a m envirionment. def default_options @default_options ||= begin version = Merb::VERSION.split('.').map { |n| n.to_i } if version[0] <= 0 && version[1] < 5 root = MERB_ROOT env = MERB_ENV else root = Merb.root.to_s env = Merb.environment end { :always_update => false, :template_location => root + '/public/stylesheets/sass', :css_location => root + '/public/stylesheets', :cache_location => root + '/tmp/sass-cache', :always_check => env != "production", :quiet => env != "production", :full_exception => env != "production" }.freeze end end end config = Merb::Plugins.config[:sass] || Merb::Plugins.config["sass"] || {} if defined? config.symbolize_keys! config.symbolize_keys! end Sass::Plugin.options.merge!(config) require 'sass/plugin/rack' class Sass::Plugin::MerbBootLoader < Merb::BootLoader after Merb::BootLoader::RackUpApplication def self.run # Apparently there's no better way than this to add Sass # to Merb's Rack stack. Merb::Config[:app] = Sass::Plugin::Rack.new(Merb::Config[:app]) end end end ././@LongLink0000644000000000000000000000017312255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugin/staleness_checker.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugi0000664000175000017500000001611212206724733033613 0ustar jamespagejamespagemodule Sass module Plugin # The class handles `.s[ca]ss` file staleness checks via their mtime timestamps. # # To speed things up two level of caches are employed: # # * A class-level dependency cache which stores @import paths for each file. # This is a long-lived cache that is reused by every StalenessChecker instance. # * Three short-lived instance-level caches, one for file mtimes, # one for whether a file is stale during this particular run. # and one for the parse tree for a file. # These are only used by a single StalenessChecker instance. # # Usage: # # * For a one-off staleness check of a single `.s[ca]ss` file, # the class-level {stylesheet_needs_update?} method # should be used. # * For a series of staleness checks (e.g. checking all files for staleness) # a StalenessChecker instance should be created, # and the instance-level \{#stylesheet\_needs\_update?} method should be used. # the caches should make the whole process significantly faster. # *WARNING*: It is important not to retain the instance for too long, # as its instance-level caches are never explicitly expired. class StalenessChecker @dependencies_cache = {} class << self # TODO: attach this to a compiler instance. # @private attr_accessor :dependencies_cache end # Creates a new StalenessChecker # for checking the staleness of several stylesheets at once. # # @param options [{Symbol => Object}] # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}. def initialize(options) @dependencies = self.class.dependencies_cache # Entries in the following instance-level caches are never explicitly expired. # Instead they are supposed to automaticaly go out of scope when a series of staleness checks # (this instance of StalenessChecker was created for) is finished. @mtimes, @dependencies_stale, @parse_trees = {}, {}, {} @options = Sass::Engine.normalize_options(options) end # Returns whether or not a given CSS file is out of date # and needs to be regenerated. # # @param css_file [String] The location of the CSS file to check. # @param template_file [String] The location of the Sass or SCSS template # that is compiled to `css_file`. # @return [Boolean] Whether the stylesheet needs to be updated. def stylesheet_needs_update?(css_file, template_file, importer = nil) template_file = File.expand_path(template_file) begin css_mtime = File.mtime(css_file) rescue Errno::ENOENT return true end stylesheet_modified_since?(template_file, css_mtime, importer) end # Returns whether a Sass or SCSS stylesheet has been modified since a given time. # # @param template_file [String] The location of the Sass or SCSS template. # @param mtime [Fixnum] The modification time to check against. # @param importer [Sass::Importers::Base] The importer used to locate the stylesheet. # Defaults to the filesystem importer. # @return [Boolean] Whether the stylesheet has been modified. def stylesheet_modified_since?(template_file, mtime, importer = nil) importer ||= @options[:filesystem_importer].new(".") dependency_updated?(mtime).call(template_file, importer) end # Returns whether or not a given CSS file is out of date # and needs to be regenerated. # # The distinction between this method and the instance-level \{#stylesheet\_needs\_update?} # is that the instance method preserves mtime and stale-dependency caches, # so it's better to use when checking multiple stylesheets at once. # # @param css_file [String] The location of the CSS file to check. # @param template_file [String] The location of the Sass or SCSS template # that is compiled to `css_file`. # @return [Boolean] Whether the stylesheet needs to be updated. def self.stylesheet_needs_update?(css_file, template_file, importer = nil) new(Plugin.engine_options).stylesheet_needs_update?(css_file, template_file, importer) end # Returns whether a Sass or SCSS stylesheet has been modified since a given time. # # The distinction between this method and the instance-level \{#stylesheet\_modified\_since?} # is that the instance method preserves mtime and stale-dependency caches, # so it's better to use when checking multiple stylesheets at once. # # @param template_file [String] The location of the Sass or SCSS template. # @param mtime [Fixnum] The modification time to check against. # @param importer [Sass::Importers::Base] The importer used to locate the stylesheet. # Defaults to the filesystem importer. # @return [Boolean] Whether the stylesheet has been modified. def self.stylesheet_modified_since?(template_file, mtime, importer = nil) new(Plugin.engine_options).stylesheet_modified_since?(template_file, mtime, importer) end private def dependencies_stale?(uri, importer, css_mtime) timestamps = @dependencies_stale[[uri, importer]] ||= {} timestamps.each_pair do |checked_css_mtime, is_stale| if checked_css_mtime <= css_mtime && !is_stale return false elsif checked_css_mtime > css_mtime && is_stale return true end end timestamps[css_mtime] = dependencies(uri, importer).any?(&dependency_updated?(css_mtime)) rescue Sass::SyntaxError # If there's an error finding dependencies, default to recompiling. true end def mtime(uri, importer) @mtimes[[uri, importer]] ||= begin mtime = importer.mtime(uri, @options) if mtime.nil? @dependencies.delete([uri, importer]) nil else mtime end end end def dependencies(uri, importer) stored_mtime, dependencies = @dependencies[[uri, importer]] if !stored_mtime || stored_mtime < mtime(uri, importer) dependencies = compute_dependencies(uri, importer) @dependencies[[uri, importer]] = [mtime(uri, importer), dependencies] end dependencies end def dependency_updated?(css_mtime) Proc.new do |uri, importer| sass_mtime = mtime(uri, importer) !sass_mtime || sass_mtime > css_mtime || dependencies_stale?(uri, importer, css_mtime) end end def compute_dependencies(uri, importer) tree(uri, importer).grep(Tree::ImportNode) do |n| next if n.css_import? file = n.imported_file key = [file.options[:filename], file.options[:importer]] @parse_trees[key] = file.to_tree key end.compact end def tree(uri, importer) @parse_trees[[uri, importer]] ||= importer.find(uri, @options).to_tree end end end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugin/compiler.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugi0000664000175000017500000003203512206724733033615 0ustar jamespagejamespagerequire 'fileutils' require 'sass' # XXX CE: is this still necessary now that we have the compiler class? require 'sass/callbacks' require 'sass/plugin/configuration' require 'sass/plugin/staleness_checker' module Sass::Plugin # The Compiler class handles compilation of multiple files and/or directories, # including checking which CSS files are out-of-date and need to be updated # and calling Sass to perform the compilation on those files. # # {Sass::Plugin} uses this class to update stylesheets for a single application. # Unlike {Sass::Plugin}, though, the Compiler class has no global state, # and so multiple instances may be created and used independently. # # If you need to compile a Sass string into CSS, # please see the {Sass::Engine} class. # # Unlike {Sass::Plugin}, this class doesn't keep track of # whether or how many times a stylesheet should be updated. # Therefore, the following `Sass::Plugin` options are ignored by the Compiler: # # * `:never_update` # * `:always_check` class Compiler include Sass::Util include Configuration extend Sass::Callbacks # Creates a new compiler. # # @param options [{Symbol => Object}] # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}. def initialize(options = {}) self.options.merge!(options) end # Register a callback to be run before stylesheets are mass-updated. # This is run whenever \{#update\_stylesheets} is called, # unless the \{file:SASS_REFERENCE.md#never_update-option `:never_update` option} # is enabled. # # @yield [individual_files] # @yieldparam individual_files [<(String, String)>] # Individual files to be updated, in addition to the directories # specified in the options. # The first element of each pair is the source file, # the second is the target CSS file. define_callback :updating_stylesheets # Register a callback to be run before a single stylesheet is updated. # The callback is only run if the stylesheet is guaranteed to be updated; # if the CSS file is fresh, this won't be run. # # Even if the \{file:SASS_REFERENCE.md#full_exception-option `:full_exception` option} # is enabled, this callback won't be run # when an exception CSS file is being written. # To run an action for those files, use \{#on\_compilation\_error}. # # @yield [template, css] # @yieldparam template [String] # The location of the Sass/SCSS file being updated. # @yieldparam css [String] # The location of the CSS file being generated. define_callback :updating_stylesheet # Register a callback to be run when Sass decides not to update a stylesheet. # In particular, the callback is run when Sass finds that # the template file and none of its dependencies # have been modified since the last compilation. # # Note that this is **not** run when the # \{file:SASS_REFERENCE.md#never-update_option `:never_update` option} is set, # nor when Sass decides not to compile a partial. # # @yield [template, css] # @yieldparam template [String] # The location of the Sass/SCSS file not being updated. # @yieldparam css [String] # The location of the CSS file not being generated. define_callback :not_updating_stylesheet # Register a callback to be run when there's an error # compiling a Sass file. # This could include not only errors in the Sass document, # but also errors accessing the file at all. # # @yield [error, template, css] # @yieldparam error [Exception] The exception that was raised. # @yieldparam template [String] # The location of the Sass/SCSS file being updated. # @yieldparam css [String] # The location of the CSS file being generated. define_callback :compilation_error # Register a callback to be run when Sass creates a directory # into which to put CSS files. # # Note that even if multiple levels of directories need to be created, # the callback may only be run once. # For example, if "foo/" exists and "foo/bar/baz/" needs to be created, # this may only be run for "foo/bar/baz/". # This is not a guarantee, however; # it may also be run for "foo/bar/". # # @yield [dirname] # @yieldparam dirname [String] # The location of the directory that was created. define_callback :creating_directory # Register a callback to be run when Sass detects # that a template has been modified. # This is only run when using \{#watch}. # # @yield [template] # @yieldparam template [String] # The location of the template that was modified. define_callback :template_modified # Register a callback to be run when Sass detects # that a new template has been created. # This is only run when using \{#watch}. # # @yield [template] # @yieldparam template [String] # The location of the template that was created. define_callback :template_created # Register a callback to be run when Sass detects # that a template has been deleted. # This is only run when using \{#watch}. # # @yield [template] # @yieldparam template [String] # The location of the template that was deleted. define_callback :template_deleted # Register a callback to be run when Sass deletes a CSS file. # This happens when the corresponding Sass/SCSS file has been deleted. # # @yield [filename] # @yieldparam filename [String] # The location of the CSS file that was deleted. define_callback :deleting_css # Updates out-of-date stylesheets. # # Checks each Sass/SCSS file in {file:SASS_REFERENCE.md#template_location-option `:template_location`} # to see if it's been modified more recently than the corresponding CSS file # in {file:SASS_REFERENCE.md#css_location-option `:css_location`}. # If it has, it updates the CSS file. # # @param individual_files [Array<(String, String)>] # A list of files to check for updates # **in addition to those specified by the # {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.** # The first string in each pair is the location of the Sass/SCSS file, # the second is the location of the CSS file that it should be compiled to. def update_stylesheets(individual_files = []) run_updating_stylesheets individual_files Sass::Plugin.checked_for_updates = true staleness_checker = StalenessChecker.new(engine_options) individual_files.each do |t, c| if options[:always_update] || staleness_checker.stylesheet_needs_update?(c, t) update_stylesheet(t, c) end end template_location_array.each do |template_location, css_location| Dir.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file| # Get the relative path to the file name = file.sub(template_location.to_s.sub(/\/*$/, '/'), "") css = css_filename(name, css_location) if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file) update_stylesheet file, css else run_not_updating_stylesheet file, css end end end end # Watches the template directory (or directories) # and updates the CSS files whenever the related Sass/SCSS files change. # `watch` never returns. # # Whenever a change is detected to a Sass/SCSS file in # {file:SASS_REFERENCE.md#template_location-option `:template_location`}, # the corresponding CSS file in {file:SASS_REFERENCE.md#css_location-option `:css_location`} # will be recompiled. # The CSS files of any Sass/SCSS files that import the changed file will also be recompiled. # # Before the watching starts in earnest, `watch` calls \{#update\_stylesheets}. # # Note that `watch` uses the [FSSM](http://github.com/ttilley/fssm) library # to monitor the filesystem for changes. # FSSM isn't loaded until `watch` is run. # The version of FSSM distributed with Sass is loaded by default, # but if another version has already been loaded that will be used instead. # # @param individual_files [Array<(String, String)>] # A list of files to watch for updates # **in addition to those specified by the # {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.** # The first string in each pair is the location of the Sass/SCSS file, # the second is the location of the CSS file that it should be compiled to. def watch(individual_files = []) update_stylesheets(individual_files) begin require 'fssm' rescue LoadError => e dir = Sass::Util.scope("vendor/fssm/lib") if $LOAD_PATH.include?(dir) e.message << "\n" << if File.exists?(scope(".git")) 'Run "git submodule update --init" to get the recommended version.' else 'Run "gem install fssm" to get it.' end raise e else $LOAD_PATH.unshift dir retry end end unless individual_files.empty? && FSSM::Backends::Default.name == "FSSM::Backends::FSEvents" # As of FSSM 0.1.4, it doesn't support FSevents on individual files, # but it also isn't smart enough to switch to polling itself. require 'fssm/backends/polling' Sass::Util.silence_warnings do FSSM::Backends.const_set(:Default, FSSM::Backends::Polling) end end # TODO: Keep better track of what depends on what # so we don't have to run a global update every time anything changes. FSSM.monitor do |mon| template_location_array.each do |template_location, css_location| mon.path template_location do |path| path.glob '**/*.s[ac]ss' path.update do |base, relative| run_template_modified File.join(base, relative) update_stylesheets(individual_files) end path.create do |base, relative| run_template_created File.join(base, relative) update_stylesheets(individual_files) end path.delete do |base, relative| run_template_deleted File.join(base, relative) css = File.join(css_location, relative.gsub(/\.s[ac]ss$/, '.css')) try_delete_css css update_stylesheets(individual_files) end end end individual_files.each do |template, css| mon.file template do |path| path.update do run_template_modified template update_stylesheets(individual_files) end path.create do run_template_created template update_stylesheets(individual_files) end path.delete do run_template_deleted template try_delete_css css update_stylesheets(individual_files) end end end end end # Non-destructively modifies \{#options} so that default values are properly set, # and returns the result. # # @param additional_options [{Symbol => Object}] An options hash with which to merge \{#options} # @return [{Symbol => Object}] The modified options hash def engine_options(additional_options = {}) opts = options.merge(additional_options) opts[:load_paths] = load_paths(opts) opts end # Compass expects this to exist def stylesheet_needs_update?(css_file, template_file) StalenessChecker.stylesheet_needs_update?(css_file, template_file) end private def update_stylesheet(filename, css) dir = File.dirname(css) unless File.exists?(dir) run_creating_directory dir FileUtils.mkdir_p dir end begin File.read(filename) unless File.readable?(filename) # triggers an error for handling engine_opts = engine_options(:css_filename => css, :filename => filename) result = Sass::Engine.for_file(filename, engine_opts).render rescue Exception => e run_compilation_error e, filename, css result = Sass::SyntaxError.exception_to_css(e, options) else run_updating_stylesheet filename, css end # Finally, write the file flag = 'w' flag = 'wb' if Sass::Util.windows? && options[:unix_newlines] File.open(css, flag) do |file| file.set_encoding(result.encoding) unless Sass::Util.ruby1_8? file.print(result) end end def try_delete_css(css) return unless File.exists?(css) run_deleting_css css File.delete css end def load_paths(opts = options) (opts[:load_paths] || []) + template_locations end def template_locations template_location_array.to_a.map {|l| l.first} end def css_locations template_location_array.to_a.map {|l| l.last} end def css_filename(name, path) "#{path}/#{name}".gsub(/\.s[ac]ss$/, '.css') end end end ././@LongLink0000644000000000000000000000015712255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugin/rails.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugi0000664000175000017500000000301012206724733033604 0ustar jamespagejamespageunless defined?(Sass::RAILS_LOADED) Sass::RAILS_LOADED = true module Sass::Plugin::Configuration # Different default options in a rails envirionment. def default_options return @default_options if @default_options opts = { :quiet => Sass::Util.rails_env != "production", :full_exception => Sass::Util.rails_env != "production", :cache_location => Sass::Util.rails_root + '/tmp/sass-cache' } opts.merge!( :always_update => false, :template_location => Sass::Util.rails_root + '/public/stylesheets/sass', :css_location => Sass::Util.rails_root + '/public/stylesheets', :always_check => Sass::Util.rails_env == "development") @default_options = opts.freeze end end Sass::Plugin.options.reverse_merge!(Sass::Plugin.default_options) # Rails 3.1 loads and handles Sass all on its own if defined?(ActionController::Metal) # 3.1 > Rails >= 3.0 require 'sass/plugin/rack' Rails.configuration.middleware.use(Sass::Plugin::Rack) elsif defined?(ActionController::Dispatcher) && defined?(ActionController::Dispatcher.middleware) # Rails >= 2.3 require 'sass/plugin/rack' ActionController::Dispatcher.middleware.use(Sass::Plugin::Rack) else module ActionController class Base alias_method :sass_old_process, :process def process(*args) Sass::Plugin.check_for_updates sass_old_process(*args) end end end end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugin/generic.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugi0000664000175000017500000000116512206724733033615 0ustar jamespagejamespage# The reason some options are declared here rather than in sass/plugin/configuration.rb # is that otherwise they'd clobber the Rails-specific options. # Since Rails' options are lazy-loaded in Rails 3, # they're reverse-merged with the default options # so that user configuration is preserved. # This means that defaults that differ from Rails' # must be declared here. unless defined?(Sass::GENERIC_LOADED) Sass::GENERIC_LOADED = true Sass::Plugin.options.merge!(:css_location => './public/stylesheets', :always_update => false, :always_check => true) end ././@LongLink0000644000000000000000000000016712255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugin/configuration.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/plugi0000664000175000017500000001165412206724733033621 0ustar jamespagejamespage# We keep configuration in its own self-contained file # so that we can load it independently in Rails 3, # where the full plugin stuff is lazy-loaded. module Sass module Plugin module Configuration # Returns the default options for a {Sass::Plugin::Compiler}. # # @return [{Symbol => Object}] def default_options @default_options ||= { :css_location => './public/stylesheets', :always_update => false, :always_check => true, :full_exception => true, :cache_location => ".sass-cache" }.freeze end # Resets the options and {Sass::Callbacks::InstanceMethods#clear_callbacks! clears all callbacks}. def reset! @options = nil clear_callbacks! end # An options hash. # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}. # # @return [{Symbol => Object}] def options @options ||= default_options.dup @options[:cache_store] ||= Sass::CacheStores::Filesystem.new(@options[:cache_location]) @options end # Sets the options hash. # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}. # See {Sass::Plugin::Configuration#reset!} # @deprecated Instead, modify the options hash in-place. # @param value [{Symbol => Object}] The options hash def options=(value) Sass::Util.sass_warn("Setting Sass::Plugin.options is deprecated " + "and will be removed in a future release.") options.merge!(value) end # Adds a new template-location/css-location mapping. # This means that Sass/SCSS files in `template_location` # will be compiled to CSS files in `css_location`. # # This is preferred over manually manipulating the {file:SASS_REFERENCE.md#template_location-option `:template_location` option} # since the option can be in multiple formats. # # Note that this method will change `options[:template_location]` # to be in the Array format. # This means that even if `options[:template_location]` # had previously been a Hash or a String, # it will now be an Array. # # @param template_location [String] The location where Sass/SCSS files will be. # @param css_location [String] The location where compiled CSS files will go. def add_template_location(template_location, css_location = options[:css_location]) normalize_template_location! template_location_array << [template_location, css_location] end # Removes a template-location/css-location mapping. # This means that Sass/SCSS files in `template_location` # will no longer be compiled to CSS files in `css_location`. # # This is preferred over manually manipulating the {file:SASS_REFERENCE.md#template_location-option `:template_location` option} # since the option can be in multiple formats. # # Note that this method will change `options[:template_location]` # to be in the Array format. # This means that even if `options[:template_location]` # had previously been a Hash or a String, # it will now be an Array. # # @param template_location [String] # The location where Sass/SCSS files were, # which is now going to be ignored. # @param css_location [String] # The location where compiled CSS files went, but will no longer go. # @return [Boolean] # Non-`nil` if the given mapping already existed and was removed, # or `nil` if nothing was changed. def remove_template_location(template_location, css_location = options[:css_location]) normalize_template_location! template_location_array.delete([template_location, css_location]) end # Returns the template locations configured for Sass # as an array of `[template_location, css_location]` pairs. # See the {file:SASS_REFERENCE.md#template_location-option `:template_location` option} # for details. # # @return [Array<(String, String)>] # An array of `[template_location, css_location]` pairs. def template_location_array old_template_location = options[:template_location] normalize_template_location! options[:template_location] ensure options[:template_location] = old_template_location end private def normalize_template_location! return if options[:template_location].is_a?(Array) options[:template_location] = case options[:template_location] when nil options[:css_location] ? [[File.join(options[:css_location], 'sass'), options[:css_location]]] : [] when String; [[options[:template_location], options[:css_location]]] else; options[:template_location].to_a end end end end end ././@LongLink0000644000000000000000000000014712255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/root.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/root.0000664000175000017500000000040212206724733033527 0ustar jamespagejamespagemodule Sass # The root directory of the Sass source tree. # This may be overridden by the package manager # if the lib directory is separated from the main source tree. # @api public ROOT_DIR = File.expand_path(File.join(__FILE__, "../../..")) end ././@LongLink0000644000000000000000000000014712255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000775000175000017500000000000012206724733033610 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016312255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/operation.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000000555112206724733033620 0ustar jamespagejamespagerequire 'set' require 'sass/script/string' require 'sass/script/number' require 'sass/script/color' require 'sass/script/functions' require 'sass/script/unary_operation' require 'sass/script/interpolation' require 'sass/script/string_interpolation' module Sass::Script # A SassScript parse node representing a binary operation, # such as `$a + $b` or `"foo" + 1`. class Operation < Node attr_reader :operand1 attr_reader :operand2 attr_reader :operator # @param operand1 [Script::Node] The parse-tree node # for the right-hand side of the operator # @param operand2 [Script::Node] The parse-tree node # for the left-hand side of the operator # @param operator [Symbol] The operator to perform. # This should be one of the binary operator names in {Lexer::OPERATORS} def initialize(operand1, operand2, operator) @operand1 = operand1 @operand2 = operand2 @operator = operator super() end # @return [String] A human-readable s-expression representation of the operation def inspect "(#{@operator.inspect} #{@operand1.inspect} #{@operand2.inspect})" end # @see Node#to_sass def to_sass(opts = {}) pred = Sass::Script::Parser.precedence_of(@operator) o1 = operand_to_sass @operand1, :left, opts o2 = operand_to_sass @operand2, :right, opts sep = case @operator when :comma; ", " when :space; " " else; " #{Lexer::OPERATORS_REVERSE[@operator]} " end "#{o1}#{sep}#{o2}" end # Returns the operands for this operation. # # @return [Array] # @see Node#children def children [@operand1, @operand2] end protected # Evaluates the operation. # # @param environment [Sass::Environment] The environment in which to evaluate the SassScript # @return [Literal] The SassScript object that is the value of the operation # @raise [Sass::SyntaxError] if the operation is undefined for the operands def _perform(environment) literal1 = @operand1.perform(environment) literal2 = @operand2.perform(environment) begin opts(literal1.send(@operator, literal2)) rescue NoMethodError => e raise e unless e.name.to_s == @operator.to_s raise Sass::SyntaxError.new("Undefined operation: \"#{literal1} #{@operator} #{literal2}\".") end end private def operand_to_sass(op, side, opts) return "(#{op.to_sass(opts)})" if op.is_a?(List) return op.to_sass(opts) unless op.is_a?(Operation) pred = Sass::Script::Parser.precedence_of(@operator) sub_pred = Sass::Script::Parser.precedence_of(op.operator) assoc = Sass::Script::Parser.associative?(@operator) return "(#{op.to_sass(opts)})" if sub_pred < pred || (side == :right && sub_pred == pred && !assoc) op.to_sass(opts) end end end ././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/list.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000000366512206724733033624 0ustar jamespagejamespagemodule Sass::Script # A SassScript object representing a CSS list. # This includes both comma-separated lists and space-separated lists. class List < Literal # The Ruby array containing the contents of the list. # # @return [Array] attr_reader :value alias_method :children, :value alias_method :to_a, :value # The operator separating the values of the list. # Either `:comma` or `:space`. # # @return [Symbol] attr_reader :separator # Creates a new list. # # @param value [Array] See \{#value} # @param separator [String] See \{#separator} def initialize(value, separator) super(value) @separator = separator end # @see Node#eq def eq(other) Sass::Script::Bool.new( self.class == other.class && self.value == other.value && self.separator == other.separator) end # @see Node#to_s def to_s(opts = {}) raise Sass::SyntaxError.new("() isn't a valid CSS value.") if value.empty? return value.reject {|e| e.is_a?(List) && e.value.empty?}.map {|e| e.to_s(opts)}.join(sep_str) end # @see Node#to_sass def to_sass(opts = {}) precedence = Sass::Script::Parser.precedence_of(separator) value.map do |v| if v.is_a?(List) && Sass::Script::Parser.precedence_of(v.separator) <= precedence "(#{v.to_sass(opts)})" else v.to_sass(opts) end end.join(sep_str(nil)) end # @see Node#inspect def inspect "(#{to_sass})" end protected # @see Node#_perform def _perform(environment) list = Sass::Script::List.new( value.map {|e| e.perform(environment)}, separator) list.options = self.options list end private def sep_str(opts = self.options) return ' ' if separator == :space return ',' if opts && opts[:style] == :compressed return ', ' end end end ././@LongLink0000644000000000000000000000017112255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/unary_operation.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000000340412206724733033613 0ustar jamespagejamespagemodule Sass::Script # A SassScript parse node representing a unary operation, # such as `-$b` or `not true`. # # Currently only `-`, `/`, and `not` are unary operators. class UnaryOperation < Node # @param operand [Script::Node] The parse-tree node # for the object of the operator # @param operator [Symbol] The operator to perform def initialize(operand, operator) @operand = operand @operator = operator super() end # @return [String] A human-readable s-expression representation of the operation def inspect "(#{@operator.inspect} #{@operand.inspect})" end # @see Node#to_sass def to_sass(opts = {}) operand = @operand.to_sass(opts) if @operand.is_a?(Operation) || (@operator == :minus && (operand =~ Sass::SCSS::RX::IDENT) == 0) operand = "(#{@operand.to_sass(opts)})" end op = Lexer::OPERATORS_REVERSE[@operator] op + (op =~ /[a-z]/ ? " " : "") + operand end # Returns the operand of the operation. # # @return [Array] # @see Node#children def children [@operand] end protected # Evaluates the operation. # # @param environment [Sass::Environment] The environment in which to evaluate the SassScript # @return [Literal] The SassScript object that is the value of the operation # @raise [Sass::SyntaxError] if the operation is undefined for the operand def _perform(environment) operator = "unary_#{@operator}" literal = @operand.perform(environment) literal.send(operator) rescue NoMethodError => e raise e unless e.name.to_s == operator.to_s raise Sass::SyntaxError.new("Undefined unary operation: \"#{@operator} #{literal}\".") end end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/variable.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000000263012206724733033613 0ustar jamespagejamespagemodule Sass module Script # A SassScript parse node representing a variable. class Variable < Node # The name of the variable. # # @return [String] attr_reader :name # The underscored name of the variable. # # @return [String] attr_reader :underscored_name # @param name [String] See \{#name} def initialize(name) @name = name @underscored_name = name.gsub(/-/,"_") super() end # @return [String] A string representation of the variable def inspect(opts = {}) return "!important" if name == "important" "$#{dasherize(name, opts)}" end alias_method :to_sass, :inspect # Returns an empty array. # # @return [Array] empty # @see Node#children def children [] end protected # Evaluates the variable. # # @param environment [Sass::Environment] The environment in which to evaluate the SassScript # @return [Literal] The SassScript object that is the value of the variable # @raise [Sass::SyntaxError] if the variable is undefined def _perform(environment) raise SyntaxError.new("Undefined variable: \"$#{name}\".") unless val = environment.var(name) if val.is_a?(Number) val = val.dup val.original = nil end return val end end end end ././@LongLink0000644000000000000000000000015712255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/color.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000003556512206724733033630 0ustar jamespagejamespagerequire 'sass/script/literal' module Sass::Script # A SassScript object representing a CSS color. # # A color may be represented internally as RGBA, HSLA, or both. # It's originally represented as whatever its input is; # if it's created with RGB values, it's represented as RGBA, # and if it's created with HSL values, it's represented as HSLA. # Once a property is accessed that requires the other representation -- # for example, \{#red} for an HSL color -- # that component is calculated and cached. # # The alpha channel of a color is independent of its RGB or HSL representation. # It's always stored, as 1 if nothing else is specified. # If only the alpha channel is modified using \{#with}, # the cached RGB and HSL values are retained. class Color < Literal class << self; include Sass::Util; end # A hash from color names to `[red, green, blue]` value arrays. HTML4_COLORS = map_vals({ 'black' => 0x000000, 'silver' => 0xc0c0c0, 'gray' => 0x808080, 'white' => 0xffffff, 'maroon' => 0x800000, 'red' => 0xff0000, 'purple' => 0x800080, 'fuchsia' => 0xff00ff, 'green' => 0x008000, 'lime' => 0x00ff00, 'olive' => 0x808000, 'yellow' => 0xffff00, 'navy' => 0x000080, 'blue' => 0x0000ff, 'teal' => 0x008080, 'aqua' => 0x00ffff }) {|color| (0..2).map {|n| color >> (n << 3) & 0xff}.reverse} # A hash from `[red, green, blue]` value arrays to color names. HTML4_COLORS_REVERSE = map_hash(HTML4_COLORS) {|k, v| [v, k]} # Constructs an RGB or HSL color object, # optionally with an alpha channel. # # The RGB values must be between 0 and 255. # The saturation and lightness values must be between 0 and 100. # The alpha value must be between 0 and 1. # # @raise [Sass::SyntaxError] if any color value isn't in the specified range # # @overload initialize(attrs) # The attributes are specified as a hash. # This hash must contain either `:hue`, `:saturation`, and `:value` keys, # or `:red`, `:green`, and `:blue` keys. # It cannot contain both HSL and RGB keys. # It may also optionally contain an `:alpha` key. # # @param attrs [{Symbol => Numeric}] A hash of color attributes to values # @raise [ArgumentError] if not enough attributes are specified, # or both RGB and HSL attributes are specified # # @overload initialize(rgba) # The attributes are specified as an array. # This overload only supports RGB or RGBA colors. # # @param rgba [Array] A three- or four-element array # of the red, green, blue, and optionally alpha values (respectively) # of the color # @raise [ArgumentError] if not enough attributes are specified def initialize(attrs, allow_both_rgb_and_hsl = false) super(nil) if attrs.is_a?(Array) unless (3..4).include?(attrs.size) raise ArgumentError.new("Color.new(array) expects a three- or four-element array") end red, green, blue = attrs[0...3].map {|c| c.to_i} @attrs = {:red => red, :green => green, :blue => blue} @attrs[:alpha] = attrs[3] ? attrs[3].to_f : 1 else attrs = attrs.reject {|k, v| v.nil?} hsl = [:hue, :saturation, :lightness] & attrs.keys rgb = [:red, :green, :blue] & attrs.keys if !allow_both_rgb_and_hsl && !hsl.empty? && !rgb.empty? raise ArgumentError.new("Color.new(hash) may not have both HSL and RGB keys specified") elsif hsl.empty? && rgb.empty? raise ArgumentError.new("Color.new(hash) must have either HSL or RGB keys specified") elsif !hsl.empty? && hsl.size != 3 raise ArgumentError.new("Color.new(hash) must have all three HSL values specified") elsif !rgb.empty? && rgb.size != 3 raise ArgumentError.new("Color.new(hash) must have all three RGB values specified") end @attrs = attrs @attrs[:hue] %= 360 if @attrs[:hue] @attrs[:alpha] ||= 1 end [:red, :green, :blue].each do |k| next if @attrs[k].nil? @attrs[k] = @attrs[k].to_i next if (0..255).include?(@attrs[k]) raise ArgumentError.new("#{k.to_s.capitalize} value must be between 0 and 255") end [:saturation, :lightness].each do |k| next if @attrs[k].nil? @attrs[k] = 0 if @attrs[k] < 0.00001 && @attrs[k] > -0.00001 @attrs[k] = 100 if @attrs[k] - 100 < 0.00001 && @attrs[k] - 100 > -0.00001 next if (0..100).include?(@attrs[k]) raise ArgumentError.new("#{k.to_s.capitalize} must be between 0 and 100") end unless (0..1).include?(@attrs[:alpha]) raise ArgumentError.new("Alpha channel must be between 0 and 1") end end # The red component of the color. # # @return [Fixnum] def red hsl_to_rgb! @attrs[:red] end # The green component of the color. # # @return [Fixnum] def green hsl_to_rgb! @attrs[:green] end # The blue component of the color. # # @return [Fixnum] def blue hsl_to_rgb! @attrs[:blue] end # The hue component of the color. # # @return [Numeric] def hue rgb_to_hsl! @attrs[:hue] end # The saturation component of the color. # # @return [Numeric] def saturation rgb_to_hsl! @attrs[:saturation] end # The lightness component of the color. # # @return [Numeric] def lightness rgb_to_hsl! @attrs[:lightness] end # The alpha channel (opacity) of the color. # This is 1 unless otherwise defined. # # @return [Fixnum] def alpha @attrs[:alpha] end # Returns whether this color object is translucent; # that is, whether the alpha channel is non-1. # # @return [Boolean] def alpha? alpha < 1 end # Returns the red, green, and blue components of the color. # # @return [Array] A frozen three-element array of the red, green, and blue # values (respectively) of the color def rgb [red, green, blue].freeze end # Returns the hue, saturation, and lightness components of the color. # # @return [Array] A frozen three-element array of the # hue, saturation, and lightness values (respectively) of the color def hsl [hue, saturation, lightness].freeze end # The SassScript `==` operation. # **Note that this returns a {Sass::Script::Bool} object, # not a Ruby boolean**. # # @param other [Literal] The right-hand side of the operator # @return [Bool] True if this literal is the same as the other, # false otherwise def eq(other) Sass::Script::Bool.new( other.is_a?(Color) && rgb == other.rgb && alpha == other.alpha) end # Returns a copy of this color with one or more channels changed. # RGB or HSL colors may be changed, but not both at once. # # For example: # # Color.new([10, 20, 30]).with(:blue => 40) # #=> rgb(10, 40, 30) # Color.new([126, 126, 126]).with(:red => 0, :green => 255) # #=> rgb(0, 255, 126) # Color.new([255, 0, 127]).with(:saturation => 60) # #=> rgb(204, 51, 127) # Color.new([1, 2, 3]).with(:alpha => 0.4) # #=> rgba(1, 2, 3, 0.4) # # @param attrs [{Symbol => Numeric}] # A map of channel names (`:red`, `:green`, `:blue`, # `:hue`, `:saturation`, `:lightness`, or `:alpha`) to values # @return [Color] The new Color object # @raise [ArgumentError] if both RGB and HSL keys are specified def with(attrs) attrs = attrs.reject {|k, v| v.nil?} hsl = !([:hue, :saturation, :lightness] & attrs.keys).empty? rgb = !([:red, :green, :blue] & attrs.keys).empty? if hsl && rgb raise ArgumentError.new("Cannot specify HSL and RGB values for a color at the same time") end if hsl [:hue, :saturation, :lightness].each {|k| attrs[k] ||= send(k)} elsif rgb [:red, :green, :blue].each {|k| attrs[k] ||= send(k)} else # If we're just changing the alpha channel, # keep all the HSL/RGB stuff we've calculated attrs = @attrs.merge(attrs) end attrs[:alpha] ||= alpha Color.new(attrs, :allow_both_rgb_and_hsl) end # The SassScript `+` operation. # Its functionality depends on the type of its argument: # # {Number} # : Adds the number to each of the RGB color channels. # # {Color} # : Adds each of the RGB color channels together. # # {Literal} # : See {Literal#plus}. # # @param other [Literal] The right-hand side of the operator # @return [Color] The resulting color # @raise [Sass::SyntaxError] if `other` is a number with units def plus(other) if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color) piecewise(other, :+) else super end end # The SassScript `-` operation. # Its functionality depends on the type of its argument: # # {Number} # : Subtracts the number from each of the RGB color channels. # # {Color} # : Subtracts each of the other color's RGB color channels from this color's. # # {Literal} # : See {Literal#minus}. # # @param other [Literal] The right-hand side of the operator # @return [Color] The resulting color # @raise [Sass::SyntaxError] if `other` is a number with units def minus(other) if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color) piecewise(other, :-) else super end end # The SassScript `*` operation. # Its functionality depends on the type of its argument: # # {Number} # : Multiplies the number by each of the RGB color channels. # # {Color} # : Multiplies each of the RGB color channels together. # # @param other [Number, Color] The right-hand side of the operator # @return [Color] The resulting color # @raise [Sass::SyntaxError] if `other` is a number with units def times(other) if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color) piecewise(other, :*) else raise NoMethodError.new(nil, :times) end end # The SassScript `/` operation. # Its functionality depends on the type of its argument: # # {Number} # : Divides each of the RGB color channels by the number. # # {Color} # : Divides each of this color's RGB color channels by the other color's. # # {Literal} # : See {Literal#div}. # # @param other [Literal] The right-hand side of the operator # @return [Color] The resulting color # @raise [Sass::SyntaxError] if `other` is a number with units def div(other) if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color) piecewise(other, :/) else super end end # The SassScript `%` operation. # Its functionality depends on the type of its argument: # # {Number} # : Takes each of the RGB color channels module the number. # # {Color} # : Takes each of this color's RGB color channels modulo the other color's. # # @param other [Number, Color] The right-hand side of the operator # @return [Color] The resulting color # @raise [Sass::SyntaxError] if `other` is a number with units def mod(other) if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color) piecewise(other, :%) else raise NoMethodError.new(nil, :mod) end end # Returns a string representation of the color. # This is usually the color's hex value, # but if the color has a name that's used instead. # # @return [String] The string representation def to_s(opts = {}) return rgba_str if alpha? return smallest if options[:style] == :compressed return HTML4_COLORS_REVERSE[rgb] if HTML4_COLORS_REVERSE[rgb] hex_str end alias_method :to_sass, :to_s # Returns a string representation of the color. # # @return [String] The hex value def inspect alpha? ? rgba_str : hex_str end private def smallest small_hex_str = hex_str.gsub(/^#(.)\1(.)\2(.)\3$/, '#\1\2\3') return small_hex_str unless (color = HTML4_COLORS_REVERSE[rgb]) && color.size <= small_hex_str.size return color end def rgba_str split = options[:style] == :compressed ? ',' : ', ' "rgba(#{rgb.join(split)}#{split}#{Number.round(alpha)})" end def hex_str red, green, blue = rgb.map { |num| num.to_s(16).rjust(2, '0') } "##{red}#{green}#{blue}" end def piecewise(other, operation) other_num = other.is_a? Number if other_num && !other.unitless? raise Sass::SyntaxError.new("Cannot add a number with units (#{other}) to a color (#{self}).") end result = [] for i in (0...3) res = rgb[i].send(operation, other_num ? other.value : other.rgb[i]) result[i] = [ [res, 255].min, 0 ].max end if !other_num && other.alpha != alpha raise Sass::SyntaxError.new("Alpha channels must be equal: #{self} #{operation} #{other}") end with(:red => result[0], :green => result[1], :blue => result[2]) end def hsl_to_rgb! return if @attrs[:red] && @attrs[:blue] && @attrs[:green] h = @attrs[:hue] / 360.0 s = @attrs[:saturation] / 100.0 l = @attrs[:lightness] / 100.0 # Algorithm from the CSS3 spec: http://www.w3.org/TR/css3-color/#hsl-color. m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s m1 = l * 2 - m2 @attrs[:red], @attrs[:green], @attrs[:blue] = [ hue_to_rgb(m1, m2, h + 1.0/3), hue_to_rgb(m1, m2, h), hue_to_rgb(m1, m2, h - 1.0/3) ].map {|c| (c * 0xff).round} end def hue_to_rgb(m1, m2, h) h += 1 if h < 0 h -= 1 if h > 1 return m1 + (m2 - m1) * h * 6 if h * 6 < 1 return m2 if h * 2 < 1 return m1 + (m2 - m1) * (2.0/3 - h) * 6 if h * 3 < 2 return m1 end def rgb_to_hsl! return if @attrs[:hue] && @attrs[:saturation] && @attrs[:lightness] r, g, b = [:red, :green, :blue].map {|k| @attrs[k] / 255.0} # Algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV max = [r, g, b].max min = [r, g, b].min d = max - min h = case max when min; 0 when r; 60 * (g-b)/d when g; 60 * (b-r)/d + 120 when b; 60 * (r-g)/d + 240 end l = (max + min)/2.0 s = if max == min 0 elsif l < 0.5 d/(2*l) else d/(2 - 2*l) end @attrs[:hue] = h % 360 @attrs[:saturation] = s * 100 @attrs[:lightness] = l * 100 end end end ././@LongLink0000644000000000000000000000016012255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/number.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000003403512206724733033617 0ustar jamespagejamespagerequire 'sass/script/literal' module Sass::Script # A SassScript object representing a number. # SassScript numbers can have decimal values, # and can also have units. # For example, `12`, `1px`, and `10.45em` # are all valid values. # # Numbers can also have more complex units, such as `1px*em/in`. # These cannot be inputted directly in Sass code at the moment. class Number < Literal # The Ruby value of the number. # # @return [Numeric] attr_reader :value # A list of units in the numerator of the number. # For example, `1px*em/in*cm` would return `["px", "em"]` # @return [Array] attr_reader :numerator_units # A list of units in the denominator of the number. # For example, `1px*em/in*cm` would return `["in", "cm"]` # @return [Array] attr_reader :denominator_units # The original representation of this number. # For example, although the result of `1px/2px` is `0.5`, # the value of `#original` is `"1px/2px"`. # # This is only non-nil when the original value should be used as the CSS value, # as in `font: 1px/2px`. # # @return [Boolean, nil] attr_accessor :original # The precision with which numbers will be printed to CSS files. # For example, if this is `1000.0`, # `3.1415926` will be printed as `3.142`. # @api public PRECISION = 1000.0 # Used so we don't allocate two new arrays for each new number. NO_UNITS = [] # @param value [Numeric] The value of the number # @param numerator_units [Array] See \{#numerator\_units} # @param denominator_units [Array] See \{#denominator\_units} def initialize(value, numerator_units = NO_UNITS, denominator_units = NO_UNITS) super(value) @numerator_units = numerator_units @denominator_units = denominator_units normalize! end # The SassScript `+` operation. # Its functionality depends on the type of its argument: # # {Number} # : Adds the two numbers together, converting units if possible. # # {Color} # : Adds this number to each of the RGB color channels. # # {Literal} # : See {Literal#plus}. # # @param other [Literal] The right-hand side of the operator # @return [Literal] The result of the operation # @raise [Sass::UnitConversionError] if `other` is a number with incompatible units def plus(other) if other.is_a? Number operate(other, :+) elsif other.is_a?(Color) other.plus(self) else super end end # The SassScript binary `-` operation (e.g. `$a - $b`). # Its functionality depends on the type of its argument: # # {Number} # : Subtracts this number from the other, converting units if possible. # # {Literal} # : See {Literal#minus}. # # @param other [Literal] The right-hand side of the operator # @return [Literal] The result of the operation # @raise [Sass::UnitConversionError] if `other` is a number with incompatible units def minus(other) if other.is_a? Number operate(other, :-) else super end end # The SassScript unary `+` operation (e.g. `+$a`). # # @return [Number] The value of this number def unary_plus self end # The SassScript unary `-` operation (e.g. `-$a`). # # @return [Number] The negative value of this number def unary_minus Number.new(-value, @numerator_units, @denominator_units) end # The SassScript `*` operation. # Its functionality depends on the type of its argument: # # {Number} # : Multiplies the two numbers together, converting units appropriately. # # {Color} # : Multiplies each of the RGB color channels by this number. # # @param other [Number, Color] The right-hand side of the operator # @return [Number, Color] The result of the operation # @raise [NoMethodError] if `other` is an invalid type def times(other) if other.is_a? Number operate(other, :*) elsif other.is_a? Color other.times(self) else raise NoMethodError.new(nil, :times) end end # The SassScript `/` operation. # Its functionality depends on the type of its argument: # # {Number} # : Divides this number by the other, converting units appropriately. # # {Literal} # : See {Literal#div}. # # @param other [Literal] The right-hand side of the operator # @return [Literal] The result of the operation def div(other) if other.is_a? Number res = operate(other, :/) if self.original && other.original res.original = "#{self.original}/#{other.original}" end res else super end end # The SassScript `%` operation. # # @param other [Number] The right-hand side of the operator # @return [Number] This number modulo the other # @raise [NoMethodError] if `other` is an invalid type # @raise [Sass::UnitConversionError] if `other` has any units def mod(other) if other.is_a?(Number) unless other.unitless? raise Sass::UnitConversionError.new("Cannot modulo by a number with units: #{other.inspect}.") end operate(other, :%) else raise NoMethodError.new(nil, :mod) end end # The SassScript `==` operation. # # @param other [Literal] The right-hand side of the operator # @return [Boolean] Whether this number is equal to the other object def eq(other) return Sass::Script::Bool.new(false) unless other.is_a?(Sass::Script::Number) this = self begin if unitless? this = this.coerce(other.numerator_units, other.denominator_units) else other = other.coerce(@numerator_units, @denominator_units) end rescue Sass::UnitConversionError return Sass::Script::Bool.new(false) end Sass::Script::Bool.new(this.value == other.value) end # The SassScript `>` operation. # # @param other [Number] The right-hand side of the operator # @return [Boolean] Whether this number is greater than the other # @raise [NoMethodError] if `other` is an invalid type def gt(other) raise NoMethodError.new(nil, :gt) unless other.is_a?(Number) operate(other, :>) end # The SassScript `>=` operation. # # @param other [Number] The right-hand side of the operator # @return [Boolean] Whether this number is greater than or equal to the other # @raise [NoMethodError] if `other` is an invalid type def gte(other) raise NoMethodError.new(nil, :gte) unless other.is_a?(Number) operate(other, :>=) end # The SassScript `<` operation. # # @param other [Number] The right-hand side of the operator # @return [Boolean] Whether this number is less than the other # @raise [NoMethodError] if `other` is an invalid type def lt(other) raise NoMethodError.new(nil, :lt) unless other.is_a?(Number) operate(other, :<) end # The SassScript `<=` operation. # # @param other [Number] The right-hand side of the operator # @return [Boolean] Whether this number is less than or equal to the other # @raise [NoMethodError] if `other` is an invalid type def lte(other) raise NoMethodError.new(nil, :lte) unless other.is_a?(Number) operate(other, :<=) end # @return [String] The CSS representation of this number # @raise [Sass::SyntaxError] if this number has units that can't be used in CSS # (e.g. `px*in`) def to_s(opts = {}) return original if original raise Sass::SyntaxError.new("#{inspect} isn't a valid CSS value.") unless legal_units? inspect end # Returns a readable representation of this number. # # This representation is valid CSS (and valid SassScript) # as long as there is only one unit. # # @return [String] The representation def inspect(opts = {}) value = self.class.round(self.value) unitless? ? value.to_s : "#{value}#{unit_str}" end alias_method :to_sass, :inspect # @return [Fixnum] The integer value of the number # @raise [Sass::SyntaxError] if the number isn't an integer def to_i super unless int? return value end # @return [Boolean] Whether or not this number is an integer. def int? value % 1 == 0.0 end # @return [Boolean] Whether or not this number has no units. def unitless? @numerator_units.empty? && @denominator_units.empty? end # @return [Boolean] Whether or not this number has units that can be represented in CSS # (that is, zero or one \{#numerator\_units}). def legal_units? (@numerator_units.empty? || @numerator_units.size == 1) && @denominator_units.empty? end # Returns this number converted to other units. # The conversion takes into account the relationship between e.g. mm and cm, # as well as between e.g. in and cm. # # If this number has no units, it will simply return itself # with the given units. # # An incompatible coercion, e.g. between px and cm, will raise an error. # # @param num_units [Array] The numerator units to coerce this number into. # See {\#numerator\_units} # @param den_units [Array] The denominator units to coerce this number into. # See {\#denominator\_units} # @return [Number] The number with the new units # @raise [Sass::UnitConversionError] if the given units are incompatible with the number's # current units def coerce(num_units, den_units) Number.new(if unitless? self.value else self.value * coercion_factor(@numerator_units, num_units) / coercion_factor(@denominator_units, den_units) end, num_units, den_units) end # @param other [Number] A number to decide if it can be compared with this number. # @return [Boolean] Whether or not this number can be compared with the other. def comparable_to?(other) begin operate(other, :+) true rescue Sass::UnitConversionError false end end # Returns a human readable representation of the units in this number. # For complex units this takes the form of: # numerator_unit1 * numerator_unit2 / denominator_unit1 * denominator_unit2 # @return [String] a string that represents the units in this number def unit_str rv = @numerator_units.sort.join("*") if @denominator_units.any? rv << "/" rv << @denominator_units.sort.join("*") end rv end private # @private def self.round(num) if num.is_a?(Float) && (num.infinite? || num.nan?) num elsif num % 1 == 0.0 num.to_i else (num * PRECISION).round / PRECISION end end OPERATIONS = [:+, :-, :<=, :<, :>, :>=] def operate(other, operation) this = self if OPERATIONS.include?(operation) if unitless? this = this.coerce(other.numerator_units, other.denominator_units) else other = other.coerce(@numerator_units, @denominator_units) end end # avoid integer division value = (:/ == operation) ? this.value.to_f : this.value result = value.send(operation, other.value) if result.is_a?(Numeric) Number.new(result, *compute_units(this, other, operation)) else # Boolean op Bool.new(result) end end def coercion_factor(from_units, to_units) # get a list of unmatched units from_units, to_units = sans_common_units(from_units, to_units) if from_units.size != to_units.size || !convertable?(from_units | to_units) raise Sass::UnitConversionError.new("Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.") end from_units.zip(to_units).inject(1) {|m,p| m * conversion_factor(p[0], p[1]) } end def compute_units(this, other, operation) case operation when :* [this.numerator_units + other.numerator_units, this.denominator_units + other.denominator_units] when :/ [this.numerator_units + other.denominator_units, this.denominator_units + other.numerator_units] else [this.numerator_units, this.denominator_units] end end def normalize! return if unitless? @numerator_units, @denominator_units = sans_common_units(@numerator_units, @denominator_units) @denominator_units.each_with_index do |d, i| if convertable?(d) && (u = @numerator_units.detect(&method(:convertable?))) @value /= conversion_factor(d, u) @denominator_units.delete_at(i) @numerator_units.delete_at(@numerator_units.index(u)) end end end # A hash of unit names to their index in the conversion table CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4} CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 ], # in [ nil, 1, 2.36220473, 10, 28.3464567], # cm [ nil, nil, 1, 4.23333333, 12 ], # pc [ nil, nil, nil, 1, 2.83464567], # mm [ nil, nil, nil, nil, 1 ]] # pt def conversion_factor(from_unit, to_unit) res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]] return 1.0 / conversion_factor(to_unit, from_unit) if res.nil? res end def convertable?(units) Array(units).all? {|u| CONVERTABLE_UNITS.include?(u)} end def sans_common_units(units1, units2) units2 = units2.dup # Can't just use -, because we want px*px to coerce properly to px*mm return units1.map do |u| next u unless j = units2.index(u) units2.delete_at(j) nil end.compact, units2 end end end ././@LongLink0000644000000000000000000000015712255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/lexer.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000002427612206724733033625 0ustar jamespagejamespagerequire 'sass/scss/rx' require 'strscan' module Sass module Script # The lexical analyzer for SassScript. # It takes a raw string and converts it to individual tokens # that are easier to parse. class Lexer include Sass::SCSS::RX # A struct containing information about an individual token. # # `type`: \[`Symbol`\] # : The type of token. # # `value`: \[`Object`\] # : The Ruby object corresponding to the value of the token. # # `line`: \[`Fixnum`\] # : The line of the source file on which the token appears. # # `offset`: \[`Fixnum`\] # : The number of bytes into the line the SassScript token appeared. # # `pos`: \[`Fixnum`\] # : The scanner position at which the SassScript token appeared. Token = Struct.new(:type, :value, :line, :offset, :pos) # The line number of the lexer's current position. # # @return [Fixnum] attr_reader :line # The number of bytes into the current line # of the lexer's current position. # # @return [Fixnum] attr_reader :offset # A hash from operator strings to the corresponding token types. OPERATORS = { '+' => :plus, '-' => :minus, '*' => :times, '/' => :div, '%' => :mod, '=' => :single_eq, ':' => :colon, '(' => :lparen, ')' => :rparen, ',' => :comma, 'and' => :and, 'or' => :or, 'not' => :not, '==' => :eq, '!=' => :neq, '>=' => :gte, '<=' => :lte, '>' => :gt, '<' => :lt, '#{' => :begin_interpolation, '}' => :end_interpolation, ';' => :semicolon, '{' => :lcurly, } OPERATORS_REVERSE = Sass::Util.map_hash(OPERATORS) {|k, v| [v, k]} TOKEN_NAMES = Sass::Util.map_hash(OPERATORS_REVERSE) {|k, v| [k, v.inspect]}.merge({ :const => "variable (e.g. $foo)", :ident => "identifier (e.g. middle)", :bool => "boolean (e.g. true, false)", }) # A list of operator strings ordered with longer names first # so that `>` and `<` don't clobber `>=` and `<=`. OP_NAMES = OPERATORS.keys.sort_by {|o| -o.size} # A sub-list of {OP_NAMES} that only includes operators # with identifier names. IDENT_OP_NAMES = OP_NAMES.select {|k, v| k =~ /^\w+/} # A hash of regular expressions that are used for tokenizing. REGULAR_EXPRESSIONS = { :whitespace => /\s+/, :comment => COMMENT, :single_line_comment => SINGLE_LINE_COMMENT, :variable => /(\$)(#{IDENT})/, :ident => /(#{IDENT})(\()?/, :number => /(-)?(?:(\d*\.\d+)|(\d+))([a-zA-Z%]+)?/, :color => HEXCOLOR, :bool => /(true|false)\b/, :ident_op => %r{(#{Regexp.union(*IDENT_OP_NAMES.map{|s| Regexp.new(Regexp.escape(s) + "(?!#{NMCHAR}|\Z)")})})}, :op => %r{(#{Regexp.union(*OP_NAMES)})}, } class << self private def string_re(open, close) /#{open}((?:\\.|\#(?!\{)|[^#{close}\\#])*)(#{close}|#\{)/ end end # A hash of regular expressions that are used for tokenizing strings. # # The key is a `[Symbol, Boolean]` pair. # The symbol represents which style of quotation to use, # while the boolean represents whether or not the string # is following an interpolated segment. STRING_REGULAR_EXPRESSIONS = { [:double, false] => string_re('"', '"'), [:single, false] => string_re("'", "'"), [:double, true] => string_re('', '"'), [:single, true] => string_re('', "'"), [:uri, false] => /url\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/, [:uri, true] => /(#{URLCHAR}*?)(#{W}\)|#\{)/, } # @param str [String, StringScanner] The source text to lex # @param line [Fixnum] The line on which the SassScript appears. # Used for error reporting # @param offset [Fixnum] The number of characters in on which the SassScript appears. # Used for error reporting # @param options [{Symbol => Object}] An options hash; # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation} def initialize(str, line, offset, options) @scanner = str.is_a?(StringScanner) ? str : StringScanner.new(str) @line = line @offset = offset @options = options @interpolation_stack = [] @prev = nil end # Moves the lexer forward one token. # # @return [Token] The token that was moved past def next @tok ||= read_token @tok, tok = nil, @tok @prev = tok return tok end # Returns whether or not there's whitespace before the next token. # # @return [Boolean] def whitespace?(tok = @tok) if tok @scanner.string[0...tok.pos] =~ /\s\Z/ else @scanner.string[@scanner.pos, 1] =~ /^\s/ || @scanner.string[@scanner.pos - 1, 1] =~ /\s\Z/ end end # Returns the next token without moving the lexer forward. # # @return [Token] The next token def peek @tok ||= read_token end # Rewinds the underlying StringScanner # to before the token returned by \{#peek}. def unpeek! @scanner.pos = @tok.pos if @tok end # @return [Boolean] Whether or not there's more source text to lex. def done? whitespace unless after_interpolation? && @interpolation_stack.last @scanner.eos? && @tok.nil? end # @return [Boolean] Whether or not the last token lexed was `:end_interpolation`. def after_interpolation? @prev && @prev.type == :end_interpolation end # Raise an error to the effect that `name` was expected in the input stream # and wasn't found. # # This calls \{#unpeek!} to rewind the scanner to immediately after # the last returned token. # # @param name [String] The name of the entity that was expected but not found # @raise [Sass::SyntaxError] def expected!(name) unpeek! Sass::SCSS::Parser.expected(@scanner, name, @line) end # Records all non-comment text the lexer consumes within the block # and returns it as a string. # # @yield A block in which text is recorded # @return [String] def str old_pos = @tok ? @tok.pos : @scanner.pos yield new_pos = @tok ? @tok.pos : @scanner.pos @scanner.string[old_pos...new_pos] end private def read_token return if done? return unless value = token type, val, size = value size ||= @scanner.matched_size val.line = @line if val.is_a?(Script::Node) Token.new(type, val, @line, current_position - size, @scanner.pos - size) end def whitespace nil while scan(REGULAR_EXPRESSIONS[:whitespace]) || scan(REGULAR_EXPRESSIONS[:comment]) || scan(REGULAR_EXPRESSIONS[:single_line_comment]) end def token if after_interpolation? && (interp_type = @interpolation_stack.pop) return string(interp_type, true) end variable || string(:double, false) || string(:single, false) || number || color || bool || string(:uri, false) || raw(UNICODERANGE) || special_fun || ident_op || ident || op end def variable _variable(REGULAR_EXPRESSIONS[:variable]) end def _variable(rx) line = @line offset = @offset return unless scan(rx) [:const, @scanner[2]] end def ident return unless scan(REGULAR_EXPRESSIONS[:ident]) [@scanner[2] ? :funcall : :ident, @scanner[1]] end def string(re, open) return unless scan(STRING_REGULAR_EXPRESSIONS[[re, open]]) if @scanner[2] == '#{' #' @scanner.pos -= 2 # Don't actually consume the #{ @interpolation_stack << re end str = if re == :uri Script::String.new("#{'url(' unless open}#{@scanner[1]}#{')' unless @scanner[2] == '#{'}") else Script::String.new(@scanner[1].gsub(/\\(['"]|\#\{)/, '\1'), :string) end [:string, str] end def number return unless scan(REGULAR_EXPRESSIONS[:number]) value = @scanner[2] ? @scanner[2].to_f : @scanner[3].to_i value = -value if @scanner[1] [:number, Script::Number.new(value, Array(@scanner[4]))] end def color return unless s = scan(REGULAR_EXPRESSIONS[:color]) raise Sass::SyntaxError.new(<] # @see #initialize # @see Node#children def children [@before, @mid, @after].compact end protected # Evaluates the interpolation. # # @param environment [Sass::Environment] The environment in which to evaluate the SassScript # @return [Sass::Script::String] The SassScript string that is the value of the interpolation def _perform(environment) res = "" res << @before.perform(environment).to_s if @before res << " " if @before && @whitespace_before val = @mid.perform(environment) res << (val.is_a?(Sass::Script::String) ? val.value : val.to_s) res << " " if @after && @whitespace_after res << @after.perform(environment).to_s if @after opts(Sass::Script::String.new(res)) end end end ././@LongLink0000644000000000000000000000016012255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/parser.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000003464612206724733033627 0ustar jamespagejamespagerequire 'sass/script/lexer' module Sass module Script # The parser for SassScript. # It parses a string of code into a tree of {Script::Node}s. class Parser # The line number of the parser's current position. # # @return [Fixnum] def line @lexer.line end # @param str [String, StringScanner] The source text to parse # @param line [Fixnum] The line on which the SassScript appears. # Used for error reporting # @param offset [Fixnum] The number of characters in on which the SassScript appears. # Used for error reporting # @param options [{Symbol => Object}] An options hash; # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation} def initialize(str, line, offset, options = {}) @options = options @lexer = lexer_class.new(str, line, offset, options) end # Parses a SassScript expression within an interpolated segment (`#{}`). # This means that it stops when it comes across an unmatched `}`, # which signals the end of an interpolated segment, # it returns rather than throwing an error. # # @return [Script::Node] The root node of the parse tree # @raise [Sass::SyntaxError] if the expression isn't valid SassScript def parse_interpolated expr = assert_expr :expr assert_tok :end_interpolation expr.options = @options expr rescue Sass::SyntaxError => e e.modify_backtrace :line => @lexer.line, :filename => @options[:filename] raise e end # Parses a SassScript expression. # # @return [Script::Node] The root node of the parse tree # @raise [Sass::SyntaxError] if the expression isn't valid SassScript def parse expr = assert_expr :expr assert_done expr.options = @options expr rescue Sass::SyntaxError => e e.modify_backtrace :line => @lexer.line, :filename => @options[:filename] raise e end # Parses a SassScript expression, # ending it when it encounters one of the given identifier tokens. # # @param [#include?(String)] A set of strings that delimit the expression. # @return [Script::Node] The root node of the parse tree # @raise [Sass::SyntaxError] if the expression isn't valid SassScript def parse_until(tokens) @stop_at = tokens expr = assert_expr :expr assert_done expr.options = @options expr rescue Sass::SyntaxError => e e.modify_backtrace :line => @lexer.line, :filename => @options[:filename] raise e end # Parses the argument list for a mixin include. # # @return [(Array, {String => Script::Note})] # The root nodes of the arguments. # Keyword arguments are in a hash from names to values. # @raise [Sass::SyntaxError] if the argument list isn't valid SassScript def parse_mixin_include_arglist args, keywords = [], {} if try_tok(:lparen) args, keywords = mixin_arglist || [[], {}] assert_tok(:rparen) end assert_done args.each {|a| a.options = @options} keywords.each {|k, v| v.options = @options} return args, keywords rescue Sass::SyntaxError => e e.modify_backtrace :line => @lexer.line, :filename => @options[:filename] raise e end # Parses the argument list for a mixin definition. # # @return [Array] The root nodes of the arguments. # @raise [Sass::SyntaxError] if the argument list isn't valid SassScript def parse_mixin_definition_arglist args = defn_arglist!(false) assert_done args.each do |k, v| k.options = @options v.options = @options if v end args rescue Sass::SyntaxError => e e.modify_backtrace :line => @lexer.line, :filename => @options[:filename] raise e end # Parses the argument list for a function definition. # # @return [Array] The root nodes of the arguments. # @raise [Sass::SyntaxError] if the argument list isn't valid SassScript def parse_function_definition_arglist args = defn_arglist!(true) assert_done args.each do |k, v| k.options = @options v.options = @options if v end args rescue Sass::SyntaxError => e e.modify_backtrace :line => @lexer.line, :filename => @options[:filename] raise e end # Parses a SassScript expression. # # @overload parse(str, line, offset, filename = nil) # @return [Script::Node] The root node of the parse tree # @see Parser#initialize # @see Parser#parse def self.parse(*args) new(*args).parse end PRECEDENCE = [ :comma, :single_eq, :space, :or, :and, [:eq, :neq], [:gt, :gte, :lt, :lte], [:plus, :minus], [:times, :div, :mod], ] ASSOCIATIVE = [:plus, :times] class << self # Returns an integer representing the precedence # of the given operator. # A lower integer indicates a looser binding. # # @private def precedence_of(op) PRECEDENCE.each_with_index do |e, i| return i if Array(e).include?(op) end raise "[BUG] Unknown operator #{op}" end # Returns whether or not the given operation is associative. # # @private def associative?(op) ASSOCIATIVE.include?(op) end private # Defines a simple left-associative production. # name is the name of the production, # sub is the name of the production beneath it, # and ops is a list of operators for this precedence level def production(name, sub, *ops) class_eval < assert_expr(subexpr, EXPR_NAMES[type])} end unless try_tok(:comma) return [], keywords if keywords return [e], {} end other_args, other_keywords = assert_expr(type) if keywords if other_keywords[name.underscored_name] raise SyntaxError.new("Keyword argument \"#{name.to_sass}\" passed more than once") end return other_args, keywords.merge(other_keywords) else return [e, *other_args], other_keywords end end def keyword_arglist return unless var = try_tok(:const) unless try_tok(:colon) return_tok! return end name = var[1] value = interpolation return {name => value} unless try_tok(:comma) {name => value}.merge(assert_expr(:keyword_arglist)) end def raw return special_fun unless tok = try_tok(:raw) node(Script::String.new(tok.value)) end def special_fun return paren unless tok = try_tok(:special_fun) first = node(Script::String.new(tok.value.first)) Sass::Util.enum_slice(tok.value[1..-1], 2).inject(first) do |l, (i, r)| Script::Interpolation.new( l, i, r && node(Script::String.new(r)), false, false) end end def paren return variable unless try_tok(:lparen) was_in_parens = @in_parens @in_parens = true line = @lexer.line e = expr assert_tok(:rparen) return e || node(List.new([], :space), line) ensure @in_parens = was_in_parens end def variable return string unless c = try_tok(:const) node(Variable.new(*c.value)) end def string return number unless first = try_tok(:string) return first.value unless try_tok(:begin_interpolation) line = @lexer.line mid = parse_interpolated last = assert_expr(:string) interp = StringInterpolation.new(first.value, mid, last) interp.line = line interp end def number return literal unless tok = try_tok(:number) num = tok.value num.original = num.to_s unless @in_parens num end def literal (t = try_tok(:color, :bool)) && (return t.value) end # It would be possible to have unified #assert and #try methods, # but detecting the method/token difference turns out to be quite expensive. EXPR_NAMES = { :string => "string", :default => "expression (e.g. 1px, bold)", :mixin_arglist => "mixin argument", :fn_arglist => "function argument", } def assert_expr(name, expected = nil) (e = send(name)) && (return e) @lexer.expected!(expected || EXPR_NAMES[name] || EXPR_NAMES[:default]) end def assert_tok(*names) (t = try_tok(*names)) && (return t) @lexer.expected!(names.map {|tok| Lexer::TOKEN_NAMES[tok] || tok}.join(" or ")) end def try_tok(*names) peeked = @lexer.peek peeked && names.include?(peeked.type) && @lexer.next end def assert_done return if @lexer.done? @lexer.expected!(EXPR_NAMES[:default]) end def node(node, line = @lexer.line) node.line = line node end end end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/funcall.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000001355312206724733033621 0ustar jamespagejamespagerequire 'sass/script/functions' module Sass module Script # A SassScript parse node representing a function call. # # A function call either calls one of the functions in {Script::Functions}, # or if no function with the given name exists # it returns a string representation of the function call. class Funcall < Node # The name of the function. # # @return [String] attr_reader :name # The arguments to the function. # # @return [Array] attr_reader :args # The keyword arguments to the function. # # @return [{String => Script::Node}] attr_reader :keywords # @param name [String] See \{#name} # @param args [Array] See \{#args} # @param keywords [{String => Script::Node}] See \{#keywords} def initialize(name, args, keywords) @name = name @args = args @keywords = keywords super() end # @return [String] A string representation of the function call def inspect args = @args.map {|a| a.inspect}.join(', ') keywords = @keywords.sort_by {|k, v| k}. map {|k, v| "$#{k}: #{v.inspect}"}.join(', ') "#{name}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})" end # @see Node#to_sass def to_sass(opts = {}) args = @args.map {|a| a.to_sass(opts)}.join(', ') keywords = @keywords.sort_by {|k, v| k}. map {|k, v| "$#{dasherize(k, opts)}: #{v.to_sass(opts)}"}.join(', ') "#{dasherize(name, opts)}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})" end # Returns the arguments to the function. # # @return [Array] # @see Node#children def children @args + @keywords.values end protected # Evaluates the function call. # # @param environment [Sass::Environment] The environment in which to evaluate the SassScript # @return [Literal] The SassScript object that is the value of the function call # @raise [Sass::SyntaxError] if the function call raises an ArgumentError def _perform(environment) args = @args.map {|a| a.perform(environment)} if fn = environment.function(@name) keywords = Sass::Util.map_hash(@keywords) {|k, v| [k, v.perform(environment)]} return perform_sass_fn(fn, args, keywords) end ruby_name = @name.tr('-', '_') args = construct_ruby_args(ruby_name, args, environment) unless Functions.callable?(ruby_name) opts(to_literal(args)) else opts(Functions::EvaluationContext.new(environment.options).send(ruby_name, *args)) end rescue ArgumentError => e raise e unless e.backtrace.any? {|t| t =~ /:in `(block in )?(#{name}|perform)'$/} raise Sass::SyntaxError.new("#{e.message} for `#{name}'") end # This method is factored out from `_perform` so that compass can override # it with a cross-browser implementation for functions that require vendor prefixes # in the generated css. def to_literal(args) Script::String.new("#{name}(#{args.join(', ')})") end private def construct_ruby_args(name, args, environment) unless signature = Functions.signature(name.to_sym, args.size, @keywords.size) return args if keywords.empty? raise Sass::SyntaxError.new("Function #{name} doesn't support keyword arguments") end keywords = Sass::Util.map_hash(@keywords) {|k, v| [k, v.perform(environment)]} # If the user passes more non-keyword args than the function expects, # but it does expect keyword args, Ruby's arg handling won't raise an error. # Since we don't want to make functions think about this, # we'll handle it for them here. if signature.var_kwargs && !signature.var_args && args.size > signature.args.size raise Sass::SyntaxError.new( "#{args[signature.args.size].inspect} is not a keyword argument for `#{name}'") elsif keywords.empty? return args end args = args + signature.args[args.size..-1].map do |argname| if keywords.has_key?(argname) keywords.delete(argname) else raise Sass::SyntaxError.new("Function #{name} requires an argument named $#{argname}") end end if keywords.size > 0 if signature.var_kwargs args << keywords else raise Sass::SyntaxError.new("Function #{name} doesn't take an argument named $#{keywords.keys.sort.first}") end end args end def perform_sass_fn(function, args, keywords) # TODO: merge with mixin arg evaluation? keywords.each do |name, value| # TODO: Make this fast unless function.args.find {|(var, default)| var.underscored_name == name} raise Sass::SyntaxError.new("Function #{@name} doesn't have an argument named $#{name}") end end if args.size > function.args.size raise ArgumentError.new("Wrong number of arguments (#{args.size} for #{function.args.size})") end environment = function.args.zip(args). inject(Sass::Environment.new(function.environment)) do |env, ((var, default), value)| env.set_local_var(var.name, value || keywords[var.underscored_name] || (default && default.perform(env))) raise Sass::SyntaxError.new("Function #{@name} is missing parameter #{var.inspect}.") unless env.var(var.name) env end val = catch :_sass_return do function.tree.each {|c| Sass::Tree::Visitors::Perform.visit(c, environment)} raise Sass::SyntaxError.new("Function #{@name} finished without @return") end val end end end end ././@LongLink0000644000000000000000000000017612255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/string_interpolation.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000000602712206724733033617 0ustar jamespagejamespagemodule Sass::Script # A SassScript object representing `#{}` interpolation within a string. # # @see Interpolation class StringInterpolation < Node # Interpolation in a string is of the form `"before #{mid} after"`, # where `before` and `after` may include more interpolation. # # @param before [Node] The string before the interpolation # @param mid [Node] The SassScript within the interpolation # @param after [Node] The string after the interpolation def initialize(before, mid, after) @before = before @mid = mid @after = after end # @return [String] A human-readable s-expression representation of the interpolation def inspect "(string_interpolation #{@before.inspect} #{@mid.inspect} #{@after.inspect})" end # @see Node#to_sass def to_sass(opts = {}) # We can get rid of all of this when we remove the deprecated :equals context # XXX CE: It's gone now but I'm not sure what can be removed now. before_unquote, before_quote_char, before_str = parse_str(@before.to_sass(opts)) after_unquote, after_quote_char, after_str = parse_str(@after.to_sass(opts)) unquote = before_unquote || after_unquote || (before_quote_char && !after_quote_char && !after_str.empty?) || (!before_quote_char && after_quote_char && !before_str.empty?) quote_char = if before_quote_char && after_quote_char && before_quote_char != after_quote_char before_str.gsub!("\\'", "'") before_str.gsub!('"', "\\\"") after_str.gsub!("\\'", "'") after_str.gsub!('"', "\\\"") '"' else before_quote_char || after_quote_char end res = "" res << 'unquote(' if unquote res << quote_char if quote_char res << before_str res << '#{' << @mid.to_sass(opts) << '}' res << after_str res << quote_char if quote_char res << ')' if unquote res end # Returns the three components of the interpolation, `before`, `mid`, and `after`. # # @return [Array] # @see #initialize # @see Node#children def children [@before, @mid, @after].compact end protected # Evaluates the interpolation. # # @param environment [Sass::Environment] The environment in which to evaluate the SassScript # @return [Sass::Script::String] The SassScript string that is the value of the interpolation def _perform(environment) res = "" before = @before.perform(environment) res << before.value mid = @mid.perform(environment) res << (mid.is_a?(Sass::Script::String) ? mid.value : mid.to_s) res << @after.perform(environment).value opts(Sass::Script::String.new(res, before.type)) end private def parse_str(str) case str when /^unquote\((["'])(.*)\1\)$/ return true, $1, $2 when '""' return false, nil, "" when /^(["'])(.*)\1$/ return false, $1, $2 else return false, nil, str end end end end ././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/css_parser.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000000147712206724733033623 0ustar jamespagejamespagerequire 'sass/script' require 'sass/script/css_lexer' module Sass module Script # This is a subclass of {Parser} for use in parsing plain CSS properties. # # @see Sass::SCSS::CssParser class CssParser < Parser private # @private def lexer_class; CssLexer; end # We need a production that only does /, # since * and % aren't allowed in plain CSS production :div, :unary_plus, :div def string return number unless tok = try_tok(:string) return tok.value unless @lexer.peek && @lexer.peek.type == :begin_interpolation end # Short-circuit all the SassScript-only productions alias_method :interpolation, :space alias_method :or_expr, :div alias_method :unary_div, :ident alias_method :paren, :string end end end ././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000000456412206724733033623 0ustar jamespagejamespagemodule Sass::Script # The abstract superclass for SassScript parse tree nodes. # # Use \{#perform} to evaluate a parse tree. class Node # The options hash for this node. # # @return [{Symbol => Object}] attr_reader :options # The line of the document on which this node appeared. # # @return [Fixnum] attr_accessor :line # Sets the options hash for this node, # as well as for all child nodes. # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}. # # @param options [{Symbol => Object}] The options def options=(options) @options = options children.each do |c| if c.is_a? Hash c.values.each {|v| v.options = options } else c.options = options end end end # Evaluates the node. # # \{#perform} shouldn't be overridden directly; # instead, override \{#\_perform}. # # @param environment [Sass::Environment] The environment in which to evaluate the SassScript # @return [Literal] The SassScript object that is the value of the SassScript def perform(environment) _perform(environment) rescue Sass::SyntaxError => e e.modify_backtrace(:line => line) raise e end # Returns all child nodes of this node. # # @return [Array] def children Sass::Util.abstract(self) end # Returns the text of this SassScript expression. # # @return [String] def to_sass(opts = {}) Sass::Util.abstract(self) end protected # Converts underscores to dashes if the :dasherize option is set. def dasherize(s, opts) if opts[:dasherize] s.gsub(/_/,'-') else s end end # Evaluates this node. # Note that all {Literal} objects created within this method # should have their \{#options} attribute set, probably via \{#opts}. # # @param environment [Sass::Environment] The environment in which to evaluate the SassScript # @return [Literal] The SassScript object that is the value of the SassScript # @see #perform def _perform(environment) Sass::Util.abstract(self) end # Sets the \{#options} field on the given literal and returns it # # @param literal [Literal] # @return [Literal] def opts(literal) literal.options = options literal end end end ././@LongLink0000644000000000000000000000016312255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/css_lexer.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000000121112206724733033605 0ustar jamespagejamespagemodule Sass module Script # This is a subclass of {Lexer} for use in parsing plain CSS properties. # # @see Sass::SCSS::CssParser class CssLexer < Lexer private def token important || super end def string(re, *args) if re == :uri return unless uri = scan(URI) return [:string, Script::String.new(uri)] end return unless scan(STRING) [:string, Script::String.new((@scanner[1] || @scanner[2]).gsub(/\\(['"])/, '\1'), :string)] end def important return unless s = scan(IMPORTANT) [:raw, s] end end end end ././@LongLink0000644000000000000000000000016012255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/string.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000000254512206724733033620 0ustar jamespagejamespagerequire 'sass/script/literal' module Sass::Script # A SassScript object representing a CSS string *or* a CSS identifier. class String < Literal # The Ruby value of the string. # # @return [String] attr_reader :value # Whether this is a CSS string or a CSS identifier. # The difference is that strings are written with double-quotes, # while identifiers aren't. # # @return [Symbol] `:string` or `:identifier` attr_reader :type # Creates a new string. # # @param value [String] See \{#value} # @param type [Symbol] See \{#type} def initialize(value, type = :identifier) super(value) @type = type end # @see Literal#plus def plus(other) other_str = other.is_a?(Sass::Script::String) ? other.value : other.to_s Sass::Script::String.new(self.value + other_str, self.type) end # @see Node#to_s def to_s(opts = {}) if @type == :identifier return @value.tr("\n", " ") end return "\"#{value.gsub('"', "\\\"")}\"" if opts[:quote] == %q{"} return "'#{value.gsub("'", "\\'")}'" if opts[:quote] == %q{'} return "\"#{value}\"" unless value.include?('"') return "'#{value}'" unless value.include?("'") "\"#{value.gsub('"', "\\\"")}\"" #' end # @see Node#to_sass def to_sass(opts = {}) to_s end end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/literal.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000001703412206724733033617 0ustar jamespagejamespagemodule Sass::Script # The abstract superclass for SassScript objects. # # Many of these methods, especially the ones that correspond to SassScript operations, # are designed to be overridden by subclasses which may change the semantics somewhat. # The operations listed here are just the defaults. class Literal < Node require 'sass/script/string' require 'sass/script/number' require 'sass/script/color' require 'sass/script/bool' require 'sass/script/list' # Returns the Ruby value of the literal. # The type of this value varies based on the subclass. # # @return [Object] attr_reader :value # Creates a new literal. # # @param value [Object] The object for \{#value} def initialize(value = nil) @value = value super() end # Returns an empty array. # # @return [Array] empty # @see Node#children def children [] end # Returns the options hash for this node. # # @return [{Symbol => Object}] # @raise [Sass::SyntaxError] if the options hash hasn't been set. # This should only happen when the literal was created # outside of the parser and \{#to\_s} was called on it def options opts = super return opts if opts raise Sass::SyntaxError.new(<] The of this literal as a list def to_a [self] end # Returns the string representation of this literal # as it would be output to the CSS document. # # @return [String] def to_s(opts = {}) raise Sass::SyntaxError.new("[BUG] All subclasses of Sass::Literal must implement #to_s.") end alias_method :to_sass, :to_s protected # Evaluates the literal. # # @param environment [Sass::Environment] The environment in which to evaluate the SassScript # @return [Literal] This literal def _perform(environment) self end end end ././@LongLink0000644000000000000000000000016312255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/script/functions.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scrip0000664000175000017500000014117312206724733033621 0ustar jamespagejamespagemodule Sass::Script # Methods in this module are accessible from the SassScript context. # For example, you can write # # $color = hsl(120deg, 100%, 50%) # # and it will call {Sass::Script::Functions#hsl}. # # The following functions are provided: # # *Note: These functions are described in more detail below.* # # ## RGB Functions # # \{#rgb rgb($red, $green, $blue)} # : Converts an `rgb(red, green, blue)` triplet into a color. # # \{#rgba rgba($red, $green, $blue, $alpha)} # : Converts an `rgba(red, green, blue, alpha)` quadruplet into a color. # # \{#rgba rgba($color, $alpha)} # : Adds an alpha layer to any color value. # # \{#red red($color)} # : Gets the red component of a color. # # \{#green green($color)} # : Gets the green component of a color. # # \{#blue blue($color)} # : Gets the blue component of a color. # # \{#mix mix($color-1, $color-2, \[$weight\])} # : Mixes two colors together. # # ## HSL Functions # # \{#hsl hsl($hue, $saturation, $lightness)} # : Converts an `hsl(hue, saturation, lightness)` triplet into a color. # # \{#hsla hsla($hue, $saturation, $lightness, $alpha)} # : Converts an `hsla(hue, saturation, lightness, alpha)` quadruplet into a color. # # \{#hue hue($color)} # : Gets the hue component of a color. # # \{#saturation saturation($color)} # : Gets the saturation component of a color. # # \{#lightness lightness($color)} # : Gets the lightness component of a color. # # \{#adjust_hue adjust-hue($color, $degrees)} # : Changes the hue of a color. # # \{#lighten lighten($color, $amount)} # : Makes a color lighter. # # \{#darken darken($color, $amount)} # : Makes a color darker. # # \{#saturate saturate($color, $amount)} # : Makes a color more saturated. # # \{#desaturate desaturate($color, $amount)} # : Makes a color less saturated. # # \{#grayscale grayscale($color)} # : Converts a color to grayscale. # # \{#complement complement($color)} # : Returns the complement of a color. # # \{#invert invert($color)} # : Returns the inverse of a color. # # ## Opacity Functions # # \{#alpha alpha($color)} / \{#opacity opacity($color)} # : Gets the alpha component (opacity) of a color. # # \{#rgba rgba($color, $alpha)} # : Add or change an alpha layer for any color value. # # \{#opacify opacify($color, $amount)} / \{#fade_in fade-in($color, $amount)} # : Makes a color more opaque. # # \{#transparentize transparentize($color, $amount)} / \{#fade_out fade-out($color, $amount)} # : Makes a color more transparent. # # ## Other Color Functions # # \{#adjust_color adjust-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\]} # : Increase or decrease any of the components of a color. # # \{#scale_color scale-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\]} # : Fluidly scale one or more components of a color. # # \{#change_color change-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], \[$lightness\], \[$alpha\]} # : Changes one or more properties of a color. # # ## String Functions # # \{#unquote unquote($string)} # : Removes the quotes from a string. # # \{#quote quote($string)} # : Adds quotes to a string. # # ## Number Functions # # \{#percentage percentage($value)} # : Converts a unitless number to a percentage. # # \{#round round($value)} # : Rounds a number to the nearest whole number. # # \{#ceil ceil($value)} # : Rounds a number up to the nearest whole number. # # \{#floor floor($value)} # : Rounds a number down to the nearest whole number. # # \{#abs abs($value)} # : Returns the absolute value of a number. # # ## List Functions {#list-functions} # # \{#length length($list)} # : Returns the length of a list. # # \{#nth nth($list, $n)} # : Returns a specific item in a list. # # \{#join join($list1, $list2, \[$separator\])} # : Joins together two lists into one. # # ## Introspection Functions # # \{#type_of type-of($value)} # : Returns the type of a value. # # \{#unit unit($number)} # : Returns the units associated with a number. # # \{#unitless unitless($number)} # : Returns whether a number has units or not. # # \{#comparable comparable($number-1, $number-2)} # : Returns whether two numbers can be added or compared. # # ## Miscellaneous Functions # # \{#if if($condition, $if-true, $if-false)} # : Returns one of two values, depending on whether or not a condition is true. # # ## Adding Custom Functions # # New Sass functions can be added by adding Ruby methods to this module. # For example: # # module Sass::Script::Functions # def reverse(string) # assert_type string, :String # Sass::Script::String.new(string.value.reverse) # end # declare :reverse, :args => [:string] # end # # Calling {declare} tells Sass the argument names for your function. # If omitted, the function will still work, but will not be able to accept keyword arguments. # {declare} can also allow your function to take arbitrary keyword arguments. # # There are a few things to keep in mind when modifying this module. # First of all, the arguments passed are {Sass::Script::Literal} objects. # Literal objects are also expected to be returned. # This means that Ruby values must be unwrapped and wrapped. # # Most Literal objects support the {Sass::Script::Literal#value value} accessor # for getting their Ruby values. # Color objects, though, must be accessed using {Sass::Script::Color#rgb rgb}, # {Sass::Script::Color#red red}, {Sass::Script::Color#blue green}, or {Sass::Script::Color#blue blue}. # # Second, making Ruby functions accessible from Sass introduces the temptation # to do things like database access within stylesheets. # This is generally a bad idea; # since Sass files are by default only compiled once, # dynamic code is not a great fit. # # If you really, really need to compile Sass on each request, # first make sure you have adequate caching set up. # Then you can use {Sass::Engine} to render the code, # using the {file:SASS_REFERENCE.md#custom-option `options` parameter} # to pass in data that {EvaluationContext#options can be accessed} # from your Sass functions. # # Within one of the functions in this module, # methods of {EvaluationContext} can be used. # # ### Caveats # # When creating new {Literal} objects within functions, # be aware that it's not safe to call {Literal#to_s #to_s} # (or other methods that use the string representation) # on those objects without first setting {Node#options= the #options attribute}. module Functions @signatures = {} # A class representing a Sass function signature. # # @attr args [Array] The names of the arguments to the function. # @attr var_args [Boolean] Whether the function takes a variable number of arguments. # @attr var_kwargs [Boolean] Whether the function takes an arbitrary set of keyword arguments. Signature = Struct.new(:args, :var_args, :var_kwargs) # Declare a Sass signature for a Ruby-defined function. # This includes the names of the arguments, # whether the function takes a variable number of arguments, # and whether the function takes an arbitrary set of keyword arguments. # # It's not necessary to declare a signature for a function. # However, without a signature it won't support keyword arguments. # # A single function can have multiple signatures declared # as long as each one takes a different number of arguments. # It's also possible to declare multiple signatures # that all take the same number of arguments, # but none of them but the first will be used # unless the user uses keyword arguments. # # @param method_name [Symbol] The name of the method # whose signature is being declared. # @param args [Array] The names of the arguments for the function signature. # @option options :var_args [Boolean] (false) # Whether the function accepts a variable number of (unnamed) arguments # in addition to the named arguments. # @option options :var_kwargs [Boolean] (false) # Whether the function accepts other keyword arguments # in addition to those in `:args`. # If this is true, the Ruby function will be passed a hash from strings # to {Sass::Script::Literal}s as the last argument. # In addition, if this is true and `:var_args` is not, # Sass will ensure that the last argument passed is a hash. # # @example # declare :rgba, [:hex, :alpha] # declare :rgba, [:red, :green, :blue, :alpha] # declare :accepts_anything, [], :var_args => true, :var_kwargs => true # declare :some_func, [:foo, :bar, :baz], :var_kwargs => true def self.declare(method_name, args, options = {}) @signatures[method_name] ||= [] @signatures[method_name] << Signature.new( args.map {|s| s.to_s}, options[:var_args], options[:var_kwargs]) end # Determine the correct signature for the number of arguments # passed in for a given function. # If no signatures match, the first signature is returned for error messaging. # # @param method_name [Symbol] The name of the Ruby function to be called. # @param arg_arity [Number] The number of unnamed arguments the function was passed. # @param kwarg_arity [Number] The number of keyword arguments the function was passed. # # @return [{Symbol => Object}, nil] # The signature options for the matching signature, # or nil if no signatures are declared for this function. See {declare}. def self.signature(method_name, arg_arity, kwarg_arity) return unless @signatures[method_name] @signatures[method_name].each do |signature| return signature if signature.args.size == arg_arity + kwarg_arity next unless signature.args.size < arg_arity + kwarg_arity # We have enough args. # Now we need to figure out which args are varargs # and if the signature allows them. t_arg_arity, t_kwarg_arity = arg_arity, kwarg_arity if signature.args.size > t_arg_arity # we transfer some kwargs arity to args arity # if it does not have enough args -- assuming the names will work out. t_kwarg_arity -= (signature.args.size - t_arg_arity) t_arg_arity = signature.args.size end if ( t_arg_arity == signature.args.size || t_arg_arity > signature.args.size && signature.var_args ) && (t_kwarg_arity == 0 || t_kwarg_arity > 0 && signature.var_kwargs) return signature end end @signatures[method_name].first end # The context in which methods in {Script::Functions} are evaluated. # That means that all instance methods of {EvaluationContext} # are available to use in functions. class EvaluationContext include Functions # The options hash for the {Sass::Engine} that is processing the function call # # @return [{Symbol => Object}] attr_reader :options # @param options [{Symbol => Object}] See \{#options} def initialize(options) @options = options end # Asserts that the type of a given SassScript value # is the expected type (designated by a symbol). # # Valid types are `:Bool`, `:Color`, `:Number`, and `:String`. # Note that `:String` will match both double-quoted strings # and unquoted identifiers. # # @example # assert_type value, :String # assert_type value, :Number # @param value [Sass::Script::Literal] A SassScript value # @param type [Symbol] The name of the type the value is expected to be # @param name [String, nil] The name of the argument. def assert_type(value, type, name = nil) return if value.is_a?(Sass::Script.const_get(type)) err = "#{value.inspect} is not a #{type.to_s.downcase}" err = "$#{name}: " + err if name raise ArgumentError.new(err) end end class << self # Returns whether user function with a given name exists. # # @param function_name [String] # @return [Boolean] alias_method :callable?, :public_method_defined? private def include(*args) r = super # We have to re-include ourselves into EvaluationContext to work around # an icky Ruby restriction. EvaluationContext.send :include, self r end end # Creates a {Color} object from red, green, and blue values. # # @param red [Number] # A number between 0 and 255 inclusive, # or between 0% and 100% inclusive # @param green [Number] # A number between 0 and 255 inclusive, # or between 0% and 100% inclusive # @param blue [Number] # A number between 0 and 255 inclusive, # or between 0% and 100% inclusive # @see #rgba # @return [Color] def rgb(red, green, blue) assert_type red, :Number assert_type green, :Number assert_type blue, :Number Color.new([red, green, blue].map do |c| v = c.value if c.numerator_units == ["%"] && c.denominator_units.empty? next v * 255 / 100.0 if (0..100).include?(v) raise ArgumentError.new("Color value #{c} must be between 0% and 100% inclusive") else next v if (0..255).include?(v) raise ArgumentError.new("Color value #{v} must be between 0 and 255 inclusive") end end) end declare :rgb, [:red, :green, :blue] # @see #rgb # @overload rgba(red, green, blue, alpha) # Creates a {Color} object from red, green, and blue values, # as well as an alpha channel indicating opacity. # # @param red [Number] # A number between 0 and 255 inclusive # @param green [Number] # A number between 0 and 255 inclusive # @param blue [Number] # A number between 0 and 255 inclusive # @param alpha [Number] # A number between 0 and 1 # @return [Color] # # @overload rgba(color, alpha) # Sets the opacity of a color. # # @example # rgba(#102030, 0.5) => rgba(16, 32, 48, 0.5) # rgba(blue, 0.2) => rgba(0, 0, 255, 0.2) # # @param color [Color] # @param alpha [Number] # A number between 0 and 1 # @return [Color] def rgba(*args) case args.size when 2 color, alpha = args assert_type color, :Color assert_type alpha, :Number unless (0..1).include?(alpha.value) raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1 inclusive") end color.with(:alpha => alpha.value) when 4 red, green, blue, alpha = args rgba(rgb(red, green, blue), alpha) else raise ArgumentError.new("wrong number of arguments (#{args.size} for 4)") end end declare :rgba, [:red, :green, :blue, :alpha] declare :rgba, [:color, :alpha] # Creates a {Color} object from hue, saturation, and lightness. # Uses the algorithm from the [CSS3 spec](http://www.w3.org/TR/css3-color/#hsl-color). # # @param hue [Number] The hue of the color. # Should be between 0 and 360 degrees, inclusive # @param saturation [Number] The saturation of the color. # Must be between `0%` and `100%`, inclusive # @param lightness [Number] The lightness of the color. # Must be between `0%` and `100%`, inclusive # @return [Color] The resulting color # @see #hsla # @raise [ArgumentError] if `saturation` or `lightness` are out of bounds def hsl(hue, saturation, lightness) hsla(hue, saturation, lightness, Number.new(1)) end declare :hsl, [:hue, :saturation, :lightness] # Creates a {Color} object from hue, saturation, and lightness, # as well as an alpha channel indicating opacity. # Uses the algorithm from the [CSS3 spec](http://www.w3.org/TR/css3-color/#hsl-color). # # @param hue [Number] The hue of the color. # Should be between 0 and 360 degrees, inclusive # @param saturation [Number] The saturation of the color. # Must be between `0%` and `100%`, inclusive # @param lightness [Number] The lightness of the color. # Must be between `0%` and `100%`, inclusive # @param alpha [Number] The opacity of the color. # Must be between 0 and 1, inclusive # @return [Color] The resulting color # @see #hsl # @raise [ArgumentError] if `saturation`, `lightness`, or `alpha` are out of bounds def hsla(hue, saturation, lightness, alpha) assert_type hue, :Number assert_type saturation, :Number assert_type lightness, :Number assert_type alpha, :Number unless (0..1).include?(alpha.value) raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1") end original_s = saturation original_l = lightness # This algorithm is from http://www.w3.org/TR/css3-color#hsl-color h, s, l = [hue, saturation, lightness].map { |a| a.value } raise ArgumentError.new("Saturation #{s} must be between 0% and 100%") unless (0..100).include?(s) raise ArgumentError.new("Lightness #{l} must be between 0% and 100%") unless (0..100).include?(l) Color.new(:hue => h, :saturation => s, :lightness => l, :alpha => alpha.value) end declare :hsla, [:hue, :saturation, :lightness, :alpha] # Returns the red component of a color. # # @param color [Color] # @return [Number] # @raise [ArgumentError] If `color` isn't a color def red(color) assert_type color, :Color Sass::Script::Number.new(color.red) end declare :red, [:color] # Returns the green component of a color. # # @param color [Color] # @return [Number] # @raise [ArgumentError] If `color` isn't a color def green(color) assert_type color, :Color Sass::Script::Number.new(color.green) end declare :green, [:color] # Returns the blue component of a color. # # @param color [Color] # @return [Number] # @raise [ArgumentError] If `color` isn't a color def blue(color) assert_type color, :Color Sass::Script::Number.new(color.blue) end declare :blue, [:color] # Returns the hue component of a color. # # See [the CSS3 HSL specification](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV). # # Calculated from RGB where necessary via [this algorithm](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV). # # @param color [Color] # @return [Number] between 0deg and 360deg # @see #adjust_hue # @raise [ArgumentError] if `color` isn't a color def hue(color) assert_type color, :Color Sass::Script::Number.new(color.hue, ["deg"]) end declare :hue, [:color] # Returns the saturation component of a color. # # See [the CSS3 HSL specification](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV). # # Calculated from RGB where necessary via [this algorithm](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV). # # @param color [Color] # @return [Number] between 0% and 100% # @see #saturate # @see #desaturate # @raise [ArgumentError] if `color` isn't a color def saturation(color) assert_type color, :Color Sass::Script::Number.new(color.saturation, ["%"]) end declare :saturation, [:color] # Returns the hue component of a color. # # See [the CSS3 HSL specification](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV). # # Calculated from RGB where necessary via [this algorithm](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV). # # @param color [Color] # @return [Number] between 0% and 100% # @see #lighten # @see #darken # @raise [ArgumentError] if `color` isn't a color def lightness(color) assert_type color, :Color Sass::Script::Number.new(color.lightness, ["%"]) end declare :lightness, [:color] # Returns the alpha component (opacity) of a color. # This is 1 unless otherwise specified. # # This function also supports the proprietary Microsoft # `alpha(opacity=20)` syntax. # # @overload def alpha(color) # @param color [Color] # @return [Number] # @see #opacify # @see #transparentize # @raise [ArgumentError] If `color` isn't a color def alpha(*args) if args.all? do |a| a.is_a?(Sass::Script::String) && a.type == :identifier && a.value =~ /^[a-zA-Z]+\s*=/ end # Support the proprietary MS alpha() function return Sass::Script::String.new("alpha(#{args.map {|a| a.to_s}.join(", ")})") end opacity(*args) end declare :alpha, [:color] # Returns the alpha component (opacity) of a color. # This is 1 unless otherwise specified. # # @param color [Color] # @return [Number] # @see #opacify # @see #transparentize # @raise [ArgumentError] If `color` isn't a color def opacity(color) assert_type color, :Color Sass::Script::Number.new(color.alpha) end declare :opacity, [:color] # Makes a color more opaque. # Takes a color and an amount between 0 and 1, # and returns a color with the opacity increased by that value. # # @example # opacify(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.6) # opacify(rgba(0, 0, 17, 0.8), 0.2) => #001 # @param color [Color] # @param amount [Number] # @return [Color] # @see #transparentize # @raise [ArgumentError] If `color` isn't a color, # or `number` isn't a number between 0 and 1 def opacify(color, amount) _adjust(color, amount, :alpha, 0..1, :+) end declare :opacify, [:color, :amount] alias_method :fade_in, :opacify declare :fade_in, [:color, :amount] # Makes a color more transparent. # Takes a color and an amount between 0 and 1, # and returns a color with the opacity decreased by that value. # # @example # transparentize(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.4) # transparentize(rgba(0, 0, 0, 0.8), 0.2) => rgba(0, 0, 0, 0.6) # @param color [Color] # @param amount [Number] # @return [Color] # @see #opacify # @raise [ArgumentError] If `color` isn't a color, # or `number` isn't a number between 0 and 1 def transparentize(color, amount) _adjust(color, amount, :alpha, 0..1, :-) end declare :transparentize, [:color, :amount] alias_method :fade_out, :transparentize declare :fade_out, [:color, :amount] # Makes a color lighter. # Takes a color and an amount between 0% and 100%, # and returns a color with the lightness increased by that value. # # @example # lighten(hsl(0, 0%, 0%), 30%) => hsl(0, 0, 30) # lighten(#800, 20%) => #e00 # @param color [Color] # @param amount [Number] # @return [Color] # @see #darken # @raise [ArgumentError] If `color` isn't a color, # or `number` isn't a number between 0% and 100% def lighten(color, amount) _adjust(color, amount, :lightness, 0..100, :+, "%") end declare :lighten, [:color, :amount] # Makes a color darker. # Takes a color and an amount between 0% and 100%, # and returns a color with the lightness decreased by that value. # # @example # darken(hsl(25, 100%, 80%), 30%) => hsl(25, 100%, 50%) # darken(#800, 20%) => #200 # @param color [Color] # @param amount [Number] # @return [Color] # @see #lighten # @raise [ArgumentError] If `color` isn't a color, # or `number` isn't a number between 0% and 100% def darken(color, amount) _adjust(color, amount, :lightness, 0..100, :-, "%") end declare :darken, [:color, :amount] # Makes a color more saturated. # Takes a color and an amount between 0% and 100%, # and returns a color with the saturation increased by that value. # # @example # saturate(hsl(120, 30%, 90%), 20%) => hsl(120, 50%, 90%) # saturate(#855, 20%) => #9e3f3f # @param color [Color] # @param amount [Number] # @return [Color] # @see #desaturate # @raise [ArgumentError] If `color` isn't a color, # or `number` isn't a number between 0% and 100% def saturate(color, amount) _adjust(color, amount, :saturation, 0..100, :+, "%") end declare :saturate, [:color, :amount] # Makes a color less saturated. # Takes a color and an amount between 0% and 100%, # and returns a color with the saturation decreased by that value. # # @example # desaturate(hsl(120, 30%, 90%), 20%) => hsl(120, 10%, 90%) # desaturate(#855, 20%) => #726b6b # @param color [Color] # @param amount [Number] # @return [Color] # @see #saturate # @raise [ArgumentError] If `color` isn't a color, # or `number` isn't a number between 0% and 100% def desaturate(color, amount) _adjust(color, amount, :saturation, 0..100, :-, "%") end declare :desaturate, [:color, :amount] # Changes the hue of a color while retaining the lightness and saturation. # Takes a color and a number of degrees (usually between -360deg and 360deg), # and returns a color with the hue rotated by that value. # # @example # adjust-hue(hsl(120, 30%, 90%), 60deg) => hsl(180, 30%, 90%) # adjust-hue(hsl(120, 30%, 90%), 060deg) => hsl(60, 30%, 90%) # adjust-hue(#811, 45deg) => #886a11 # @param color [Color] # @param amount [Number] # @return [Color] # @raise [ArgumentError] If `color` isn't a color, or `number` isn't a number def adjust_hue(color, degrees) assert_type color, :Color assert_type degrees, :Number color.with(:hue => color.hue + degrees.value) end declare :adjust_hue, [:color, :degrees] # Adjusts one or more properties of a color. # This can change the red, green, blue, hue, saturation, value, and alpha properties. # The properties are specified as keyword arguments, # and are added to or subtracted from the color's current value for that property. # # `$red`, `$green`, and `$blue` properties should be between 0 and 255. # `$saturation` and `$lightness` should be between 0% and 100%. # `$alpha` should be between 0 and 1. # # All properties are optional. # You can't specify both RGB properties (`$red`, `$green`, `$blue`) # and HSL properties (`$hue`, `$saturation`, `$value`) at the same time. # # @example # adjust-color(#102030, $blue: 5) => #102035 # adjust-color(#102030, $red: -5, $blue: 5) => #0b2035 # adjust-color(hsl(25, 100%, 80%), $lightness: -30%, $alpha: -0.4) => hsla(25, 100%, 50%, 0.6) # @param color [Color] # @param red [Number] # @param green [Number] # @param blue [Number] # @param hue [Number] # @param saturation [Number] # @param lightness [Number] # @param alpha [Number] # @return [Color] # @raise [ArgumentError] if `color` is not a color, # if any keyword argument is not a number, # if any keyword argument is not in the legal range, # if an unexpected keyword argument is given, # or if both HSL and RGB properties are given. def adjust_color(color, kwargs) assert_type color, :Color with = Sass::Util.map_hash({ "red" => [-255..255, ""], "green" => [-255..255, ""], "blue" => [-255..255, ""], "hue" => nil, "saturation" => [-100..100, "%"], "lightness" => [-100..100, "%"], "alpha" => [-1..1, ""] }) do |name, (range, units)| next unless val = kwargs.delete(name) assert_type val, :Number, name if range && !range.include?(val.value) raise ArgumentError.new("$#{name}: Amount #{val} must be between #{range.first}#{units} and #{range.last}#{units}") end adjusted = color.send(name) + val.value adjusted = [0, Sass::Util.restrict(adjusted, range)].max if range [name.to_sym, adjusted] end unless kwargs.empty? name, val = kwargs.to_a.first raise ArgumentError.new("Unknown argument $#{name} (#{val})") end color.with(with) end declare :adjust_color, [:color], :var_kwargs => true # Scales one or more properties of a color by a percentage value. # Unlike \{#adjust_color adjust-color}, which changes a color's properties by fixed amounts, # \{#scale_color scale-color} fluidly changes them based on how high or low they already are. # That means that lightening an already-light color with \{#scale_color scale-color} # won't change the lightness much, # but lightening a dark color by the same amount will change it more dramatically. # This has the benefit of making `scale-color($color, ...)` have a similar effect # regardless of what `$color` is. # # For example, the lightness of a color can be anywhere between 0 and 100. # If `scale-color($color, $lightness: 40%)` is called, the resulting color's lightness # will be 40% of the way between its original lightness and 100. # If `scale-color($color, $lightness: -40%)` is called instead, # the lightness will be 40% of the way between the original and 0. # # This can change the red, green, blue, saturation, value, and alpha properties. # The properties are specified as keyword arguments. # All arguments should be percentages between 0% and 100%. # # All properties are optional. # You can't specify both RGB properties (`$red`, `$green`, `$blue`) # and HSL properties (`$saturation`, `$value`) at the same time. # # @example # scale-color(hsl(120, 70, 80), $lightness: 50%) => hsl(120, 70, 90) # scale-color(rgb(200, 150, 170), $green: -40%, $blue: 70%) => rgb(200, 90, 229) # scale-color(hsl(200, 70, 80), $saturation: -90%, $alpha: -30%) => hsla(200, 7, 80, 0.7) # @param color [Color] # @param red [Number] # @param green [Number] # @param blue [Number] # @param saturation [Number] # @param lightness [Number] # @param alpha [Number] # @return [Color] # @raise [ArgumentError] if `color` is not a color, # if any keyword argument is not a percentage between 0% and 100%, # if an unexpected keyword argument is given, # or if both HSL and RGB properties are given. def scale_color(color, kwargs) assert_type color, :Color with = Sass::Util.map_hash({ "red" => 255, "green" => 255, "blue" => 255, "saturation" => 100, "lightness" => 100, "alpha" => 1 }) do |name, max| next unless val = kwargs.delete(name) assert_type val, :Number, name if !(val.numerator_units == ['%'] && val.denominator_units.empty?) raise ArgumentError.new("$#{name}: Amount #{val} must be a % (e.g. #{val.value}%)") elsif !(-100..100).include?(val.value) raise ArgumentError.new("$#{name}: Amount #{val} must be between -100% and 100%") end current = color.send(name) scale = val.value/100.0 diff = scale > 0 ? max - current : current [name.to_sym, current + diff*scale] end unless kwargs.empty? name, val = kwargs.to_a.first raise ArgumentError.new("Unknown argument $#{name} (#{val})") end color.with(with) end declare :scale_color, [:color], :var_kwargs => true # Changes one or more properties of a color. # This can change the red, green, blue, hue, saturation, value, and alpha properties. # The properties are specified as keyword arguments, # and replace the color's current value for that property. # # `$red`, `$green`, and `$blue` properties should be between 0 and 255. # `$saturation` and `$lightness` should be between 0% and 100%. # `$alpha` should be between 0 and 1. # # All properties are optional. # You can't specify both RGB properties (`$red`, `$green`, `$blue`) # and HSL properties (`$hue`, `$saturation`, `$value`) at the same time. # # @example # change-color(#102030, $blue: 5) => #102005 # change-color(#102030, $red: 120, $blue: 5) => #782005 # change-color(hsl(25, 100%, 80%), $lightness: 40%, $alpha: 0.8) => hsla(25, 100%, 40%, 0.8) # @param color [Color] # @param red [Number] # @param green [Number] # @param blue [Number] # @param hue [Number] # @param saturation [Number] # @param lightness [Number] # @param alpha [Number] # @return [Color] # @raise [ArgumentError] if `color` is not a color, # if any keyword argument is not a number, # if any keyword argument is not in the legal range, # if an unexpected keyword argument is given, # or if both HSL and RGB properties are given. def change_color(color, kwargs) assert_type color, :Color with = Sass::Util.map_hash(%w[red green blue hue saturation lightness alpha]) do |name, max| next unless val = kwargs.delete(name) assert_type val, :Number, name [name.to_sym, val.value] end unless kwargs.empty? name, val = kwargs.to_a.first raise ArgumentError.new("Unknown argument $#{name} (#{val})") end color.with(with) end declare :change_color, [:color], :var_kwargs => true # Mixes together two colors. # Specifically, takes the average of each of the RGB components, # optionally weighted by the given percentage. # The opacity of the colors is also considered when weighting the components. # # The weight specifies the amount of the first color that should be included # in the returned color. # The default, 50%, means that half the first color # and half the second color should be used. # 25% means that a quarter of the first color # and three quarters of the second color should be used. # # @example # mix(#f00, #00f) => #7f007f # mix(#f00, #00f, 25%) => #3f00bf # mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75) # @overload mix(color1, color2, weight: 50%) # @param color1 [Color] # @param color2 [Color] # @param weight [Number] between 0% and 100% # @return [Color] # @raise [ArgumentError] if `color1` or `color2` aren't colors, # or `weight` isn't a number between 0% and 100% def mix(color1, color2, weight = Number.new(50)) assert_type color1, :Color assert_type color2, :Color assert_type weight, :Number unless (0..100).include?(weight.value) raise ArgumentError.new("Weight #{weight} must be between 0% and 100%") end # This algorithm factors in both the user-provided weight # and the difference between the alpha values of the two colors # to decide how to perform the weighted average of the two RGB values. # # It works by first normalizing both parameters to be within [-1, 1], # where 1 indicates "only use color1", -1 indicates "only use color 0", # and all values in between indicated a proportionately weighted average. # # Once we have the normalized variables w and a, # we apply the formula (w + a)/(1 + w*a) # to get the combined weight (in [-1, 1]) of color1. # This formula has two especially nice properties: # # * When either w or a are -1 or 1, the combined weight is also that number # (cases where w * a == -1 are undefined, and handled as a special case). # # * When a is 0, the combined weight is w, and vice versa # # Finally, the weight of color1 is renormalized to be within [0, 1] # and the weight of color2 is given by 1 minus the weight of color1. p = weight.value/100.0 w = p*2 - 1 a = color1.alpha - color2.alpha w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0 w2 = 1 - w1 rgb = color1.rgb.zip(color2.rgb).map {|v1, v2| v1*w1 + v2*w2} alpha = color1.alpha*p + color2.alpha*(1-p) Color.new(rgb + [alpha]) end declare :mix, [:color_1, :color_2] declare :mix, [:color_1, :color_2, :weight] # Converts a color to grayscale. # This is identical to `desaturate(color, 100%)`. # # @param color [Color] # @return [Color] # @raise [ArgumentError] if `color` isn't a color # @see #desaturate def grayscale(color) desaturate color, Number.new(100) end declare :grayscale, [:color] # Returns the complement of a color. # This is identical to `adjust-hue(color, 180deg)`. # # @param color [Color] # @return [Color] # @raise [ArgumentError] if `color` isn't a color # @see #adjust_hue #adjust-hue def complement(color) adjust_hue color, Number.new(180) end declare :complement, [:color] # Returns the inverse (negative) of a color. # The red, green, and blue values are inverted, while the opacity is left alone. # # @param color [Color] # @return [Color] # @raise [ArgumentError] if `color` isn't a color def invert(color) assert_type color, :Color color.with( :red => (255 - color.red), :green => (255 - color.green), :blue => (255 - color.blue)) end # Removes quotes from a string if the string is quoted, # or returns the same string if it's not. # # @param string [String] # @return [String] # @raise [ArgumentError] if `string` isn't a string # @see #quote # @example # unquote("foo") => foo # unquote(foo) => foo def unquote(string) if string.is_a?(Sass::Script::String) Sass::Script::String.new(string.value, :identifier) else string end end declare :unquote, [:string] # Add quotes to a string if the string isn't quoted, # or returns the same string if it is. # # @param string [String] # @return [String] # @raise [ArgumentError] if `string` isn't a string # @see #unquote # @example # quote("foo") => "foo" # quote(foo) => "foo" def quote(string) assert_type string, :String Sass::Script::String.new(string.value, :string) end declare :quote, [:string] # Inspects the type of the argument, returning it as an unquoted string. # # @example # type-of(100px) => number # type-of(asdf) => string # type-of("asdf") => string # type-of(true) => bool # type-of(#fff) => color # type-of(blue) => color # @param value [Literal] The object to inspect # @return [String] The unquoted string name of the literal's type def type_of(value) Sass::Script::String.new(value.class.name.gsub(/Sass::Script::/,'').downcase) end declare :type_of, [:value] # Inspects the unit of the number, returning it as a quoted string. # Complex units are sorted in alphabetical order by numerator and denominator. # # @example # unit(100) => "" # unit(100px) => "px" # unit(3em) => "em" # unit(10px * 5em) => "em*px" # unit(10px * 5em / 30cm / 1rem) => "em*px/cm*rem" # @param number [Literal] The number to inspect # @return [String] The unit(s) of the number # @raise [ArgumentError] if `number` isn't a number def unit(number) assert_type number, :Number Sass::Script::String.new(number.unit_str, :string) end declare :unit, [:number] # Inspects the unit of the number, returning a boolean indicating if it is unitless. # # @example # unitless(100) => true # unitless(100px) => false # @param number [Literal] The number to inspect # @return [Bool] Whether or not the number is unitless # @raise [ArgumentError] if `number` isn't a number def unitless(number) assert_type number, :Number Sass::Script::Bool.new(number.unitless?) end declare :unitless, [:number] # Returns true if two numbers are similar enough to be added, subtracted, or compared. # # @example # comparable(2px, 1px) => true # comparable(100px, 3em) => false # comparable(10cm, 3mm) => true # @param number_1 [Number] # @param number_2 [Number] # @return [Bool] indicating if the numbers can be compared. # @raise [ArgumentError] if `number_1` or `number_2` aren't numbers def comparable(number_1, number_2) assert_type number_1, :Number assert_type number_2, :Number Sass::Script::Bool.new(number_1.comparable_to?(number_2)) end declare :comparable, [:number_1, :number_2] # Converts a decimal number to a percentage. # # @example # percentage(100px / 50px) => 200% # @param value [Number] The decimal number to convert to a percentage # @return [Number] The percentage # @raise [ArgumentError] If `value` isn't a unitless number def percentage(value) unless value.is_a?(Sass::Script::Number) && value.unitless? raise ArgumentError.new("#{value.inspect} is not a unitless number") end Sass::Script::Number.new(value.value * 100, ['%']) end declare :percentage, [:value] # Rounds a number to the nearest whole number. # # @example # round(10.4px) => 10px # round(10.6px) => 11px # @param value [Number] The number # @return [Number] The rounded number # @raise [ArgumentError] if `value` isn't a number def round(value) numeric_transformation(value) {|n| n.round} end declare :round, [:value] # Rounds a number up to the nearest whole number. # # @example # ciel(10.4px) => 11px # ciel(10.6px) => 11px # @param value [Number] The number # @return [Number] The rounded number # @raise [ArgumentError] if `value` isn't a number def ceil(value) numeric_transformation(value) {|n| n.ceil} end declare :ceil, [:value] # Rounds down to the nearest whole number. # # @example # floor(10.4px) => 10px # floor(10.6px) => 10px # @param value [Number] The number # @return [Number] The rounded number # @raise [ArgumentError] if `value` isn't a number def floor(value) numeric_transformation(value) {|n| n.floor} end declare :floor, [:value] # Finds the absolute value of a number. # # @example # abs(10px) => 10px # abs(-10px) => 10px # @param value [Number] The number # @return [Number] The absolute value # @raise [ArgumentError] if `value` isn't a number def abs(value) numeric_transformation(value) {|n| n.abs} end declare :abs, [:value] # Return the length of a list. # # @example # length(10px) => 1 # length(10px 20px 30px) => 3 # @param list [Literal] The list # @return [Number] The length def length(list) Sass::Script::Number.new(list.to_a.size) end declare :length, [:list] # Gets the nth item in a list. # # Note that unlike some languages, the first item in a Sass list is number 1, # the second number 2, and so forth. # # @example # nth(10px 20px 30px, 1) => 10px # nth((Helvetica, Arial, sans-serif), 3) => sans-serif # @param list [Literal] The list # @param n [Number] The index into the list # @return [Literal] The nth item in the list # @raise [ArgumentError] If `n` isn't an integer between 1 and the list's length. def nth(list, n) assert_type n, :Number if !n.int? raise ArgumentError.new("List index #{n} must be an integer") elsif n.to_i < 1 raise ArgumentError.new("List index #{n} must be greater than or equal to 1") elsif list.to_a.size == 0 raise ArgumentError.new("List index is #{n} but list has no items") elsif n.to_i > (size = list.to_a.size) raise ArgumentError.new("List index is #{n} but list is only #{size} item#{'s' if size != 1} long") end list.to_a[n.to_i - 1] end declare :nth, [:list, :n] # Joins together two lists into a new list. # # Unless the `$separator` argument is passed, # if one list is comma-separated and one is space-separated, # the first parameter's separator is used for the resulting list. # If the lists have only one item each, spaces are used for the resulting list. # # @example # join(10px 20px, 30px 40px) => 10px 20px 30px 40px # join((blue, red), (#abc, #def)) => blue, red, #abc, #def # join(10px, 20px) => 10px 20px # join(10px, 20px, comma) => 10px, 20px # join((blue, red), (#abc, #def), space) => blue red #abc #def # @overload join(list1, list2, separator: auto) # @param list1 [Literal] The first list to join # @param list2 [Literal] The second list to join # @param separator [String] How the list separator (comma or space) should be determined. # If this is `comma` or `space`, that is always the separator; # if this is `auto` (the default), the separator is determined as explained above. def join(list1, list2, separator = Sass::Script::String.new("auto")) assert_type separator, :String unless %w[auto space comma].include?(separator.value) raise ArgumentError.new("Separator name must be space, comma, or auto") end sep1 = list1.separator if list1.is_a?(Sass::Script::List) && !list1.value.empty? sep2 = list2.separator if list2.is_a?(Sass::Script::List) && !list2.value.empty? Sass::Script::List.new( list1.to_a + list2.to_a, if separator.value == 'auto' sep1 || sep2 || :space else separator.value.to_sym end) end declare :join, [:list1, :list2] declare :join, [:list1, :list2, :separator] # Appends a single value onto the end of a list. # # Unless the `$separator` argument is passed, # if the list has only one item, # the resulting list will be space-separated. # # @example # append(10px 20px, 30px) => 10px 20px 30px # append((blue, red), green) => blue, red, green # append(10px 20px, 30px 40px) => 10px 20px (30px 40px) # join(10px, 20px, comma) => 10px, 20px # join((blue, red), green, space) => blue red green # @overload join(list, val, separator: auto) # @param list1 [Literal] The first list to join # @param list2 [Literal] The second list to join # @param separator [String] How the list separator (comma or space) should be determined. # If this is `comma` or `space`, that is always the separator; # if this is `auto` (the default), the separator is determined as explained above. def append(list, val, separator = Sass::Script::String.new("auto")) assert_type separator, :String unless %w[auto space comma].include?(separator.value) raise ArgumentError.new("Separator name must be space, comma, or auto") end sep = list.separator if list.is_a?(Sass::Script::List) Sass::Script::List.new( list.to_a + [val], if separator.value == 'auto' sep || :space else separator.value.to_sym end) end declare :append, [:list, :val] declare :append, [:list, :val, :separator] # Returns one of two values based on the truth value of the first argument. # # @example # if(true, 1px, 2px) => 1px # if(false, 1px, 2px) => 2px # @param condition [Bool] Whether the first or second value will be returned. # @param if_true [Literal] The value that will be returned if `$condition` is true. # @param if_false [Literal] The value that will be returned if `$condition` is false. def if(condition, if_true, if_false) if condition.to_bool if_true else if_false end end declare :if, [:condition, :if_true, :if_false] private # This method implements the pattern of transforming a numeric value into # another numeric value with the same units. # It yields a number to a block to perform the operation and return a number def numeric_transformation(value) assert_type value, :Number Sass::Script::Number.new(yield(value.value), value.numerator_units, value.denominator_units) end def _adjust(color, amount, attr, range, op, units = "") assert_type color, :Color assert_type amount, :Number unless range.include?(amount.value) raise ArgumentError.new("Amount #{amount} must be between #{range.first}#{units} and #{range.last}#{units}") end # TODO: is it worth restricting here, # or should we do so in the Color constructor itself, # and allow clipping in rgb() et al? color.with(attr => Sass::Util.restrict( color.send(attr).send(op, amount.value), range)) end end end ././@LongLink0000644000000000000000000000015112255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selector/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selec0000775000175000017500000000000012206724733033563 5ustar jamespagejamespage././@LongLink0000644000000000000000000000017512255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selector/abstract_sequence.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selec0000664000175000017500000000373112206724733033571 0ustar jamespagejamespagemodule Sass module Selector # The abstract parent class of the various selector sequence classes. # # All subclasses should implement a `members` method # that returns an array of object that respond to `#line=` and `#filename=`. class AbstractSequence # The line of the Sass template on which this selector was declared. # # @return [Fixnum] attr_reader :line # The name of the file in which this selector was declared. # # @return [String, nil] attr_reader :filename # Sets the line of the Sass template on which this selector was declared. # This also sets the line for all child selectors. # # @param line [Fixnum] # @return [Fixnum] def line=(line) members.each {|m| m.line = line} @line = line end # Sets the name of the file in which this selector was declared, # or `nil` if it was not declared in a file (e.g. on stdin). # This also sets the filename for all child selectors. # # @param filename [String, nil] # @return [String, nil] def filename=(filename) members.each {|m| m.filename = filename} @filename = filename end # Returns a hash code for this sequence. # # Subclasses should define `#_hash` rather than overriding this method, # which automatically handles memoizing the result. # # @return [Fixnum] def hash @_hash ||= _hash end # Checks equality between this and another object. # # Subclasses should define `#_eql?` rather than overriding this method, # which handles checking class equality and hash equality. # # @param other [Object] The object to test equality against # @return [Boolean] Whether or not this is equal to `other` def eql?(other) other.class == self.class && other.hash == self.hash && _eql?(other) end alias_method :==, :eql? end end end ././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selector/sequence.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selec0000664000175000017500000002110212206724733033561 0ustar jamespagejamespagemodule Sass module Selector # An operator-separated sequence of # {SimpleSequence simple selector sequences}. class Sequence < AbstractSequence # Sets the line of the Sass template on which this selector was declared. # This also sets the line for all child selectors. # # @param line [Fixnum] # @return [Fixnum] def line=(line) members.each {|m| m.line = line if m.is_a?(SimpleSequence)} line end # Sets the name of the file in which this selector was declared, # or `nil` if it was not declared in a file (e.g. on stdin). # This also sets the filename for all child selectors. # # @param filename [String, nil] # @return [String, nil] def filename=(filename) members.each {|m| m.filename = filename if m.is_a?(SimpleSequence)} filename end # The array of {SimpleSequence simple selector sequences}, operators, and newlines. # The operators are strings such as `"+"` and `">"` # representing the corresponding CSS operators. # Newlines are also newline strings; # these aren't semantically relevant, # but they do affect formatting. # # @return [Array] attr_reader :members # @param seqs_and_ops [Array] See \{#members} def initialize(seqs_and_ops) @members = seqs_and_ops end # Resolves the {Parent} selectors within this selector # by replacing them with the given parent selector, # handling commas appropriately. # # @param super_seq [Sequence] The parent selector sequence # @return [Sequence] This selector, with parent references resolved # @raise [Sass::SyntaxError] If a parent selector is invalid def resolve_parent_refs(super_seq) members = @members nl = (members.first == "\n" && members.shift) unless members.any? do |seq_or_op| seq_or_op.is_a?(SimpleSequence) && seq_or_op.members.first.is_a?(Parent) end members = [] members << nl if nl members << SimpleSequence.new([Parent.new]) members += @members end Sequence.new( members.map do |seq_or_op| next seq_or_op unless seq_or_op.is_a?(SimpleSequence) seq_or_op.resolve_parent_refs(super_seq) end.flatten) end # Non-destructively extends this selector with the extensions specified in a hash # (which should come from {Sass::Tree::Visitors::Cssize}). # # @overload def do_extend(extends) # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}] # The extensions to perform on this selector # @return [Array] A list of selectors generated # by extending this selector with `extends`. # These correspond to a {CommaSequence}'s {CommaSequence#members members array}. # @see CommaSequence#do_extend def do_extend(extends, seen = Set.new) paths = Sass::Util.paths(members.map do |sseq_or_op| next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence) extended = sseq_or_op.do_extend(extends, seen) choices = extended.map {|seq| seq.members} choices.unshift([sseq_or_op]) unless extended.any? {|seq| seq.superselector?(sseq_or_op)} choices end) Sass::Util.flatten(paths.map {|path| weave(path)}, 1).map {|p| Sequence.new(p)} end # Returns whether or not this selector matches all elements # that the given selector matches (as well as possibly more). # # @example # (.foo).superselector?(.foo.bar) #=> true # (.foo).superselector?(.bar) #=> false # (.bar .foo).superselector?(.foo) #=> false # @param sseq [SimpleSequence] # @return [Boolean] def superselector?(sseq) return false unless members.size == 1 members.last.superselector?(sseq) end # @see Simple#to_a def to_a ary = @members.map {|seq_or_op| seq_or_op.is_a?(SimpleSequence) ? seq_or_op.to_a : seq_or_op} Sass::Util.intersperse(ary, " ").flatten.compact end # Returns a string representation of the sequence. # This is basically the selector string. # # @return [String] def inspect members.map {|m| m.inspect}.join(" ") end private # Conceptually, this expands "parenthesized selectors". # That is, if we have `.A .B {@extend .C}` and `.D .C {...}`, # this conceptually expands into `.D .C, .D (.A .B)`, # and this function translates `.D (.A .B)` into `.D .A .B, .A.D .B, .D .A .B`. # # @param path [Array>] A list of parenthesized selector groups. # @return [Array>] A list of fully-expanded selectors. def weave(path) befores = [[]] afters = path.dup until afters.empty? current = afters.shift.dup last_current = [current.pop] while !current.empty? && last_current.first.is_a?(String) || current.last.is_a?(String) last_current.unshift(current.pop) end befores = Sass::Util.flatten(befores.map do |before| subweave(before, current).map {|seqs| seqs + last_current} end, 1) return befores if afters.empty? end end # This interweaves two lists of selectors, # returning all possible orderings of them (including using unification) # that maintain the relative ordering of the input arrays. # # For example, given `.foo .bar` and `.baz .bang`, # this would return `.foo .bar .baz .bang`, `.foo .bar.baz .bang`, # `.foo .baz .bar .bang`, `.foo .baz .bar.bang`, `.foo .baz .bang .bar`, # and so on until `.baz .bang .foo .bar`. # # @overload def subweave(seq1, seq2) # @param seq1 [Array] # @param seq2 [Array] # @return [Array>] def subweave(seq1, seq2, cache = {}) return [seq2] if seq1.empty? return [seq1] if seq2.empty? seq1 = group_selectors(seq1) seq2 = group_selectors(seq2) lcs = Sass::Util.lcs(seq2, seq1) do |s1, s2| next s1 if s1 == s2 next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence) next s2 if subweave_superselector?(s1, s2) next s1 if subweave_superselector?(s2, s1) end diff = [] until lcs.empty? diff << chunks(seq1, seq2) {|s| subweave_superselector?(s.first, lcs.first)} << [lcs.shift] seq1.shift seq2.shift end diff << chunks(seq1, seq2) {|s| s.empty?} diff.reject! {|c| c.empty?} Sass::Util.paths(diff).map {|p| p.flatten} end def chunks(seq1, seq2) chunk1 = [] chunk1 << seq1.shift until yield seq1 chunk2 = [] chunk2 << seq2.shift until yield seq2 return [] if chunk1.empty? && chunk2.empty? return [chunk2] if chunk1.empty? return [chunk1] if chunk2.empty? [chunk1 + chunk2, chunk2 + chunk1] end def group_selectors(seq) newseq = [] tail = seq.dup until tail.empty? head = [] begin head << tail.shift end while !tail.empty? && head.last.is_a?(String) || tail.first.is_a?(String) newseq << head end return newseq end def subweave_superselector?(sseq1, sseq2) if sseq1.size > 1 # More complex selectors are never superselectors of less complex ones return unless sseq2.size > 1 # .foo ~ .bar is a superselector of .foo + .bar return unless sseq1[1] == "~" ? sseq2[1] != ">" : sseq2[1] == sseq1[1] return unless sseq1.first.superselector?(sseq2.first) return true if sseq1.size == 2 return false if sseq2.size == 2 return subweave_superselector?(sseq1[2..-1], sseq2[2..-1]) elsif sseq2.size > 1 return true if sseq2[1] == ">" && sseq1.first.superselector?(sseq2.first) return false if sseq2.size == 2 return subweave_superselector?(sseq1, sseq2[2..-1]) else sseq1.first.superselector?(sseq2.first) end end def _hash members.reject {|m| m == "\n"}.hash end def _eql?(other) other.members.reject {|m| m == "\n"}.eql?(self.members.reject {|m| m == "\n"}) end end end end ././@LongLink0000644000000000000000000000017312255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selector/simple_sequence.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selec0000664000175000017500000001161212206724733033566 0ustar jamespagejamespagemodule Sass module Selector # A unseparated sequence of selectors # that all apply to a single element. # For example, `.foo#bar[attr=baz]` is a simple sequence # of the selectors `.foo`, `#bar`, and `[attr=baz]`. class SimpleSequence < AbstractSequence # The array of individual selectors. # # @return [Array] attr_reader :members # Returns the element or universal selector in this sequence, # if it exists. # # @return [Element, Universal, nil] def base @base ||= (members.first if members.first.is_a?(Element) || members.first.is_a?(Universal)) end # Returns the non-base selectors in this sequence. # # @return [Set] def rest @rest ||= Set.new(base ? members[1..-1] : members) end # @param selectors [Array] See \{#members} def initialize(selectors) @members = selectors end # Resolves the {Parent} selectors within this selector # by replacing them with the given parent selector, # handling commas appropriately. # # @param super_seq [Sequence] The parent selector sequence # @return [Array] This selector, with parent references resolved. # This is an array because the parent selector is itself a {Sequence} # @raise [Sass::SyntaxError] If a parent selector is invalid def resolve_parent_refs(super_seq) # Parent selector only appears as the first selector in the sequence return [self] unless @members.first.is_a?(Parent) return super_seq.members if @members.size == 1 unless super_seq.members.last.is_a?(SimpleSequence) raise Sass::SyntaxError.new("Invalid parent selector: " + super_seq.to_a.join) end super_seq.members[0...-1] + [SimpleSequence.new(super_seq.members.last.members + @members[1..-1])] end # Non-destrucively extends this selector with the extensions specified in a hash # (which should come from {Sass::Tree::Visitors::Cssize}). # # @overload def do_extend(extends) # @param extends [{Selector::Simple => Selector::Sequence}] # The extensions to perform on this selector # @return [Array] A list of selectors generated # by extending this selector with `extends`. # @see CommaSequence#do_extend def do_extend(extends, seen = Set.new) extends.get(members.to_set).map do |seq, sels| # If A {@extend B} and C {...}, # seq is A, sels is B, and self is C self_without_sel = self.members - sels next unless unified = seq.members.last.unify(self_without_sel) [sels, seq.members[0...-1] + [unified]] end.compact.map do |sels, seq| seq = Sequence.new(seq) seen.include?(sels) ? [] : seq.do_extend(extends, seen + [sels]) end.flatten.uniq end # Unifies this selector with another {SimpleSequence}'s {SimpleSequence#members members array}, # returning another `SimpleSequence` # that matches both this selector and the input selector. # # @param sels [Array] A {SimpleSequence}'s {SimpleSequence#members members array} # @return [SimpleSequence, nil] A {SimpleSequence} matching both `sels` and this selector, # or `nil` if this is impossible (e.g. unifying `#foo` and `#bar`) # @raise [Sass::SyntaxError] If this selector cannot be unified. # This will only ever occur when a dynamic selector, # such as {Parent} or {Interpolation}, is used in unification. # Since these selectors should be resolved # by the time extension and unification happen, # this exception will only ever be raised as a result of programmer error def unify(sels) return unless sseq = members.inject(sels) do |sseq, sel| return unless sseq sel.unify(sseq) end SimpleSequence.new(sseq) end # Returns whether or not this selector matches all elements # that the given selector matches (as well as possibly more). # # @example # (.foo).superselector?(.foo.bar) #=> true # (.foo).superselector?(.bar) #=> false # @param sseq [SimpleSequence] # @return [Boolean] def superselector?(sseq) (base.nil? || base.eql?(sseq.base)) && rest.subset?(sseq.rest) end # @see Simple#to_a def to_a @members.map {|sel| sel.to_a}.flatten end # Returns a string representation of the sequence. # This is basically the selector string. # # @return [String] def inspect members.map {|m| m.inspect}.join end private def _hash [base, Sass::Util.set_hash(rest)].hash end def _eql?(other) other.base.eql?(self.base) && Sass::Util.set_eql?(other.rest, self.rest) end end end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selector/simple.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selec0000664000175000017500000001110212206724733033560 0ustar jamespagejamespagemodule Sass module Selector # The abstract superclass for simple selectors # (that is, those that don't compose multiple selectors). class Simple # The line of the Sass template on which this selector was declared. # # @return [Fixnum] attr_accessor :line # The name of the file in which this selector was declared, # or `nil` if it was not declared in a file (e.g. on stdin). # # @return [String, nil] attr_accessor :filename # Returns a representation of the node # as an array of strings and potentially {Sass::Script::Node}s # (if there's interpolation in the selector). # When the interpolation is resolved and the strings are joined together, # this will be the string representation of this node. # # @return [Array] def to_a Sass::Util.abstract(self) end # Returns a string representation of the node. # This is basically the selector string. # # @return [String] def inspect to_a.map {|e| e.is_a?(Sass::Script::Node) ? "\#{#{e.to_sass}}" : e}.join end # Returns a hash code for this selector object. # # By default, this is based on the value of \{#to\_a}, # so if that contains information irrelevant to the identity of the selector, # this should be overridden. # # @return [Fixnum] def hash @_hash ||= to_a.hash end # Checks equality between this and another object. # # By default, this is based on the value of \{#to\_a}, # so if that contains information irrelevant to the identity of the selector, # this should be overridden. # # @param other [Object] The object to test equality against # @return [Boolean] Whether or not this is equal to `other` def eql?(other) other.class == self.class && other.hash == self.hash && other.to_a.eql?(to_a) end alias_method :==, :eql? # Unifies this selector with a {SimpleSequence}'s {SimpleSequence#members members array}, # returning another `SimpleSequence` members array # that matches both this selector and the input selector. # # By default, this just appends this selector to the end of the array # (or returns the original array if this selector already exists in it). # # @param sels [Array] A {SimpleSequence}'s {SimpleSequence#members members array} # @return [Array, nil] A {SimpleSequence} {SimpleSequence#members members array} # matching both `sels` and this selector, # or `nil` if this is impossible (e.g. unifying `#foo` and `#bar`) # @raise [Sass::SyntaxError] If this selector cannot be unified. # This will only ever occur when a dynamic selector, # such as {Parent} or {Interpolation}, is used in unification. # Since these selectors should be resolved # by the time extension and unification happen, # this exception will only ever be raised as a result of programmer error def unify(sels) return sels if sels.any? {|sel2| eql?(sel2)} sels_with_ix = Sass::Util.enum_with_index(sels) _, i = if self.is_a?(Pseudo) || self.is_a?(SelectorPseudoClass) sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) && sels.last.type == :element} else sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) || sel.is_a?(SelectorPseudoClass)} end return sels + [self] unless i return sels[0...i] + [self] + sels[i..-1] end protected # Unifies two namespaces, # returning a namespace that works for both of them if possible. # # @param ns1 [String, nil] The first namespace. # `nil` means none specified, e.g. `foo`. # The empty string means no namespace specified, e.g. `|foo`. # `"*"` means any namespace is allowed, e.g. `*|foo`. # @param ns2 [String, nil] The second namespace. See `ns1`. # @return [Array(String or nil, Boolean)] # The first value is the unified namespace, or `nil` for no namespace. # The second value is whether or not a namespace that works for both inputs # could be found at all. # If the second value is `false`, the first should be ignored. def unify_namespaces(ns1, ns2) return nil, false unless ns1 == ns2 || ns1.nil? || ns1 == ['*'] || ns2.nil? || ns2 == ['*'] return ns2, true if ns1 == ['*'] return ns1, true if ns2 == ['*'] return ns1 || ns2, true end end end end ././@LongLink0000644000000000000000000000017212255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selector/comma_sequence.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selec0000664000175000017500000000505112206724733033566 0ustar jamespagejamespagemodule Sass module Selector # A comma-separated sequence of selectors. class CommaSequence < AbstractSequence # The comma-separated selector sequences # represented by this class. # # @return [Array] attr_reader :members # @param seqs [Array] See \{#members} def initialize(seqs) @members = seqs end # Resolves the {Parent} selectors within this selector # by replacing them with the given parent selector, # handling commas appropriately. # # @param super_cseq [CommaSequence] The parent selector # @return [CommaSequence] This selector, with parent references resolved # @raise [Sass::SyntaxError] If a parent selector is invalid def resolve_parent_refs(super_cseq) if super_cseq.nil? if @members.any? do |sel| sel.members.any? do |sel_or_op| sel_or_op.is_a?(SimpleSequence) && sel_or_op.members.any? {|ssel| ssel.is_a?(Parent)} end end raise Sass::SyntaxError.new("Base-level rules cannot contain the parent-selector-referencing character '&'.") end return self end CommaSequence.new( super_cseq.members.map do |super_seq| @members.map {|seq| seq.resolve_parent_refs(super_seq)} end.flatten) end # Non-destrucively extends this selector with the extensions specified in a hash # (which should come from {Sass::Tree::Visitors::Cssize}). # # @todo Link this to the reference documentation on `@extend` # when such a thing exists. # # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}] # The extensions to perform on this selector # @return [CommaSequence] A copy of this selector, # with extensions made according to `extends` def do_extend(extends) CommaSequence.new(members.map {|seq| seq.do_extend(extends)}.flatten) end # Returns a string representation of the sequence. # This is basically the selector string. # # @return [String] def inspect members.map {|m| m.inspect}.join(", ") end # @see Simple#to_a def to_a arr = Sass::Util.intersperse(@members.map {|m| m.to_a}, ", ").flatten arr.delete("\n") arr end private def _hash members.hash end def _eql?(other) other.class == self.class && other.members.eql?(self.members) end end end end ././@LongLink0000644000000000000000000000015012255653646011654 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/error.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/error0000664000175000017500000001525312206724733033631 0ustar jamespagejamespagemodule Sass # An exception class that keeps track of # the line of the Sass template it was raised on # and the Sass file that was being parsed (if applicable). # # All Sass errors are raised as {Sass::SyntaxError}s. # # When dealing with SyntaxErrors, # it's important to provide filename and line number information. # This will be used in various error reports to users, including backtraces; # see \{#sass\_backtrace} for details. # # Some of this information is usually provided as part of the constructor. # New backtrace entries can be added with \{#add\_backtrace}, # which is called when an exception is raised between files (e.g. with `@import`). # # Often, a chunk of code will all have similar backtrace information - # the same filename or even line. # It may also be useful to have a default line number set. # In those situations, the default values can be used # by omitting the information on the original exception, # and then calling \{#modify\_backtrace} in a wrapper `rescue`. # When doing this, be sure that all exceptions ultimately end up # with the information filled in. class SyntaxError < StandardError # The backtrace of the error within Sass files. # This is an array of hashes containing information for a single entry. # The hashes have the following keys: # # `:filename` # : The name of the file in which the exception was raised, # or `nil` if no filename is available. # # `:mixin` # : The name of the mixin in which the exception was raised, # or `nil` if it wasn't raised in a mixin. # # `:line` # : The line of the file on which the error occurred. Never nil. # # This information is also included in standard backtrace format # in the output of \{#backtrace}. # # @return [Aray<{Symbol => Object>}] attr_accessor :sass_backtrace # The text of the template where this error was raised. # # @return [String] attr_accessor :sass_template # @param msg [String] The error message # @param attrs [{Symbol => Object}] The information in the backtrace entry. # See \{#sass\_backtrace} def initialize(msg, attrs = {}) @message = msg @sass_backtrace = [] add_backtrace(attrs) end # The name of the file in which the exception was raised. # This could be `nil` if no filename is available. # # @return [String, nil] def sass_filename sass_backtrace.first[:filename] end # The name of the mixin in which the error occurred. # This could be `nil` if the error occurred outside a mixin. # # @return [Fixnum] def sass_mixin sass_backtrace.first[:mixin] end # The line of the Sass template on which the error occurred. # # @return [Fixnum] def sass_line sass_backtrace.first[:line] end # Adds an entry to the exception's Sass backtrace. # # @param attrs [{Symbol => Object}] The information in the backtrace entry. # See \{#sass\_backtrace} def add_backtrace(attrs) sass_backtrace << attrs.reject {|k, v| v.nil?} end # Modify the top Sass backtrace entries # (that is, the most deeply nested ones) # to have the given attributes. # # Specifically, this goes through the backtrace entries # from most deeply nested to least, # setting the given attributes for each entry. # If an entry already has one of the given attributes set, # the pre-existing attribute takes precedence # and is not used for less deeply-nested entries # (even if they don't have that attribute set). # # @param attrs [{Symbol => Object}] The information to add to the backtrace entry. # See \{#sass\_backtrace} def modify_backtrace(attrs) attrs = attrs.reject {|k, v| v.nil?} # Move backwards through the backtrace (0...sass_backtrace.size).to_a.reverse.each do |i| entry = sass_backtrace[i] sass_backtrace[i] = attrs.merge(entry) attrs.reject! {|k, v| entry.include?(k)} break if attrs.empty? end end # @return [String] The error message def to_s @message end # Returns the standard exception backtrace, # including the Sass backtrace. # # @return [Array] def backtrace return nil if super.nil? return super if sass_backtrace.all? {|h| h.empty?} sass_backtrace.map do |h| "#{h[:filename] || "(sass)"}:#{h[:line]}" + (h[:mixin] ? ":in `#{h[:mixin]}'" : "") end + super end # Returns a string representation of the Sass backtrace. # # @param default_filename [String] The filename to use for unknown files # @see #sass_backtrace # @return [String] def sass_backtrace_str(default_filename = "an unknown file") lines = self.message.split("\n") msg = lines[0] + lines[1..-1]. map {|l| "\n" + (" " * "Syntax error: ".size) + l}.join "Syntax error: #{msg}" + Sass::Util.enum_with_index(sass_backtrace).map do |entry, i| "\n #{i == 0 ? "on" : "from"} line #{entry[:line]}" + " of #{entry[:filename] || default_filename}" + (entry[:mixin] ? ", in `#{entry[:mixin]}'" : "") end.join end class << self # Returns an error report for an exception in CSS format. # # @param e [Exception] # @param options [{Symbol => Object}] The options passed to {Sass::Engine#initialize} # @return [String] The error report # @raise [Exception] `e`, if the # {file:SASS_REFERENCE.md#full_exception-option `:full_exception`} option # is set to false. def exception_to_css(e, options) raise e unless options[:full_exception] header = header_string(e, options) <] attr_reader :selector # @param selector [Array] # The CSS selector to extend, # interspersed with {Sass::Script::Node}s # representing `#{}`-interpolation. def initialize(selector) @selector = selector super() end end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/rule_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000764012206724733033517 0ustar jamespagejamespagerequire 'pathname' require 'uri' module Sass::Tree # A static node reprenting a CSS rule. # # @see Sass::Tree class RuleNode < Node # The character used to include the parent selector PARENT = '&' # The CSS selector for this rule, # interspersed with {Sass::Script::Node}s # representing `#{}`-interpolation. # Any adjacent strings will be merged together. # # @return [Array] attr_accessor :rule # The CSS selector for this rule, # without any unresolved interpolation # but with parent references still intact. # It's only set once {Tree::Node#perform} has been called. # # @return [Selector::CommaSequence] attr_accessor :parsed_rules # The CSS selector for this rule, # without any unresolved interpolation or parent references. # It's only set once {Tree::Visitors::Cssize} has been run. # # @return [Selector::CommaSequence] attr_accessor :resolved_rules # How deep this rule is indented # relative to a base-level rule. # This is only greater than 0 in the case that: # # * This node is in a CSS tree # * The style is :nested # * This is a child rule of another rule # * The parent rule has properties, and thus will be rendered # # @return [Fixnum] attr_accessor :tabs # Whether or not this rule is the last rule in a nested group. # This is only set in a CSS tree. # # @return [Boolean] attr_accessor :group_end # @param rule [Array] # The CSS rule. See \{#rule} def initialize(rule) merged = Sass::Util.merge_adjacent_strings(rule) @rule = Sass::Util.strip_string_array(merged) @tabs = 0 try_to_parse_non_interpolated_rules super() end # If we've precached the parsed selector, set the line on it, too. def line=(line) @parsed_rules.line = line if @parsed_rules super end # If we've precached the parsed selector, set the filename on it, too. def filename=(filename) @parsed_rules.filename = filename if @parsed_rules super end # Compares the contents of two rules. # # @param other [Object] The object to compare with # @return [Boolean] Whether or not this node and the other object # are the same def ==(other) self.class == other.class && rule == other.rule && super end # Adds another {RuleNode}'s rules to this one's. # # @param node [RuleNode] The other node def add_rules(node) @rule = Sass::Util.strip_string_array( Sass::Util.merge_adjacent_strings(@rule + ["\n"] + node.rule)) try_to_parse_non_interpolated_rules end # @return [Boolean] Whether or not this rule is continued on the next line def continued? last = @rule.last last.is_a?(String) && last[-1] == ?, end # Extends this Rule's selector with the given `extends`. # # @see Node#do_extend def do_extend(extends) node = dup node.resolved_rules = resolved_rules.do_extend(extends) node end # A hash that will be associated with this rule in the CSS document # if the {file:SASS_REFERENCE.md#debug_info-option `:debug_info` option} is enabled. # This data is used by e.g. [the FireSass Firebug extension](https://addons.mozilla.org/en-US/firefox/addon/103988). # # @return [{#to_s => #to_s}] def debug_info {:filename => filename && ("file://" + URI.escape(File.expand_path(filename))), :line => self.line} end private def try_to_parse_non_interpolated_rules if @rule.all? {|t| t.kind_of?(String)} # We don't use real filename/line info because we don't have it yet. # When we get it, we'll set it on the parsed rules if possible. parser = Sass::SCSS::StaticParser.new(@rule.join.strip, 1) @parsed_rules = parser.parse_selector('') rescue nil end end end end ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/variable_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000136412206724733033514 0ustar jamespagejamespagemodule Sass module Tree # A dynamic node representing a variable definition. # # @see Sass::Tree class VariableNode < Node # The name of the variable. # @return [String] attr_reader :name # The parse tree for the variable value. # @return [Script::Node] attr_reader :expr # Whether this is a guarded variable assignment (`!default`). # @return [Boolean] attr_reader :guarded # @param name [String] The name of the variable # @param expr [Script::Node] See \{#expr} # @param guarded [Boolean] See \{#guarded} def initialize(name, expr, guarded) @name = name @expr = expr @guarded = guarded super() end end end end ././@LongLink0000644000000000000000000000016612255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/mixin_def_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000130112206724733033503 0ustar jamespagejamespagemodule Sass module Tree # A dynamic node representing a mixin definition. # # @see Sass::Tree class MixinDefNode < Node # The mixin name. # @return [String] attr_reader :name # The arguments for the mixin. # Each element is a tuple containing the variable for argument # and the parse tree for the default value of the argument. # # @return [Array<(Script::Node, Script::Node)>] attr_reader :args # @param name [String] The mixin name # @param args [Array<(Script::Node, Script::Node)>] See \{#args} def initialize(name, args) @name = name @args = args super() end end end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/each_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000102012206724733033501 0ustar jamespagejamespagerequire 'sass/tree/node' module Sass::Tree # A dynamic node representing a Sass `@each` loop. # # @see Sass::Tree class EachNode < Node # The name of the loop variable. # @return [String] attr_reader :var # The parse tree for the list. # @param [Script::Node] attr_reader :list # @param var [String] The name of the loop variable # @param list [Script::Node] The parse tree for the list def initialize(var, list) @var = var @list = list super() end end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/debug_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000057712206724733033521 0ustar jamespagejamespagemodule Sass module Tree # A dynamic node representing a Sass `@debug` statement. # # @see Sass::Tree class DebugNode < Node # The expression to print. # @return [Script::Node] attr_reader :expr # @param expr [Script::Node] The expression to print def initialize(expr) @expr = expr super() end end end end ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/function_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000132512206724733033511 0ustar jamespagejamespagemodule Sass module Tree # A dynamic node representing a function definition. # # @see Sass::Tree class FunctionNode < Node # The name of the function. # @return [String] attr_reader :name # The arguments to the function. Each element is a tuple # containing the variable for argument and the parse tree for # the default value of the argument # # @return [Array] attr_reader :args # @param name [String] The function name # @param args [Array<(Script::Node, Script::Node)>] The arguments for the function. def initialize(name, args) @name = name @args = args super() end end end end ././@LongLink0000644000000000000000000000016312255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/return_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000057712206724733033521 0ustar jamespagejamespagemodule Sass module Tree # A dynamic node representing returning from a function. # # @see Sass::Tree class ReturnNode < Node # The expression to return. # @type [Script::Node] attr_reader :expr # @param expr [Script::Node] The expression to return def initialize(expr) @expr = expr super() end end end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/prop_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000001241312206724733033511 0ustar jamespagejamespagemodule Sass::Tree # A static node reprenting a CSS property. # # @see Sass::Tree class PropNode < Node # The name of the property, # interspersed with {Sass::Script::Node}s # representing `#{}`-interpolation. # Any adjacent strings will be merged together. # # @return [Array] attr_accessor :name # The name of the property # after any interpolated SassScript has been resolved. # Only set once \{Tree::Visitors::Perform} has been run. # # @return [String] attr_accessor :resolved_name # The value of the property. # # @return [Sass::Script::Node] attr_accessor :value # Whether the property was marked as !important. # # @return [Boolean] attr_accessor :important # The value of the property # after any interpolated SassScript has been resolved. # Only set once \{Tree::Visitors::Perform} has been run. # # @return [String] attr_accessor :resolved_value # How deep this property is indented # relative to a normal property. # This is only greater than 0 in the case that: # # * This node is in a CSS tree # * The style is :nested # * This is a child property of another property # * The parent property has a value, and thus will be rendered # # @return [Fixnum] attr_accessor :tabs # @param name [Array] See \{#name} # @param value [Sass::Script::Node] See \{#value} # @param important [Boolean] whether this is an !important property # @param prop_syntax [Symbol] `:new` if this property uses `a: b`-style syntax, # `:old` if it uses `:a b`-style syntax def initialize(name, value, important, prop_syntax) @name = Sass::Util.strip_string_array( Sass::Util.merge_adjacent_strings(name)) @value = value @tabs = 0 @prop_syntax = prop_syntax @important = important super() end # Compares the names and values of two properties. # # @param other [Object] The object to compare with # @return [Boolean] Whether or not this node and the other object # are the same def ==(other) self.class == other.class && name == other.name && value == other.value && super end # Returns a appropriate message indicating how to escape pseudo-class selectors. # This only applies for old-style properties with no value, # so returns the empty string if this is new-style. # # @return [String] The message def pseudo_class_selector_message return "" if @prop_syntax == :new || !value.is_a?(Sass::Script::String) || !value.value.empty? "\nIf #{declaration.dump} should be a selector, use \"\\#{declaration}\" instead." end # Computes the Sass or SCSS code for the variable declaration. # This is like \{#to\_scss} or \{#to\_sass}, # except it doesn't print any child properties or a trailing semicolon. # # @param opts [{Symbol => Object}] The options hash for the tree. # @param fmt [Symbol] `:scss` or `:sass`. def declaration(opts = {:old => @prop_syntax == :old}, fmt = :sass) name = self.name.map {|n| n.is_a?(String) ? n : "\#{#{n.to_sass(opts)}}"}.join if name[0] == ?: raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\" hack is not allowed in the Sass indented syntax") end old = opts[:old] && fmt == :sass initial = old ? ':' : '' mid = old ? '' : ':' "#{initial}#{name}#{mid} #{self.class.val_to_sass(value, opts)}#{' !important' if important}".rstrip end private def check! if @options[:property_syntax] && @options[:property_syntax] != @prop_syntax raise Sass::SyntaxError.new( "Illegal property syntax: can't use #{@prop_syntax} syntax when :property_syntax => #{@options[:property_syntax].inspect} is set.") elsif resolved_value.empty? raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no value)." + pseudo_class_selector_message) end end class << self # @private def val_to_sass(value, opts) val_to_sass_comma(value, opts).to_sass(opts) end private def val_to_sass_comma(node, opts) return node unless node.is_a?(Sass::Script::Operation) return val_to_sass_concat(node, opts) unless node.operator == :comma Sass::Script::Operation.new( val_to_sass_concat(node.operand1, opts), val_to_sass_comma(node.operand2, opts), node.operator) end def val_to_sass_concat(node, opts) return node unless node.is_a?(Sass::Script::Operation) return val_to_sass_div(node, opts) unless node.operator == :space Sass::Script::Operation.new( val_to_sass_div(node.operand1, opts), val_to_sass_concat(node.operand2, opts), node.operator) end def val_to_sass_div(node, opts) unless node.is_a?(Sass::Script::Operation) && node.operator == :div && node.operand1.is_a?(Sass::Script::Number) && node.operand2.is_a?(Sass::Script::Number) && (!node.operand1.original || !node.operand2.original) return node end Sass::Script::String.new("(#{node.to_sass(opts)})") end end end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/root_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000153612206724733033515 0ustar jamespagejamespagemodule Sass module Tree # A static node that is the root node of the Sass document. class RootNode < Node # The Sass template from which this node was created # # @param template [String] attr_reader :template # @param template [String] The Sass template from which this node was created def initialize(template) super() @template = template end # Runs the dynamic Sass code *and* computes the CSS for the tree. # @see #to_s def render Visitors::CheckNesting.visit(self) result = Visitors::Perform.visit(self) Visitors::CheckNesting.visit(result) # Check again to validate mixins result, extends = Visitors::Cssize.visit(result) result = result.do_extend(extends) unless extends.empty? result.to_s end end end end ././@LongLink0000644000000000000000000000015712255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/if_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000305412206724733033512 0ustar jamespagejamespagerequire 'sass/tree/node' module Sass::Tree # A dynamic node representing a Sass `@if` statement. # # {IfNode}s are a little odd, in that they also represent `@else` and `@else if`s. # This is done as a linked list: # each {IfNode} has a link (\{#else}) to the next {IfNode}. # # @see Sass::Tree class IfNode < Node # The conditional expression. # If this is nil, this is an `@else` node, not an `@else if`. # # @return [Script::Expr] attr_reader :expr # The next {IfNode} in the if-else list, or `nil`. # # @return [IfNode] attr_accessor :else # @param expr [Script::Expr] See \{#expr} def initialize(expr) @expr = expr @last_else = self super() end # Append an `@else` node to the end of the list. # # @param node [IfNode] The `@else` node to append def add_else(node) @last_else.else = node @last_else = node end # @see Node#options= def options=(options) super self.else.options = options if self.else end def _dump(f) Marshal.dump([self.expr, self.else, self.children]) end def self._load(data) expr, else_, children = Marshal.load(data) node = IfNode.new(expr) node.else = else_ node.children = children node.instance_variable_set('@last_else', node.else ? node.else.instance_variable_get('@last_else') : node) node end # @see Node#deep_copy def deep_copy node = super node.else = self.else.deep_copy if self.else node end end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/while_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000056712206724733033520 0ustar jamespagejamespagerequire 'sass/tree/node' module Sass::Tree # A dynamic node representing a Sass `@while` loop. # # @see Sass::Tree class WhileNode < Node # The parse tree for the continuation expression. # @return [Script::Node] attr_reader :expr # @param expr [Script::Node] See \{#expr} def initialize(expr) @expr = expr super() end end end ././@LongLink0000644000000000000000000000016012255653646011655 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/for_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000155012206724733033511 0ustar jamespagejamespagerequire 'sass/tree/node' module Sass::Tree # A dynamic node representing a Sass `@for` loop. # # @see Sass::Tree class ForNode < Node # The name of the loop variable. # @return [String] attr_reader :var # The parse tree for the initial expression. # @return [Script::Node] attr_reader :from # The parse tree for the final expression. # @return [Script::Node] attr_reader :to # Whether to include `to` in the loop or stop just before. # @return [Boolean] attr_reader :exclusive # @param var [String] See \{#var} # @param from [Script::Node] See \{#from} # @param to [Script::Node] See \{#to} # @param exclusive [Boolean] See \{#exclusive} def initialize(var, from, to, exclusive) @var = var @from = from @to = to @exclusive = exclusive super() end end end ././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/visitors/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000775000175000017500000000000012206724733033506 5ustar jamespagejamespage././@LongLink0000644000000000000000000000017012255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/visitors/perform.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000002272412206724733033517 0ustar jamespagejamespage# A visitor for converting a dynamic Sass tree into a static Sass tree. class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base # @param root [Tree::Node] The root node of the tree to visit. # @param environment [Sass::Environment] The lexical environment. # @return [Tree::Node] The resulting tree of static nodes. def self.visit(root, environment = Sass::Environment.new) new(environment).send(:visit, root) end protected def initialize(env) @environment = env end # If an exception is raised, this add proper metadata to the backtrace. def visit(node) super(node.dup) rescue Sass::SyntaxError => e e.modify_backtrace(:filename => node.filename, :line => node.line) raise e end # Keeps track of the current environment. def visit_children(parent) with_environment Sass::Environment.new(@environment) do parent.children = super.flatten parent end end # Runs a block of code with the current environment replaced with the given one. # # @param env [Sass::Environment] The new environment for the duration of the block. # @yield A block in which the environment is set to `env`. # @return [Object] The return value of the block. def with_environment(env) old_env, @environment = @environment, env yield ensure @environment = old_env end # Sets the options on the environment if this is the top-level root. def visit_root(node) @environment.options = node.options if @environment.options.nil? || @environment.options.empty? yield rescue Sass::SyntaxError => e e.sass_template ||= node.template raise e end # Removes this node from the tree if it's a silent comment. def visit_comment(node) return [] if node.invisible? if node.evaluated? node.value.gsub!(/(^|[^\\])\#\{([^}]*)\}/) do |md| $1+Sass::Script.parse($2, node.line, 0, node.options).perform(@environment).to_s end node.value = run_interp([Sass::Script::String.new(node.value)]) end node end # Prints the expression to STDERR. def visit_debug(node) res = node.expr.perform(@environment) res = res.value if res.is_a?(Sass::Script::String) if node.filename $stderr.puts "#{node.filename}:#{node.line} DEBUG: #{res}" else $stderr.puts "Line #{node.line} DEBUG: #{res}" end [] end # Runs the child nodes once for each value in the list. def visit_each(node) list = node.list.perform(@environment) with_environment Sass::Environment.new(@environment) do list.to_a.map do |v| @environment.set_local_var(node.var, v) node.children.map {|c| visit(c)} end.flatten end end # Runs SassScript interpolation in the selector, # and then parses the result into a {Sass::Selector::CommaSequence}. def visit_extend(node) parser = Sass::SCSS::CssParser.new(run_interp(node.selector), node.line) node.resolved_selector = parser.parse_selector(node.filename) node end # Runs the child nodes once for each time through the loop, varying the variable each time. def visit_for(node) from = node.from.perform(@environment) to = node.to.perform(@environment) from.assert_int! to.assert_int! to = to.coerce(from.numerator_units, from.denominator_units) range = Range.new(from.to_i, to.to_i, node.exclusive) with_environment Sass::Environment.new(@environment) do range.map do |i| @environment.set_local_var(node.var, Sass::Script::Number.new(i, from.numerator_units, from.denominator_units)) node.children.map {|c| visit(c)} end.flatten end end # Loads the function into the environment. def visit_function(node) @environment.set_function(node.name, Sass::Callable.new(node.name, node.args, @environment, node.children)) [] end # Runs the child nodes if the conditional expression is true; # otherwise, tries the else nodes. def visit_if(node) if node.expr.nil? || node.expr.perform(@environment).to_bool yield node.children elsif node.else visit(node.else) else [] end end # Returns a static DirectiveNode if this is importing a CSS file, # or parses and includes the imported Sass file. def visit_import(node) if path = node.css_import? return Sass::Tree::DirectiveNode.new("@import url(#{path})") end @environment.push_frame(:filename => node.filename, :line => node.line) root = node.imported_file.to_tree node.children = root.children.map {|c| visit(c)}.flatten node rescue Sass::SyntaxError => e e.modify_backtrace(:filename => node.imported_file.options[:filename]) e.add_backtrace(:filename => node.filename, :line => node.line) raise e ensure @environment.pop_frame end # Loads a mixin into the environment. def visit_mixindef(node) @environment.set_mixin(node.name, Sass::Callable.new(node.name, node.args, @environment, node.children)) [] end # Runs a mixin. def visit_mixin(node) handle_include_loop!(node) if @environment.mixins_in_use.include?(node.name) original_env = @environment original_env.push_frame(:filename => node.filename, :line => node.line) original_env.prepare_frame(:mixin => node.name) raise Sass::SyntaxError.new("Undefined mixin '#{node.name}'.") unless mixin = @environment.mixin(node.name) passed_args = node.args.dup passed_keywords = node.keywords.dup raise Sass::SyntaxError.new(< e if original_env # Don't add backtrace info if this is an @include loop e.modify_backtrace(:mixin => node.name, :line => node.line) e.add_backtrace(:line => node.line) end raise e ensure original_env.pop_frame if original_env end # Runs any SassScript that may be embedded in a property. def visit_prop(node) node.resolved_name = run_interp(node.name) val = node.value.perform(@environment) node.resolved_value = val.to_s yield end # Returns the value of the expression. def visit_return(node) throw :_sass_return, node.expr.perform(@environment) end # Runs SassScript interpolation in the selector, # and then parses the result into a {Sass::Selector::CommaSequence}. def visit_rule(node) parser = Sass::SCSS::StaticParser.new(run_interp(node.rule), node.line) node.parsed_rules ||= parser.parse_selector(node.filename) yield end # Loads the new variable value into the environment. def visit_variable(node) return [] if node.guarded && !@environment.var(node.name).nil? val = node.expr.perform(@environment) @environment.set_var(node.name, val) [] end # Prints the expression to STDERR with a stylesheet trace. def visit_warn(node) @environment.push_frame(:filename => node.filename, :line => node.line) res = node.expr.perform(@environment) res = res.value if res.is_a?(Sass::Script::String) msg = "WARNING: #{res}\n" @environment.stack.reverse.each_with_index do |entry, i| msg << " #{i == 0 ? "on" : "from"} line #{entry[:line]}" << " of #{entry[:filename] || "an unknown file"}" msg << ", in `#{entry[:mixin]}'" if entry[:mixin] msg << "\n" end Sass::Util.sass_warn msg [] ensure @environment.pop_frame end # Runs the child nodes until the continuation expression becomes false. def visit_while(node) children = [] with_environment Sass::Environment.new(@environment) do children += node.children.map {|c| visit(c)} while node.expr.perform(@environment).to_bool end children.flatten end def visit_directive(node) if node.value['#{'] node.value = run_interp(Sass::Engine.parse_interp(node.value, node.line, 0, node.options)) end yield node end private def run_interp(text) text.map do |r| next r if r.is_a?(String) val = r.perform(@environment) # Interpolated strings should never render with quotes next val.value if val.is_a?(Sass::Script::String) val.to_s end.join.strip end def handle_include_loop!(node) msg = "An @include loop has been found:" mixins = @environment.stack.map {|s| s[:mixin]}.compact if mixins.size == 2 && mixins[0] == mixins[1] raise Sass::SyntaxError.new("#{msg} #{node.name} includes itself") end mixins << node.name msg << "\n" << Sass::Util.enum_cons(mixins, 2).map do |m1, m2| " #{m1} includes #{m2}" end.join("\n") raise Sass::SyntaxError.new(msg) end end ././@LongLink0000644000000000000000000000016712255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/visitors/cssize.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000001352112206724733033512 0ustar jamespagejamespage# A visitor for converting a static Sass tree into a static CSS tree. class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base # @param root [Tree::Node] The root node of the tree to visit. # @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes # *and* the extensions defined for this tree def self.visit(root); super; end protected # Returns the immediate parent of the current node. # @return [Tree::Node] attr_reader :parent def initialize @extends = Sass::Util::SubsetMap.new end # If an exception is raised, this adds proper metadata to the backtrace. def visit(node) super(node.dup) rescue Sass::SyntaxError => e e.modify_backtrace(:filename => node.filename, :line => node.line) raise e end # Keeps track of the current parent node. def visit_children(parent) with_parent parent do parent.children = super.flatten parent end end # Runs a block of code with the current parent node # replaced with the given node. # # @param parent [Tree::Node] The new parent for the duration of the block. # @yield A block in which the parent is set to `parent`. # @return [Object] The return value of the block. def with_parent(parent) old_parent, @parent = @parent, parent yield ensure @parent = old_parent end # In Ruby 1.8, ensures that there's only one `@charset` directive # and that it's at the top of the document. # # @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes # *and* the extensions defined for this tree def visit_root(node) yield # In Ruby 1.9 we can make all @charset nodes invisible # and infer the final @charset from the encoding of the final string. if Sass::Util.ruby1_8? && parent.nil? charset = node.children.find {|c| c.is_a?(Sass::Tree::CharsetNode)} node.children.reject! {|c| c.is_a?(Sass::Tree::CharsetNode)} node.children.unshift charset if charset end return node, @extends rescue Sass::SyntaxError => e e.sass_template ||= node.template raise e end # Registers an extension in the `@extends` subset map. def visit_extend(node) node.resolved_selector.members.each do |seq| if seq.members.size > 1 raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend nested selectors") end sseq = seq.members.first if !sseq.is_a?(Sass::Selector::SimpleSequence) raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: invalid selector") end sel = sseq.members parent.resolved_rules.members.each do |seq| if !seq.members.last.is_a?(Sass::Selector::SimpleSequence) raise Sass::SyntaxError.new("#{seq} can't extend: invalid selector") end @extends[sel] = seq end end [] end # Modifies exception backtraces to include the imported file. def visit_import(node) # Don't use #visit_children to avoid adding the import node to the list of parents. node.children.map {|c| visit(c)}.flatten rescue Sass::SyntaxError => e e.modify_backtrace(:filename => node.children.first.filename) e.add_backtrace(:filename => node.filename, :line => node.line) raise e end # Bubbles the `@media` directive up through RuleNodes # and merges it with other `@media` directives. def visit_media(node) if parent.is_a?(Sass::Tree::RuleNode) new_rule = parent.dup new_rule.children = node.children node.children = with_parent(node) {Array(visit(new_rule))} # If the last child is actually the end of the group, # the parent's cssize will set it properly node.children.last.group_end = false unless node.children.empty? else yield end media = node.children.select {|c| c.is_a?(Sass::Tree::MediaNode)} node.children.reject! {|c| c.is_a?(Sass::Tree::MediaNode)} media.each {|n| n.query = "#{node.query} and #{n.query}"} (node.children.empty? ? [] : [node]) + media end # Asserts that all the mixin's children are valid in their new location. def visit_mixin(node) # Don't use #visit_children to avoid adding the mixin node to the list of parents. node.children.map {|c| visit(c)}.flatten rescue Sass::SyntaxError => e e.modify_backtrace(:mixin => node.name, :filename => node.filename, :line => node.line) e.add_backtrace(:filename => node.filename, :line => node.line) raise e end # Converts nested properties into flat properties # and updates the indentation of the prop node based on the nesting level. def visit_prop(node) if parent.is_a?(Sass::Tree::PropNode) node.resolved_name = "#{parent.resolved_name}-#{node.resolved_name}" node.tabs = parent.tabs + (parent.resolved_value.empty? ? 0 : 1) if node.style == :nested end yield result = node.children.dup if !node.resolved_value.empty? || node.children.empty? node.send(:check!) result.unshift(node) end result end # Resolves parent references and nested selectors, # and updates the indentation of the rule node based on the nesting level. def visit_rule(node) parent_resolved_rules = parent.is_a?(Sass::Tree::RuleNode) ? parent.resolved_rules : nil # It's possible for resolved_rules to be set if we've duplicated this node during @media bubbling node.resolved_rules ||= node.parsed_rules.resolve_parent_refs(parent_resolved_rules) yield rules = node.children.select {|c| c.is_a?(Sass::Tree::RuleNode) || c.is_a?(Sass::Tree::MediaNode)} props = node.children.reject {|c| c.is_a?(Sass::Tree::RuleNode) || c.is_a?(Sass::Tree::MediaNode) || c.invisible?} unless props.empty? node.children = props rules.each {|r| r.tabs += 1} if node.style == :nested rules.unshift(node) end rules.last.group_end = true unless parent.is_a?(Sass::Tree::RuleNode) || rules.empty? rules end end ././@LongLink0000644000000000000000000000017012255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/visitors/convert.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000001536212206724733033517 0ustar jamespagejamespage# A visitor for converting a Sass tree into a source string. class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base # Runs the visitor on a tree. # # @param root [Tree::Node] The root node of the Sass tree. # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}). # @param format [Symbol] `:sass` or `:scss`. # @return [String] The Sass or SCSS source for the tree. def self.visit(root, options, format) new(options, format).send(:visit, root) end protected def initialize(options, format) @options = options @format = format @tabs = 0 end def visit_children(parent) @tabs += 1 return @format == :sass ? "\n" : " {}\n" if parent.children.empty? (@format == :sass ? "\n" : " {\n") + super.join.rstrip + (@format == :sass ? "\n" : " }\n") ensure @tabs -= 1 end # Ensures proper spacing between top-level nodes. def visit_root(node) Sass::Util.enum_cons(node.children + [nil], 2).map do |child, nxt| visit(child) + if nxt && (child.is_a?(Sass::Tree::CommentNode) && child.line + child.value.count("\n") + 1 == nxt.line) || (child.is_a?(Sass::Tree::ImportNode) && nxt.is_a?(Sass::Tree::ImportNode) && child.line + 1 == nxt.line) || (child.is_a?(Sass::Tree::VariableNode) && nxt.is_a?(Sass::Tree::VariableNode) && child.line + 1 == nxt.line) "" else "\n" end end.join.rstrip + "\n" end def visit_charset(node) "#{tab_str}@charset \"#{node.name}\"#{semi}\n" end def visit_comment(node) content = if @format == :sass content = node.value.gsub(/\*\/$/, '').rstrip if content =~ /\A[ \t]/ # Re-indent SCSS comments like this: # /* foo # bar # baz */ content.gsub!(/^/, ' ') content.sub!(/\A([ \t]*)\/\*/, '/*\1') end content = unless content.include?("\n") content else content.gsub!(/\n( \*|\/\/)/, "\n ") spaces = content.scan(/\n( *)/).map {|s| s.first.size}.min sep = node.silent ? "\n//" : "\n *" if spaces >= 2 content.gsub(/\n /, sep) else content.gsub(/\n#{' ' * spaces}/, sep) end end content.gsub!(/\A\/\*/, '//') if node.silent content.gsub!(/^/, tab_str) content.rstrip + "\n" else spaces = (' ' * [@tabs - node.value[/^ */].size, 0].max) content = if node.silent node.value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '') else node.value end.gsub(/^/, spaces) + "\n" content end if node.loud if node.silent content.gsub!(%r{^\s*(//!?)}, '//!') else content.sub!(%r{^\s*(/\*)}, '/*!') end end content end def visit_debug(node) "#{tab_str}@debug #{node.expr.to_sass(@options)}#{semi}\n" end def visit_directive(node) res = "#{tab_str}#{node.value}" return res + "#{semi}\n" unless node.has_children res + yield + "\n" end def visit_each(node) "#{tab_str}@each $#{dasherize(node.var)} in #{node.list.to_sass(@options)}#{yield}" end def visit_extend(node) "#{tab_str}@extend #{selector_to_src(node.selector).lstrip}#{semi}\n" end def visit_for(node) "#{tab_str}@for $#{dasherize(node.var)} from #{node.from.to_sass(@options)} " + "#{node.exclusive ? "to" : "through"} #{node.to.to_sass(@options)}#{yield}" end def visit_function(node) args = node.args.map do |v, d| d ? "#{v.to_sass(@options)}: #{d.to_sass(@options)}" : v.to_sass(@options) end.join(", ") "#{tab_str}@function #{dasherize(node.name)}(#{args})#{yield}" end def visit_if(node) name = if !@is_else; "if" elsif node.expr; "else if" else; "else" end str = "#{tab_str}@#{name}" str << " #{node.expr.to_sass(@options)}" if node.expr str << yield @is_else = true str << visit(node.else) if node.else str ensure @is_else = false end def visit_import(node) quote = @format == :scss ? '"' : '' "#{tab_str}@import #{quote}#{node.imported_filename}#{quote}#{semi}\n" end def visit_media(node) "#{tab_str}@media #{node.query}#{yield}" end def visit_mixindef(node) args = if node.args.empty? "" else '(' + node.args.map do |v, d| if d "#{v.to_sass(@options)}: #{d.to_sass(@options)}" else v.to_sass(@options) end end.join(", ") + ')' end "#{tab_str}#{@format == :sass ? '=' : '@mixin '}#{dasherize(node.name)}#{args}#{yield}" end def visit_mixin(node) unless node.args.empty? && node.keywords.empty? args = node.args.map {|a| a.to_sass(@options)}.join(", ") keywords = node.keywords.map {|k, v| "$#{dasherize(k)}: #{v.to_sass(@options)}"}.join(', ') arglist = "(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})" end "#{tab_str}#{@format == :sass ? '+' : '@include '}#{dasherize(node.name)}#{arglist}#{semi}\n" end def visit_prop(node) res = tab_str + node.declaration(@options, @format) return res + semi + "\n" if node.children.empty? res + yield.rstrip + semi + "\n" end def visit_return(node) "#{tab_str}@return #{node.expr.to_sass(@options)}#{semi}\n" end def visit_rule(node) if @format == :sass name = selector_to_sass(node.rule) name = "\\" + name if name[0] == ?: name.gsub(/^/, tab_str) + yield elsif @format == :scss name = selector_to_scss(node.rule) res = name + yield if node.children.last.is_a?(Sass::Tree::CommentNode) && node.children.last.silent res.slice!(-3..-1) res << "\n" << tab_str << "}\n" end res end end def visit_variable(node) "#{tab_str}$#{dasherize(node.name)}: #{node.expr.to_sass(@options)}#{' !default' if node.guarded}#{semi}\n" end def visit_warn(node) "#{tab_str}@warn #{node.expr.to_sass(@options)}#{semi}\n" end def visit_while(node) "#{tab_str}@while #{node.expr.to_sass(@options)}#{yield}" end private def selector_to_src(sel) @format == :sass ? selector_to_sass(sel) : selector_to_scss(sel) end def selector_to_sass(sel) sel.map do |r| if r.is_a?(String) r.gsub(/(,[ \t]*)?\n\s*/) {$1 ? $1 + "\n" : " "} else "\#{#{r.to_sass(@options)}}" end end.join end def selector_to_scss(sel) sel.map {|r| r.is_a?(String) ? r : "\#{#{r.to_sass(@options)}}"}. join.gsub(/^[ \t]*/, tab_str) end def semi @format == :sass ? "" : ";" end def tab_str ' ' * @tabs end def dasherize(s) if @options[:dasherize] s.gsub('_', '-') else s end end end ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/visitors/base.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000514112206724733033511 0ustar jamespagejamespage# Visitors are used to traverse the Sass parse tree. # Visitors should extend {Visitors::Base}, # which provides a small amount of scaffolding for traversal. module Sass::Tree::Visitors # The abstract base class for Sass visitors. # Visitors should extend this class, # then implement `visit_*` methods for each node they care about # (e.g. `visit_rule` for {RuleNode} or `visit_for` for {ForNode}). # These methods take the node in question as argument. # They may `yield` to visit the child nodes of the current node. # # *Note*: due to the unusual nature of {Sass::Tree::IfNode}, # special care must be taken to ensure that it is properly handled. # In particular, there is no built-in scaffolding # for dealing with the return value of `@else` nodes. # # @abstract class Base # Runs the visitor on a tree. # # @param root [Tree::Node] The root node of the Sass tree. # @return [Object] The return value of \{#visit} for the root node. def self.visit(root) new.send(:visit, root) end protected # Runs the visitor on the given node. # This can be overridden by subclasses that need to do something for each node. # # @param node [Tree::Node] The node to visit. # @return [Object] The return value of the `visit_*` method for this node. def visit(node) method = "visit_#{node_name node}" if self.respond_to?(method) self.send(method, node) {visit_children(node)} else visit_children(node) end end # Visit the child nodes for a given node. # This can be overridden by subclasses that need to do something # with the child nodes' return values. # # This method is run when `visit_*` methods `yield`, # and its return value is returned from the `yield`. # # @param parent [Tree::Node] The parent node of the children to visit. # @return [Array] The return values of the `visit_*` methods for the children. def visit_children(parent) parent.children.map {|c| visit(c)} end NODE_NAME_RE = /.*::(.*?)Node$/ # Returns the name of a node as used in the `visit_*` method. # # @param [Tree::Node] node The node. # @return [String] The name. def node_name(node) @@node_names ||= {} @@node_names[node.class.name] ||= node.class.name.gsub(NODE_NAME_RE, '\\1').downcase end # `yield`s, then runs the visitor on the `@else` clause if the node has one. # This exists to ensure that the contents of the `@else` clause get visited. def visit_if(node) yield visit(node.else) if node.else node end end end ././@LongLink0000644000000000000000000000017612255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/visitors/check_nesting.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000001113012206724733033504 0ustar jamespagejamespage# A visitor for checking that all nodes are properly nested. class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base protected def visit(node) if error = (@parent && ( try_send("invalid_#{node_name @parent}_child?", @parent, node) || try_send("invalid_#{node_name node}_parent?", @parent, node))) || (@real_parent && ( try_send("invalid_#{node_name @real_parent}_real_child?", @real_parent, node) || try_send("invalid_#{node_name node}_real_parent?", @real_parent, node))) raise Sass::SyntaxError.new(error) end super rescue Sass::SyntaxError => e e.modify_backtrace(:filename => node.filename, :line => node.line) raise e end PARENT_CLASSES = [ Sass::Tree::EachNode, Sass::Tree::ForNode, Sass::Tree::IfNode, Sass::Tree::ImportNode, Sass::Tree::MixinNode, Sass::Tree::WhileNode] def visit_children(parent) old_parent = @parent @parent = parent unless is_any_of?(parent, PARENT_CLASSES) old_real_parent, @real_parent = @real_parent, parent super ensure @parent = old_parent @real_parent = old_real_parent end def visit_root(node) yield rescue Sass::SyntaxError => e e.sass_template ||= node.template raise e end def visit_import(node) yield rescue Sass::SyntaxError => e e.modify_backtrace(:filename => node.children.first.filename) e.add_backtrace(:filename => node.filename, :line => node.line) raise e end def invalid_charset_parent?(parent, child) "@charset may only be used at the root of a document." unless parent.is_a?(Sass::Tree::RootNode) end INVALID_EXTEND_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::MixinDefNode] def invalid_extend_parent?(parent, child) unless is_any_of?(parent, INVALID_EXTEND_PARENTS) "Extend directives may only be used within rules." end end def invalid_function_parent?(parent, child) "Functions may only be defined at the root of a document." unless parent.is_a?(Sass::Tree::RootNode) end INVALID_FUNCTION_CHILDREN = [ Sass::Tree::CommentNode, Sass::Tree::DebugNode, Sass::Tree::EachNode, Sass::Tree::ForNode, Sass::Tree::IfNode, Sass::Tree::ReturnNode, Sass::Tree::VariableNode, Sass::Tree::WarnNode, Sass::Tree::WhileNode ] def invalid_function_child?(parent, child) unless is_any_of?(child, INVALID_FUNCTION_CHILDREN) "Functions can only contain variable declarations and control directives." end end INVALID_IMPORT_PARENTS = [ Sass::Tree::IfNode, Sass::Tree::ForNode, Sass::Tree::WhileNode, Sass::Tree::EachNode, Sass::Tree::MixinDefNode ] def invalid_import_parent?(parent, child) if is_any_of?(@real_parent, INVALID_IMPORT_PARENTS) return "Import directives may not be used within control directives or mixins." end return if parent.is_a?(Sass::Tree::RootNode) return "CSS import directives may only be used at the root of a document." if child.css_import? # If this is a nested @import, we need to make sure it doesn't have anything # that's legal at top-level but not in the current context (e.g. mixin defs). child.imported_file.to_tree.children.each {|c| visit(c)} nil rescue Sass::SyntaxError => e e.modify_backtrace(:filename => child.imported_file.options[:filename]) e.add_backtrace(:filename => child.filename, :line => child.line) raise e end def invalid_import_real_parent?(parent, child) end def invalid_mixindef_parent?(parent, child) "Mixins may only be defined at the root of a document." unless parent.is_a?(Sass::Tree::RootNode) end INVALID_PROP_CHILDREN = [Sass::Tree::CommentNode, Sass::Tree::PropNode] def invalid_prop_child?(parent, child) unless is_any_of?(child, INVALID_PROP_CHILDREN) "Illegal nesting: Only properties may be nested beneath properties." end end INVALID_PROP_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::PropNode, Sass::Tree::MixinDefNode, Sass::Tree::DirectiveNode] def invalid_prop_parent?(parent, child) unless is_any_of?(parent, INVALID_PROP_PARENTS) "Properties are only allowed within rules, directives, or other properties." + child.pseudo_class_selector_message end end def invalid_return_parent?(parent, child) "@return may only be used within a function." unless parent.is_a?(Sass::Tree::FunctionNode) end private def is_any_of?(val, classes) for c in classes return true if val.is_a?(c) end return false end def try_send(method, *args, &block) return unless respond_to?(method) send(method, *args, &block) end end ././@LongLink0000644000000000000000000000016712255653646011664 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/visitors/to_css.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000001605312206724733033515 0ustar jamespagejamespage# A visitor for converting a Sass tree into CSS. class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base protected def initialize @tabs = 0 end def visit(node) super rescue Sass::SyntaxError => e e.modify_backtrace(:filename => node.filename, :line => node.line) raise e end def with_tabs(tabs) old_tabs, @tabs = @tabs, tabs yield ensure @tabs = old_tabs end def visit_root(node) result = String.new node.children.each do |child| next if child.invisible? child_str = visit(child) result << child_str + (node.style == :compressed ? '' : "\n") end result.rstrip! return "" if result.empty? result << "\n" unless Sass::Util.ruby1_8? || result.ascii_only? if node.children.first.is_a?(Sass::Tree::CharsetNode) begin encoding = node.children.first.name # Default to big-endian encoding, because we have to decide somehow encoding << 'BE' if encoding =~ /\Autf-(16|32)\Z/i result = result.encode(Encoding.find(encoding)) rescue EncodingError end end result = "@charset \"#{result.encoding.name}\";#{ node.style == :compressed ? '' : "\n" }".encode(result.encoding) + result end result rescue Sass::SyntaxError => e e.sass_template ||= node.template raise e end def visit_charset(node) "@charset \"#{node.name}\";" end def visit_comment(node) return if node.invisible? spaces = (' ' * [@tabs - node.value[/^ */].size, 0].max) content = node.value.gsub(/^/, spaces).gsub(%r{^(\s*)//(.*)$}) do |md| "#{$1}/*#{$2} */" end if content =~ /[^\\]\#\{.*\}/ Sass::Util.sass_warn < false, :line_comments => false, :style => :compressed) node end end ././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/comment_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000403012206724733033505 0ustar jamespagejamespagerequire 'sass/tree/node' module Sass::Tree # A static node representing a Sass comment (silent or loud). # # @see Sass::Tree class CommentNode < Node # The text of the comment, not including `/*` and `*/`. # # @return [String] attr_accessor :value # Whether the comment is loud. # # Loud comments start with ! and force the comment to be generated # irrespective of compilation settings or the comment syntax used. # # @return [Boolean] attr_accessor :loud # Whether or not the comment is silent (that is, doesn't output to CSS). # # @return [Boolean] attr_accessor :silent # @param value [String] See \{#value} # @param silent [Boolean] See \{#silent} def initialize(value, silent) @lines = [] @silent = silent @value = normalize_indentation value @loud = @value =~ %r{^(/[\/\*])?!} @value.sub!("#{$1}!", $1.to_s) if @loud super() end # Compares the contents of two comments. # # @param other [Object] The object to compare with # @return [Boolean] Whether or not this node and the other object # are the same def ==(other) self.class == other.class && value == other.value && silent == other.silent end # Returns `true` if this is a silent comment # or the current style doesn't render comments. # # Comments starting with ! are never invisible (and the ! is removed from the output.) # # @return [Boolean] def invisible? if @loud return false else @silent || (style == :compressed) end end # Returns whether this comment should be interpolated for dynamic comment generation. def evaluated? @loud end private def normalize_indentation(str) pre = str.split("\n").inject(str[/^[ \t]*/].split("")) do |pre, line| line[/^[ \t]*/].split("").zip(pre).inject([]) do |arr, (a, b)| break arr if a != b arr + [a] end end.join str.gsub(/^#{pre}/, '') end end end ././@LongLink0000644000000000000000000000015412255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000001507512206724733033520 0ustar jamespagejamespagemodule Sass # A namespace for nodes in the Sass parse tree. # # The Sass parse tree has three states: dynamic, static Sass, and static CSS. # # When it's first parsed, a Sass document is in the dynamic state. # It has nodes for mixin definitions and `@for` loops and so forth, # in addition to nodes for CSS rules and properties. # Nodes that only appear in this state are called **dynamic nodes**. # # {Tree::Visitors::Perform} creates a static Sass tree, which is different. # It still has nodes for CSS rules and properties # but it doesn't have any dynamic-generation-related nodes. # The nodes in this state are in the same structure as the Sass document: # rules and properties are nested beneath one another. # Nodes that can be in this state or in the dynamic state # are called **static nodes**. # # {Tree::Visitors::Cssize} is then used to create a static CSS tree. # This is like a static Sass tree, # but the structure exactly mirrors that of the generated CSS. # Rules and properties can't be nested beneath one another in this state. # # Finally, {Tree::Visitors::ToCss} can be called on a static CSS tree # to get the actual CSS code as a string. module Tree # The abstract superclass of all parse-tree nodes. class Node include Enumerable # The child nodes of this node. # # @return [Array] attr_accessor :children # Whether or not this node has child nodes. # This may be true even when \{#children} is empty, # in which case this node has an empty block (e.g. `{}`). # # @return [Boolean] attr_accessor :has_children # The line of the document on which this node appeared. # # @return [Fixnum] attr_accessor :line # The name of the document on which this node appeared. # # @return [String] attr_writer :filename # The options hash for the node. # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}. # # @return [{Symbol => Object}] attr_reader :options def initialize @children = [] end # Sets the options hash for the node and all its children. # # @param options [{Symbol => Object}] The options # @see #options def options=(options) children.each {|c| c.options = options} @options = options end # @private def children=(children) self.has_children ||= !children.empty? @children = children end # The name of the document on which this node appeared. # # @return [String] def filename @filename || (@options && @options[:filename]) end # Appends a child to the node. # # @param child [Tree::Node, Array] The child node or nodes # @raise [Sass::SyntaxError] if `child` is invalid def <<(child) return if child.nil? if child.is_a?(Array) child.each {|c| self << c} else self.has_children = true @children << child end end # Compares this node and another object (only other {Tree::Node}s will be equal). # This does a structural comparison; # if the contents of the nodes and all the child nodes are equivalent, # then the nodes are as well. # # Only static nodes need to override this. # # @param other [Object] The object to compare with # @return [Boolean] Whether or not this node and the other object # are the same # @see Sass::Tree def ==(other) self.class == other.class && other.children == children end # True if \{#to\_s} will return `nil`; # that is, if the node shouldn't be rendered. # Should only be called in a static tree. # # @return [Boolean] def invisible?; false; end # The output style. See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}. # # @return [Symbol] def style @options[:style] end # Computes the CSS corresponding to this static CSS tree. # # @return [String, nil] The resulting CSS # @see Sass::Tree def to_s Sass::Tree::Visitors::ToCss.visit(self) end # Converts a static CSS tree (e.g. the output of \{Tree::Visitors::Cssize}) # into another static CSS tree, # with the given extensions applied to all relevant {RuleNode}s. # # @todo Link this to the reference documentation on `@extend` # when such a thing exists. # # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}] # The extensions to perform on this tree # @return [Tree::Node] The resulting tree of static CSS nodes. # @raise [Sass::SyntaxError] Only if there's a programmer error # and this is not a static CSS tree def do_extend(extends) node = dup node.children = children.map {|c| c.do_extend(extends)} node rescue Sass::SyntaxError => e e.modify_backtrace(:filename => filename, :line => line) raise e end # Iterates through each node in the tree rooted at this node # in a pre-order walk. # # @yield node # @yieldparam node [Node] a node in the tree def each(&block) yield self children.each {|c| c.each(&block)} end # Converts a node to Sass code that will generate it. # # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}) # @return [String] The Sass code corresponding to the node def to_sass(options = {}) Sass::Tree::Visitors::Convert.visit(self, options, :sass) end # Converts a node to SCSS code that will generate it. # # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}) # @return [String] The Sass code corresponding to the node def to_scss(options = {}) Sass::Tree::Visitors::Convert.visit(self, options, :scss) end # Return a deep clone of this node. # The child nodes are cloned, but options are not. # # @return [Node] def deep_copy node = dup node.children = children.map {|c| c.deep_copy} node end protected # @see Sass::Shared.balance # @raise [Sass::SyntaxError] if the brackets aren't balanced def balance(*args) res = Sass::Shared.balance(*args) return res if res raise Sass::SyntaxError.new("Unbalanced brackets.", :line => line) end end end end ././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/charset_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000065212206724733033513 0ustar jamespagejamespagemodule Sass::Tree # A static node representing an unproccessed Sass `@charset` directive. # # @see Sass::Tree class CharsetNode < Node # The name of the charset. # # @return [String] attr_accessor :name # @param name [String] see \{#name} def initialize(name) @name = name super() end # @see Node#invisible? def invisible? !Sass::Util.ruby1_8? end end end ././@LongLink0000644000000000000000000000016612255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/directive_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000121012206724733033502 0ustar jamespagejamespagemodule Sass::Tree # A static node representing an unproccessed Sass `@`-directive. # Directives known to Sass, like `@for` and `@debug`, # are handled by their own nodes; # only CSS directives like `@media` and `@font-face` become {DirectiveNode}s. # # `@import` and `@charset` are special cases; # they become {ImportNode}s and {CharsetNode}s, respectively. # # @see Sass::Tree class DirectiveNode < Node # The text of the directive, `@` and all. # # @return [String] attr_accessor :value # @param value [String] See \{#value} def initialize(value) @value = value super() end end end ././@LongLink0000644000000000000000000000016112255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/warn_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000057412206724733033516 0ustar jamespagejamespagemodule Sass module Tree # A dynamic node representing a Sass `@warn` statement. # # @see Sass::Tree class WarnNode < Node # The expression to print. # @return [Script::Node] attr_reader :expr # @param expr [Script::Node] The expression to print def initialize(expr) @expr = expr super() end end end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/media_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000126712206724733033516 0ustar jamespagejamespagemodule Sass::Tree # A static node representing a `@media` rule. # `@media` rules behave differently from other directives # in that when they're nested within rules, # they bubble up to top-level. # # @see Sass::Tree class MediaNode < DirectiveNode # The media query (e.g. `print` or `screen`). # # @return [String] attr_accessor :query # @see RuleNode#tabs attr_accessor :tabs # @see RuleNode#group_end attr_accessor :group_end # @param query [String] See \{#query} def initialize(query) @query = query @tabs = 0 super('') end # @see DirectiveNode#value def value "@media #{query}" end end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/mixin_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000151012206724733033505 0ustar jamespagejamespagerequire 'sass/tree/node' module Sass::Tree # A static node representing a mixin include. # When in a static tree, the sole purpose is to wrap exceptions # to add the mixin to the backtrace. # # @see Sass::Tree class MixinNode < Node # The name of the mixin. # @return [String] attr_reader :name # The arguments to the mixin. # @return [Array] attr_reader :args # A hash from keyword argument names to values. # @return [{String => Script::Node}] attr_reader :keywords # @param name [String] The name of the mixin # @param args [Array] See \{#args} # @param keywords [{String => Script::Node}] See \{#keywords} def initialize(name, args, keywords) @name = name @args = args @keywords = keywords super() end end end ././@LongLink0000644000000000000000000000016312255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/import_node.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/tree/0000664000175000017500000000377412206724733033523 0ustar jamespagejamespagemodule Sass module Tree # A static node that wraps the {Sass::Tree} for an `@import`ed file. # It doesn't have a functional purpose other than to add the `@import`ed file # to the backtrace if an error occurs. class ImportNode < RootNode # The name of the imported file as it appears in the Sass document. # # @return [String] attr_reader :imported_filename # @param imported_filename [String] The name of the imported file def initialize(imported_filename) @imported_filename = imported_filename super(nil) end def invisible?; to_s.empty?; end # Returns the imported file. # # @return [Sass::Engine] # @raise [Sass::SyntaxError] If no file could be found to import. def imported_file @imported_file ||= import end # Returns whether or not this import should emit a CSS @import declaration # # @return [Boolean] Whether or not this is a simple CSS @import declaration. def css_import? if @imported_filename =~ /\.css$/ @imported_filename elsif imported_file.is_a?(String) && imported_file =~ /\.css$/ imported_file end end private def import paths = @options[:load_paths] if @options[:importer] f = @options[:importer].find_relative( @imported_filename, @options[:filename], @options.dup) return f if f end paths.each do |p| if f = p.find(@imported_filename, @options.dup) return f end end message = "File to import not found or unreadable: #{@imported_filename}.\n" if paths.size == 1 message << "Load path: #{paths.first}" else message << "Load paths:\n " << paths.join("\n ") end raise SyntaxError.new(message) rescue SyntaxError => e raise SyntaxError.new(e.message, :line => self.line, :filename => @filename) end end end end ././@LongLink0000644000000000000000000000015512255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache_stores/stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache0000775000175000017500000000000012206724733033533 5ustar jamespagejamespage././@LongLink0000644000000000000000000000017212255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache_stores/filesystem.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache0000664000175000017500000000355712206724733033547 0ustar jamespagejamespagemodule Sass module CacheStores # A backend for the Sass cache using the filesystem. class Filesystem < Base # The directory where the cached files will be stored. # # @return [String] attr_accessor :cache_location # @param cache_location [String] see \{#cache\_location} def initialize(cache_location) @cache_location = cache_location end # @see Base#\_retrieve def _retrieve(key, version, sha) return unless File.readable?(path_to(key)) contents = nil File.open(path_to(key), "rb") do |f| if f.readline("\n").strip == version && f.readline("\n").strip == sha return f.read end end File.unlink path_to(key) nil rescue EOFError, TypeError, ArgumentError => e Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}" end # @see Base#\_store def _store(key, version, sha, contents) # return unless File.writable?(File.dirname(@cache_location)) # return if File.exists?(@cache_location) && !File.writable?(@cache_location) compiled_filename = path_to(key) # return if File.exists?(File.dirname(compiled_filename)) && !File.writable?(File.dirname(compiled_filename)) # return if File.exists?(compiled_filename) && !File.writable?(compiled_filename) FileUtils.mkdir_p(File.dirname(compiled_filename)) File.open(compiled_filename, "wb") do |f| f.puts(version) f.puts(sha) f.write(contents) end rescue Errno::EACCES #pass end private # Returns the path to a file for the given key. # # @param key [String] # @return [String] The path to the cache file. def path_to(key) File.join(cache_location, key) end end end end ././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache_stores/null.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache0000664000175000017500000000077412206724733033545 0ustar jamespagejamespagemodule Sass module CacheStores # Doesn't store anything, but records what things it should have stored. # This doesn't currently have any use except for testing and debugging. # # @private class Null < Base def initialize @keys = {} end def _retrieve(key, version, sha) nil end def _store(key, version, sha, contents) @keys[key] = true end def was_set?(key) @keys[key] end end end end ././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache_stores/base.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache0000664000175000017500000000672012206724733033542 0ustar jamespagejamespagemodule Sass module CacheStores # An abstract base class for backends for the Sass cache. # Any key-value store can act as such a backend; # it just needs to implement the # \{#_store} and \{#_retrieve} methods. # # To use a cache store with Sass, # use the {file:SASS_REFERENCE.md#cache_store-option `:cache_store` option}. # # @abstract class Base # Store cached contents for later retrieval # Must be implemented by all CacheStore subclasses # # Note: cache contents contain binary data. # # @param key [String] The key to store the contents under # @param version [String] The current sass version. # Cached contents must not be retrieved across different versions of sass. # @param sha [String] The sha of the sass source. # Cached contents must not be retrieved if the sha has changed. # @param contents [String] The contents to store. def _store(key, version, sha, contents) raise "#{self.class} must implement #_store." end # Retrieved cached contents. # Must be implemented by all subclasses. # # Note: if the key exists but the sha or version have changed, # then the key may be deleted by the cache store, if it wants to do so. # # @param key [String] The key to retrieve # @param version [String] The current sass version. # Cached contents must not be retrieved across different versions of sass. # @param sha [String] The sha of the sass source. # Cached contents must not be retrieved if the sha has changed. # @return [String] The contents that were previously stored. # @return [NilClass] when the cache key is not found or the version or sha have changed. def _retrieve(key, version, sha) raise "#{self.class} must implement #_retrieve." end # Store a {Sass::Tree::RootNode}. # # @param key [String] The key to store it under. # @param sha [String] The checksum for the contents that are being stored. # @param obj [Object] The object to cache. def store(key, sha, root) _store(key, Sass::VERSION, sha, Marshal.dump(root)) end # Retrieve a {Sass::Tree::RootNode}. # # @param key [String] The key the root element was stored under. # @param sha [String] The checksum of the root element's content. # @return [Object] The cached object. def retrieve(key, sha) contents = _retrieve(key, Sass::VERSION, sha) Marshal.load(contents) if contents rescue EOFError, TypeError, ArgumentError => e Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}" end # Return the key for the sass file. # # The `(sass_dirname, sass_basename)` pair # should uniquely identify the Sass document, # but otherwise there are no restrictions on their content. # # @param sass_dirname [String] # The fully-expanded location of the Sass file. # This corresponds to the directory name on a filesystem. # @param sass_basename [String] The name of the Sass file that is being referenced. # This corresponds to the basename on a filesystem. def key(sass_dirname, sass_basename) dir = Digest::SHA1.hexdigest(sass_dirname) filename = "#{sass_basename}c" "#{dir}/#{filename}" end end end end ././@LongLink0000644000000000000000000000016612255653646011663 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache_stores/memory.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache0000664000175000017500000000225112206724733033535 0ustar jamespagejamespagemodule Sass module CacheStores # A backend for the Sass cache using in-process memory. class Memory < Base # Since the {Memory} store is stored in the Sass tree's options hash, # when the options get serialized as part of serializing the tree, # you get crazy exponential growth in the size of the cached objects # unless you don't dump the cache. # # @private def _dump(depth) "" end # If we deserialize this class, just make a new empty one. # # @private def self._load(repr) Memory.new end # Create a new, empty cache store. def initialize @contents = {} end # @see Base#retrieve def retrieve(key, sha) if @contents.has_key?(key) return unless @contents[key][:sha] == sha obj = @contents[key][:obj] obj.respond_to?(:deep_copy) ? obj.deep_copy : obj.dup end end # @see Base#store def store(key, sha, obj) @contents[key] = {:sha => sha, :obj => obj} end # Destructively clear the cache. def reset! @contents = {} end end end end ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache_stores/chain.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/cache0000664000175000017500000000164512206724733033543 0ustar jamespagejamespagemodule Sass module CacheStores # A meta-cache that chains multiple caches together. # Specifically: # # * All `#store`s are passed to all caches. # * `#retrieve`s are passed to each cache until one has a hit. # * When one cache has a hit, the value is `#store`d in all earlier caches. class Chain < Base # Create a new cache chaining the given caches. # # @param caches [Array] The caches to chain. def initialize(*caches) @caches = caches end # @see Base#store def store(key, sha, obj) @caches.each {|c| c.store(key, sha, obj)} end # @see Base#retrieve def retrieve(key, sha) @caches.each_with_index do |c, i| next unless obj = c.retrieve(key, sha) @caches[0...i].each {|c| c.store(key, sha, obj)} return obj end nil end end end end ././@LongLink0000644000000000000000000000014712255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/exec.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/exec.0000664000175000017500000005442312206724733033504 0ustar jamespagejamespagerequire 'optparse' require 'fileutils' module Sass # This module handles the various Sass executables (`sass` and `sass-convert`). module Exec # An abstract class that encapsulates the executable code for all three executables. class Generic # @param args [Array] The command-line arguments def initialize(args) @args = args @options = {} end # Parses the command-line arguments and runs the executable. # Calls `Kernel#exit` at the end, so it never returns. # # @see #parse def parse! begin parse rescue Exception => e raise e if @options[:trace] || e.is_a?(SystemExit) $stderr.print "#{e.class}: " unless e.class == RuntimeError $stderr.puts "#{e.message}" $stderr.puts " Use --trace for backtrace." exit 1 end exit 0 end # Parses the command-line arguments and runs the executable. # This does not handle exceptions or exit the program. # # @see #parse! def parse @opts = OptionParser.new(&method(:set_opts)) @opts.parse!(@args) process_result @options end # @return [String] A description of the executable def to_s @opts.to_s end protected # Finds the line of the source template # on which an exception was raised. # # @param exception [Exception] The exception # @return [String] The line number def get_line(exception) # SyntaxErrors have weird line reporting # when there's trailing whitespace return (exception.message.scan(/:(\d+)/).first || ["??"]).first if exception.is_a?(::SyntaxError) (exception.backtrace[0].scan(/:(\d+)/).first || ["??"]).first end # Tells optparse how to parse the arguments # available for all executables. # # This is meant to be overridden by subclasses # so they can add their own options. # # @param opts [OptionParser] def set_opts(opts) opts.on('-s', '--stdin', :NONE, 'Read input from standard input instead of an input file') do @options[:input] = $stdin end opts.on('--trace', :NONE, 'Show a full traceback on error') do @options[:trace] = true end opts.on('--unix-newlines', 'Use Unix-style newlines in written files.') do @options[:unix_newlines] = true if ::Sass::Util.windows? end opts.on_tail("-?", "-h", "--help", "Show this message") do puts opts exit end opts.on_tail("-v", "--version", "Print version") do puts("Sass #{::Sass.version[:string]}") exit end end # Processes the options set by the command-line arguments. # In particular, sets `@options[:input]` and `@options[:output]` # to appropriate IO streams. # # This is meant to be overridden by subclasses # so they can run their respective programs. def process_result input, output = @options[:input], @options[:output] args = @args.dup input ||= begin filename = args.shift @options[:filename] = filename open_file(filename) || $stdin end output ||= open_file(args.shift, 'w') || $stdout @options[:input], @options[:output] = input, output end COLORS = { :red => 31, :green => 32, :yellow => 33 } # Prints a status message about performing the given action, # colored using the given color (via terminal escapes) if possible. # # @param name [#to_s] A short name for the action being performed. # Shouldn't be longer than 11 characters. # @param color [Symbol] The name of the color to use for this action. # Can be `:red`, `:green`, or `:yellow`. def puts_action(name, color, arg) return if @options[:for_engine][:quiet] printf color(color, "%11s %s\n"), name, arg end # Same as \{Kernel.puts}, but doesn't print anything if the `--quiet` option is set. # # @param args [Array] Passed on to \{Kernel.puts} def puts(*args) return if @options[:for_engine][:quiet] Kernel.puts(*args) end # Wraps the given string in terminal escapes # causing it to have the given color. # If terminal esapes aren't supported on this platform, # just returns the string instead. # # @param color [Symbol] The name of the color to use. # Can be `:red`, `:green`, or `:yellow`. # @param str [String] The string to wrap in the given color. # @return [String] The wrapped string. def color(color, str) raise "[BUG] Unrecognized color #{color}" unless COLORS[color] # Almost any real Unix terminal will support color, # so we just filter for Windows terms (which don't set TERM) # and not-real terminals, which aren't ttys. return str if ENV["TERM"].nil? || ENV["TERM"].empty? || !STDOUT.tty? return "\e[#{COLORS[color]}m#{str}\e[0m" end private def open_file(filename, flag = 'r') return if filename.nil? flag = 'wb' if @options[:unix_newlines] && flag == 'w' File.open(filename, flag) end def handle_load_error(err) dep = err.message[/^no such file to load -- (.*)/, 1] raise err if @options[:trace] || dep.nil? || dep.empty? $stderr.puts <] The command-line arguments def initialize(args) super @options[:for_engine] = { :load_paths => ['.'] + (ENV['SASSPATH'] || '').split(File::PATH_SEPARATOR) } @default_syntax = :sass end protected # Tells optparse how to parse the arguments. # # @param opts [OptionParser] def set_opts(opts) super opts.banner = < e raise e if @options[:trace] raise e.sass_backtrace_str("standard input") end end private def load_compass begin require 'compass' rescue LoadError require 'rubygems' begin require 'compass' rescue LoadError puts "ERROR: Cannot load compass." exit 1 end end Compass.add_project_configuration Compass.configuration.project_path ||= Dir.pwd @options[:for_engine][:load_paths] += Compass.configuration.sass_load_paths end def interactive require 'sass/repl' ::Sass::Repl.new(@options).run end def watch_or_update require 'sass/plugin' ::Sass::Plugin.options.merge! @options[:for_engine] ::Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines] raise <>> Sass is watching for changes. Press Ctrl-C to stop." ::Sass::Plugin.on_template_modified {|template| puts ">>> Change detected to: #{template}"} ::Sass::Plugin.on_template_created {|template| puts ">>> New template detected: #{template}"} ::Sass::Plugin.on_template_deleted {|template| puts ">>> Deleted template detected: #{template}"} ::Sass::Plugin.watch(files) end def colon_path?(path) !split_colon_path(path)[1].nil? end def split_colon_path(path) one, two = path.split(':', 2) if one && two && ::Sass::Util.windows? && one =~ /\A[A-Za-z]\Z/ && two =~ /\A[\/\\]/ # If we're on Windows and we were passed a drive letter path, # don't split on that colon. one2, two = two.split(':', 2) one = one + ':' + one2 end return one, two end # Whether path is likely to be meant as the destination # in a source:dest pair. def probably_dest_dir?(path) return false unless path return false if colon_path?(path) return Dir.glob(File.join(path, "*.s[ca]ss")).empty? end end class Scss < Sass # @param args [Array] The command-line arguments def initialize(args) super @default_syntax = :scss end end # The `sass-convert` executable. class SassConvert < Generic # @param args [Array] The command-line arguments def initialize(args) super require 'sass' @options[:for_tree] = {} @options[:for_engine] = {:cache => false, :read_cache => true} end # Tells optparse how to parse the arguments. # # @param opts [OptionParser] def set_opts(opts) opts.banner = < e raise e if @options[:trace] file = " of #{e.sass_filename}" if e.sass_filename raise "Error on line #{e.sass_line}#{file}: #{e.message}\n Use --trace for backtrace" rescue LoadError => err handle_load_error(err) end @@less_note_printed = false def try_less_note return if @@less_note_printed @@less_note_printed = true warn < Object}] def options @options || parent_options || {} end # Push a new stack frame onto the mixin/include stack. # # @param frame_info [{Symbol => Object}] # Frame information has the following keys: # # `:filename` # : The name of the file in which the lexical scope changed. # # `:mixin` # : The name of the mixin in which the lexical scope changed, # or `nil` if it wasn't within in a mixin. # # `:line` # : The line of the file on which the lexical scope changed. Never nil. def push_frame(frame_info) top_of_stack = stack.last if top_of_stack && top_of_stack.delete(:prepared) top_of_stack.merge!(frame_info) else stack.push(top_of_stack = frame_info) end mixins_in_use << top_of_stack[:mixin] if top_of_stack[:mixin] && !top_of_stack[:prepared] end # Like \{#push\_frame}, but next time a stack frame is pushed, # it will be merged with this frame. # # @param frame_info [{Symbol => Object}] Same as for \{#push\_frame}. def prepare_frame(frame_info) push_frame(frame_info.merge(:prepared => true)) end # Pop a stack frame from the mixin/include stack. def pop_frame stack.pop if stack.last && stack.last[:prepared] popped = stack.pop mixins_in_use.delete(popped[:mixin]) if popped && popped[:mixin] end # A list of stack frames in the mixin/include stack. # The last element in the list is the most deeply-nested frame. # # @return [Array<{Symbol => Object}>] The stack frames, # of the form passed to \{#push\_frame}. def stack @stack ||= @parent.stack end # A set of names of mixins currently present in the stack. # # @return [Set] The mixin names. def mixins_in_use @mixins_in_use ||= @parent.mixins_in_use end private def parent_options @parent_options ||= @parent && @parent.options end class << self private UNDERSCORE, DASH = '_', '-' # Note: when updating this, # update sass/yard/inherited_hash.rb as well. def inherited_hash(name) class_eval < "2.1.0.9616393", # :rev => "9616393b8924ef36639c7e82aa88a51a24d16949", # :number => "2.1.0", # :major => 2, :minor => 1, :teeny => 0 # } # # If a prerelease version of Sass is being used, # the `:string` and `:number` fields will reflect the full version # (e.g. `"2.2.beta.1"`), and the `:teeny` field will be `-1`. # A `:prerelease` key will contain the name of the prerelease (e.g. `"beta"`), # and a `:prerelease_number` key will contain the rerelease number. # For example: # # { # :string => "3.0.beta.1", # :number => "3.0.beta.1", # :major => 3, :minor => 0, :teeny => -1, # :prerelease => "beta", # :prerelease_number => 1 # } # # @return [{Symbol => String/Fixnum}] The version hash def version return @@version if defined?(@@version) numbers = File.read(scope('VERSION')).strip.split('.'). map {|n| n =~ /^[0-9]+$/ ? n.to_i : n} name = File.read(scope('VERSION_NAME')).strip @@version = { :major => numbers[0], :minor => numbers[1], :teeny => numbers[2], :name => name } if numbers[3].is_a?(String) @@version[:teeny] = -1 @@version[:prerelease] = numbers[3] @@version[:prerelease_number] = numbers[4] end @@version[:number] = numbers.join('.') @@version[:string] = @@version[:number].dup if rev = revision_number @@version[:rev] = rev unless rev[0] == ?( @@version[:string] << "." << rev[0...7] end end @@version[:string] << " (#{name})" @@version end private def revision_number if File.exists?(scope('REVISION')) rev = File.read(scope('REVISION')).strip return rev unless rev =~ /^([a-f0-9]+|\(.*\))$/ || rev == '(unknown)' end return unless File.exists?(scope('.git/HEAD')) rev = File.read(scope('.git/HEAD')).strip return rev unless rev =~ /^ref: (.*)$/ ref_name = $1 ref_file = scope(".git/#{ref_name}") info_file = scope(".git/info/refs") return File.read(ref_file).strip if File.exists?(ref_file) return unless File.exists?(info_file) File.open(info_file) do |f| f.each do |l| sha, ref = l.strip.split("\t", 2) next unless ref == ref_name return sha end end return nil end end extend Sass::Version # A string representing the version of Sass. # A more fine-grained representation is available from Sass.version. # @api public VERSION = version[:string] unless defined?(Sass::VERSION) end ././@LongLink0000644000000000000000000000015312255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selector.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/selec0000664000175000017500000002625712206724733033601 0ustar jamespagejamespagerequire 'sass/selector/simple' require 'sass/selector/abstract_sequence' require 'sass/selector/comma_sequence' require 'sass/selector/sequence' require 'sass/selector/simple_sequence' module Sass # A namespace for nodes in the parse tree for selectors. # # {CommaSequence} is the toplevel seelctor, # representing a comma-separated sequence of {Sequence}s, # such as `foo bar, baz bang`. # {Sequence} is the next level, # representing {SimpleSequence}s separated by combinators (e.g. descendant or child), # such as `foo bar` or `foo > bar baz`. # {SimpleSequence} is a sequence of selectors that all apply to a single element, # such as `foo.bar[attr=val]`. # Finally, {Simple} is the superclass of the simplest selectors, # such as `.foo` or `#bar`. module Selector # A parent-referencing selector (`&` in Sass). # The function of this is to be replaced by the parent selector # in the nested hierarchy. class Parent < Simple # @see Selector#to_a def to_a ["&"] end # Always raises an exception. # # @raise [Sass::SyntaxError] Parent selectors should be resolved before unification # @see Selector#unify def unify(sels) raise Sass::SyntaxError.new("[BUG] Cannot unify parent selectors.") end end # A class selector (e.g. `.foo`). class Class < Simple # The class name. # # @return [Array] attr_reader :name # @param name [Array] The class name def initialize(name) @name = name end # @see Selector#to_a def to_a [".", *@name] end end # An id selector (e.g. `#foo`). class Id < Simple # The id name. # # @return [Array] attr_reader :name # @param name [Array] The id name def initialize(name) @name = name end # @see Selector#to_a def to_a ["#", *@name] end # Returns `nil` if `sels` contains an {Id} selector # with a different name than this one. # # @see Selector#unify def unify(sels) return if sels.any? {|sel2| sel2.is_a?(Id) && self.name != sel2.name} super end end # A universal selector (`*` in CSS). class Universal < Simple # The selector namespace. # `nil` means the default namespace, # `[""]` means no namespace, # `["*"]` means any namespace. # # @return [Array, nil] attr_reader :namespace # @param namespace [Array, nil] See \{#namespace} def initialize(namespace) @namespace = namespace end # @see Selector#to_a def to_a @namespace ? @namespace + ["|*"] : ["*"] end # Unification of a universal selector is somewhat complicated, # especially when a namespace is specified. # If there is no namespace specified # or any namespace is specified (namespace `"*"`), # then `sel` is returned without change # (unless it's empty, in which case `"*"` is required). # # If a namespace is specified # but `sel` does not specify a namespace, # then the given namespace is applied to `sel`, # either by adding this {Universal} selector # or applying this namespace to an existing {Element} selector. # # If both this selector *and* `sel` specify namespaces, # those namespaces are unified via {Simple#unify_namespaces} # and the unified namespace is used, if possible. # # @todo There are lots of cases that this documentation specifies; # make sure we thoroughly test **all of them**. # @todo Keep track of whether a default namespace has been declared # and handle namespace-unspecified selectors accordingly. # @todo If any branch of a CommaSequence ends up being just `"*"`, # then all other branches should be eliminated # # @see Selector#unify def unify(sels) name = case sels.first when Universal; :universal when Element; sels.first.name else return [self] + sels unless namespace.nil? || namespace == ['*'] return sels unless sels.empty? return [self] end ns, accept = unify_namespaces(namespace, sels.first.namespace) return unless accept [name == :universal ? Universal.new(ns) : Element.new(name, ns)] + sels[1..-1] end end # An element selector (e.g. `h1`). class Element < Simple # The element name. # # @return [Array] attr_reader :name # The selector namespace. # `nil` means the default namespace, # `[""]` means no namespace, # `["*"]` means any namespace. # # @return [Array, nil] attr_reader :namespace # @param name [Array] The element name # @param namespace [Array, nil] See \{#namespace} def initialize(name, namespace) @name = name @namespace = namespace end # @see Selector#to_a def to_a @namespace ? @namespace + ["|"] + @name : @name end # Unification of an element selector is somewhat complicated, # especially when a namespace is specified. # First, if `sel` contains another {Element} with a different \{#name}, # then the selectors can't be unified and `nil` is returned. # # Otherwise, if `sel` doesn't specify a namespace, # or it specifies any namespace (via `"*"`), # then it's returned with this element selector # (e.g. `.foo` becomes `a.foo` or `svg|a.foo`). # Similarly, if this selector doesn't specify a namespace, # the namespace from `sel` is used. # # If both this selector *and* `sel` specify namespaces, # those namespaces are unified via {Simple#unify_namespaces} # and the unified namespace is used, if possible. # # @todo There are lots of cases that this documentation specifies; # make sure we thoroughly test **all of them**. # @todo Keep track of whether a default namespace has been declared # and handle namespace-unspecified selectors accordingly. # # @see Selector#unify def unify(sels) case sels.first when Universal; when Element; return unless name == sels.first.name else return [self] + sels end ns, accept = unify_namespaces(namespace, sels.first.namespace) return unless accept [Element.new(name, ns)] + sels[1..-1] end end # Selector interpolation (`#{}` in Sass). class Interpolation < Simple # The script to run. # # @return [Sass::Script::Node] attr_reader :script # @param script [Sass::Script::Node] The script to run def initialize(script) @script = script end # @see Selector#to_a def to_a [@script] end # Always raises an exception. # # @raise [Sass::SyntaxError] Interpolation selectors should be resolved before unification # @see Selector#unify def unify(sels) raise Sass::SyntaxError.new("[BUG] Cannot unify interpolation selectors.") end end # An attribute selector (e.g. `[href^="http://"]`). class Attribute < Simple # The attribute name. # # @return [Array] attr_reader :name # The attribute namespace. # `nil` means the default namespace, # `[""]` means no namespace, # `["*"]` means any namespace. # # @return [Array, nil] attr_reader :namespace # The matching operator, e.g. `"="` or `"^="`. # # @return [String] attr_reader :operator # The right-hand side of the operator. # # @return [Array] attr_reader :value # @param name [Array] The attribute name # @param namespace [Array, nil] See \{#namespace} # @param operator [String] The matching operator, e.g. `"="` or `"^="` # @param value [Array] See \{#value} def initialize(name, namespace, operator, value) @name = name @namespace = namespace @operator = operator @value = value end # @see Selector#to_a def to_a res = ["["] res.concat(@namespace) << "|" if @namespace res.concat @name (res << @operator).concat @value if @value res << "]" end end # A pseudoclass (e.g. `:visited`) or pseudoelement (e.g. `::first-line`) selector. # It can have arguments (e.g. `:nth-child(2n+1)`). class Pseudo < Simple # The type of the selector. # `:class` if this is a pseudoclass selector, # `:element` if it's a pseudoelement. # # @return [Symbol] attr_reader :type # The name of the selector. # # @return [Array] attr_reader :name # The argument to the selector, # or `nil` if no argument was given. # # This may include SassScript nodes that will be run during resolution. # Note that this should not include SassScript nodes # after resolution has taken place. # # @return [Array, nil] attr_reader :arg # @param type [Symbol] See \{#type} # @param name [Array] The name of the selector # @param arg [nil, Array] The argument to the selector, # or nil if no argument was given def initialize(type, name, arg) @type = type @name = name @arg = arg end # @see Selector#to_a def to_a res = [@type == :class ? ":" : "::"] + @name (res << "(").concat(Sass::Util.strip_string_array(@arg)) << ")" if @arg res end # Returns `nil` if this is a pseudoclass selector # and `sels` contains a pseudoclass selector different than this one. # # @see Selector#unify def unify(sels) return if type == :element && sels.any? do |sel| sel.is_a?(Pseudo) && sel.type == :element && (sel.name != self.name || sel.arg != self.arg) end super end end # A pseudoclass selector whose argument is itself a selector # (e.g. `:not(.foo)` or `:-moz-all(.foo, .bar)`). class SelectorPseudoClass < Simple # The name of the pseudoclass. # # @return [String] attr_reader :name # The selector argument. # # @return [Selector::Sequence] attr_reader :selector # @param [String] The name of the pseudoclass # @param [Selector::Sequence] The selector argument def initialize(name, selector) @name = name @selector = selector end # @see Selector#to_a def to_a [":", @name, "("] + @selector.to_a + [")"] end end end end stapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/0000775000175000017500000000000012206724733033522 5ustar jamespagejamespage././@LongLink0000644000000000000000000000016312255653646011660 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/sass_parser.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/0000664000175000017500000000052012206724733033521 0ustar jamespagejamespagemodule Sass module SCSS # A subclass of {Parser} that parses code in Sass documents # using some SCSS constructs. # This is necessary because SassScript in Sass supports `!`-style variables, # whereas in SCSS it doesn't. class SassParser < Parser @sass_script_parser = Sass::Script::Parser end end end ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/static_parser.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/0000664000175000017500000000243012206724733033523 0ustar jamespagejamespagemodule Sass module SCSS # A parser for a static SCSS tree. # Parses with SCSS extensions, like nested rules and parent selectors, # but without dynamic SassScript. # This is useful for e.g. \{#parse\_selector parsing selectors} # after resolving the interpolation. class StaticParser < Parser # Parses the text as a selector. # # @param filename [String, nil] The file in which the selector appears, # or nil if there is no such file. # Used for error reporting. # @return [Selector::CommaSequence] The parsed selector # @raise [Sass::SyntaxError] if there's a syntax error in the selector def parse_selector(filename) init_scanner! seq = expr!(:selector_comma_sequence) expected("selector") unless @scanner.eos? seq.line = @line seq.filename = filename seq end private def variable; nil; end def script_value; nil; end def interpolation; nil; end def interp_string; s = tok(STRING) and [s]; end def interp_ident(ident = IDENT); s = tok(ident) and [s]; end def use_css_import?; true; end def special_directive(name) return unless %w[media import charset].include?(name) super end end end end ././@LongLink0000644000000000000000000000015612255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/parser.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/0000664000175000017500000006146012206724733033533 0ustar jamespagejamespagerequire 'strscan' require 'set' module Sass module SCSS # The parser for SCSS. # It parses a string of code into a tree of {Sass::Tree::Node}s. class Parser # @param str [String, StringScanner] The source document to parse. # Note that `Parser` *won't* raise a nice error message if this isn't properly parsed; # for that, you should use the higher-level {Sass::Engine} or {Sass::CSS}. # @param line [Fixnum] The line on which the source string appeared, # if it's part of another document def initialize(str, line = 1) @template = str @line = line @strs = [] end # Parses an SCSS document. # # @return [Sass::Tree::RootNode] The root node of the document tree # @raise [Sass::SyntaxError] if there's a syntax error in the document def parse init_scanner! root = stylesheet expected("selector or at-rule") unless @scanner.eos? root end # Parses an identifier with interpolation. # Note that this won't assert that the identifier takes up the entire input string; # it's meant to be used with `StringScanner`s as part of other parsers. # # @return [Array, nil] # The interpolated identifier, or nil if none could be parsed def parse_interp_ident init_scanner! interp_ident end private include Sass::SCSS::RX def init_scanner! @scanner = if @template.is_a?(StringScanner) @template else StringScanner.new(@template.gsub("\r", "")) end end def stylesheet node = node(Sass::Tree::RootNode.new(@scanner.string)) block_contents(node, :stylesheet) {s(node)} end def s(node) while tok(S) || tok(CDC) || tok(CDO) || (c = tok(SINGLE_LINE_COMMENT)) || (c = tok(COMMENT)) next unless c process_comment c, node c = nil end true end def ss nil while tok(S) || tok(SINGLE_LINE_COMMENT) || tok(COMMENT) true end def ss_comments(node) while tok(S) || (c = tok(SINGLE_LINE_COMMENT)) || (c = tok(COMMENT)) next unless c process_comment c, node c = nil end true end def whitespace return unless tok(S) || tok(SINGLE_LINE_COMMENT) || tok(COMMENT) ss end def process_comment(text, node) single_line = text =~ /^\/\// pre_str = single_line ? "" : @scanner. string[0...@scanner.pos]. reverse[/.*?\*\/(.*?)($|\Z)/, 1]. reverse.gsub(/[^\s]/, ' ') text = text.sub(/^\s*\/\//, '/*').gsub(/^\s*\/\//, ' *') + ' */' if single_line comment = Sass::Tree::CommentNode.new(pre_str + text, single_line) comment.line = @line - text.count("\n") node << comment end DIRECTIVES = Set[:mixin, :include, :function, :return, :debug, :warn, :for, :each, :while, :if, :else, :extend, :import, :media, :charset] def directive return unless tok(/@/) name = tok!(IDENT) ss if dir = special_directive(name) return dir end # Most at-rules take expressions (e.g. @import), # but some (e.g. @page) take selector-like arguments val = str {break unless expr} val ||= CssParser.new(@scanner, @line).parse_selector_string node = node(Sass::Tree::DirectiveNode.new("@#{name} #{val}".strip)) if tok(/\{/) node.has_children = true block_contents(node, :directive) tok!(/\}/) end node end def special_directive(name) sym = name.gsub('-', '_').to_sym DIRECTIVES.include?(sym) && send("#{sym}_directive") end def mixin_directive name = tok! IDENT args = sass_script(:parse_mixin_definition_arglist) ss block(node(Sass::Tree::MixinDefNode.new(name, args)), :directive) end def include_directive name = tok! IDENT args, keywords = sass_script(:parse_mixin_include_arglist) ss node(Sass::Tree::MixinNode.new(name, args, keywords)) end def function_directive name = tok! IDENT args = sass_script(:parse_function_definition_arglist) ss block(node(Sass::Tree::FunctionNode.new(name, args)), :function) end def return_directive node(Sass::Tree::ReturnNode.new(sass_script(:parse))) end def debug_directive node(Sass::Tree::DebugNode.new(sass_script(:parse))) end def warn_directive node(Sass::Tree::WarnNode.new(sass_script(:parse))) end def for_directive tok!(/\$/) var = tok! IDENT ss tok!(/from/) from = sass_script(:parse_until, Set["to", "through"]) ss @expected = '"to" or "through"' exclusive = (tok(/to/) || tok!(/through/)) == 'to' to = sass_script(:parse) ss block(node(Sass::Tree::ForNode.new(var, from, to, exclusive)), :directive) end def each_directive tok!(/\$/) var = tok! IDENT ss tok!(/in/) list = sass_script(:parse) ss block(node(Sass::Tree::EachNode.new(var, list)), :directive) end def while_directive expr = sass_script(:parse) ss block(node(Sass::Tree::WhileNode.new(expr)), :directive) end def if_directive expr = sass_script(:parse) ss node = block(node(Sass::Tree::IfNode.new(expr)), :directive) pos = @scanner.pos line = @line ss else_block(node) || begin # Backtrack in case there are any comments we want to parse @scanner.pos = pos @line = line node end end def else_block(node) return unless tok(/@else/) ss else_node = block( Sass::Tree::IfNode.new((sass_script(:parse) if tok(/if/))), :directive) node.add_else(else_node) pos = @scanner.pos line = @line ss else_block(node) || begin # Backtrack in case there are any comments we want to parse @scanner.pos = pos @line = line node end end def else_directive err("Invalid CSS: @else must come after @if") end def extend_directive node(Sass::Tree::ExtendNode.new(expr!(:selector))) end def import_directive values = [] loop do values << expr!(:import_arg) break if use_css_import? || !tok(/,\s*/) end return values end def import_arg return unless arg = tok(STRING) || (uri = tok!(URI)) path = @scanner[1] || @scanner[2] || @scanner[3] ss media = str {media_query_list}.strip if uri || path =~ /^http:\/\// || !media.strip.empty? || use_css_import? return node(Sass::Tree::DirectiveNode.new("@import #{arg} #{media}".strip)) end node(Sass::Tree::ImportNode.new(path.strip)) end def use_css_import?; false; end def media_directive val = str {media_query_list}.strip block(node(Sass::Tree::MediaNode.new(val)), :directive) end # http://www.w3.org/TR/css3-mediaqueries/#syntax def media_query_list return unless media_query ss while tok(/,/) ss; expr!(:media_query); ss end true end def media_query if tok(/only|not/i) ss @expected = "media type (e.g. print, screen)" tok!(IDENT) ss elsif !tok(IDENT) && !media_expr return end ss while tok(/and/i) ss; expr!(:media_expr); ss end true end def media_expr return unless tok(/\(/) ss @expected = "media feature (e.g. min-device-width, color)" tok!(IDENT) ss if tok(/:/) ss; expr!(:expr) end tok!(/\)/) ss true end def charset_directive tok! STRING name = @scanner[1] || @scanner[2] ss node(Sass::Tree::CharsetNode.new(name)) end def variable return unless tok(/\$/) name = tok!(IDENT) ss; tok!(/:/); ss expr = sass_script(:parse) guarded = tok(DEFAULT) node(Sass::Tree::VariableNode.new(name, expr, guarded)) end def operator # Many of these operators (all except / and ,) # are disallowed by the CSS spec, # but they're included here for compatibility # with some proprietary MS properties str {ss if tok(/[\/,:.=]/)} end def unary_operator tok(/[+-]/) end def ruleset return unless rules = selector_sequence block(node(Sass::Tree::RuleNode.new(rules.flatten.compact)), :ruleset) end def block(node, context) node.has_children = true tok!(/\{/) block_contents(node, context) tok!(/\}/) node end # A block may contain declarations and/or rulesets def block_contents(node, context) block_given? ? yield : ss_comments(node) node << (child = block_child(context)) while tok(/;/) || has_children?(child) block_given? ? yield : ss_comments(node) node << (child = block_child(context)) end node end def block_child(context) return variable || directive if context == :function return variable || directive || ruleset if context == :stylesheet variable || directive || declaration_or_ruleset end def has_children?(child_or_array) return false unless child_or_array return child_or_array.last.has_children if child_or_array.is_a?(Array) return child_or_array.has_children end # This is a nasty hack, and the only place in the parser # that requires backtracking. # The reason is that we can't figure out if certain strings # are declarations or rulesets with fixed finite lookahead. # For example, "foo:bar baz baz baz..." could be either a property # or a selector. # # To handle this, we simply check if it works as a property # (which is the most common case) # and, if it doesn't, try it as a ruleset. # # We could eke some more efficiency out of this # by handling some easy cases (first token isn't an identifier, # no colon after the identifier, whitespace after the colon), # but I'm not sure the gains would be worth the added complexity. def declaration_or_ruleset old_use_property_exception, @use_property_exception = @use_property_exception, false decl_err = catch_error do decl = declaration unless decl && decl.has_children # We want an exception if it's not there, # but we don't want to consume if it is tok!(/[;}]/) unless tok?(/[;}]/) end return decl end ruleset_err = catch_error {return ruleset} rethrow(@use_property_exception ? decl_err : ruleset_err) ensure @use_property_exception = old_use_property_exception end def selector_sequence if sel = tok(STATIC_SELECTOR) return [sel] end rules = [] return unless v = selector rules.concat v ws = '' while tok(/,/) ws << str {ss} if v = selector rules << ',' << ws rules.concat v ws = '' end end rules end def selector return unless sel = _selector sel.to_a end def selector_comma_sequence return unless sel = _selector selectors = [sel] ws = '' while tok(/,/) ws << str{ss} if sel = _selector selectors << sel selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members) if ws.include?("\n") ws = '' end end Selector::CommaSequence.new(selectors) end def _selector # The combinator here allows the "> E" hack return unless val = combinator || simple_selector_sequence nl = str{ss}.include?("\n") res = [] res << val res << "\n" if nl while val = combinator || simple_selector_sequence res << val res << "\n" if str{ss}.include?("\n") end Selector::Sequence.new(res.compact) end def combinator tok(PLUS) || tok(GREATER) || tok(TILDE) end def simple_selector_sequence # This allows for stuff like http://www.w3.org/TR/css3-animations/#keyframes- return expr unless e = element_name || id_selector || class_selector || attrib || negation || pseudo || parent_selector || interpolation_selector res = [e] # The tok(/\*/) allows the "E*" hack while v = element_name || id_selector || class_selector || attrib || negation || pseudo || interpolation_selector || (tok(/\*/) && Selector::Universal.new(nil)) res << v end if tok?(/&/) begin expected('"{"') rescue Sass::SyntaxError => e e.message << "\n\n" << < e throw(:_sass_parser_error, true) if @throw_error raise e end def merge(arr) arr && Sass::Util.merge_adjacent_strings([arr].flatten) end EXPR_NAMES = { :media_query => "media query (e.g. print, screen, print and screen)", :media_expr => "media expression (e.g. (min-device-width: 800px)))", :pseudo_expr => "expression (e.g. fr, 2n+1)", :interp_ident => "identifier", :interp_name => "identifier", :expr => "expression (e.g. 1px, bold)", :_selector => "selector", :selector_comma_sequence => "selector", :simple_selector_sequence => "selector", :import_arg => "file to import (string or url())", } TOK_NAMES = Sass::Util.to_hash( Sass::SCSS::RX.constants.map {|c| [Sass::SCSS::RX.const_get(c), c.downcase]}). merge(IDENT => "identifier", /[;}]/ => '";"') def tok?(rx) @scanner.match?(rx) end def expr!(name) (e = send(name)) && (return e) expected(EXPR_NAMES[name] || name.to_s) end def tok!(rx) (t = tok(rx)) && (return t) name = TOK_NAMES[rx] unless name # Display basic regexps as plain old strings string = rx.source.gsub(/\\(.)/, '\1') name = rx.source == Regexp.escape(string) ? string.inspect : rx.inspect end expected(name) end def expected(name) throw(:_sass_parser_error, true) if @throw_error self.class.expected(@scanner, @expected || name, @line) end def err(msg) throw(:_sass_parser_error, true) if @throw_error raise Sass::SyntaxError.new(msg, :line => @line) end def catch_error(&block) old_throw_error, @throw_error = @throw_error, true pos = @scanner.pos line = @line expected = @expected if catch(:_sass_parser_error, &block) @scanner.pos = pos @line = line @expected = expected {:pos => pos, :line => line, :expected => @expected, :block => block} end ensure @throw_error = old_throw_error end def rethrow(err) if @throw_err throw :_sass_parser_error, err else @scanner = StringScanner.new(@scanner.string) @scanner.pos = err[:pos] @line = err[:line] @expected = err[:expected] err[:block].call end end # @private def self.expected(scanner, expected, line) pos = scanner.pos after = scanner.string[0...pos] # Get rid of whitespace between pos and the last token, # but only if there's a newline in there after.gsub!(/\s*\n\s*$/, '') # Also get rid of stuff before the last newline after.gsub!(/.*\n/, '') after = "..." + after[-15..-1] if after.size > 18 was = scanner.rest.dup # Get rid of whitespace between pos and the next token, # but only if there's a newline in there was.gsub!(/^\s*\n\s*/, '') # Also get rid of stuff after the next newline was.gsub!(/\n.*/, '') was = was[0...15] + "..." if was.size > 18 raise Sass::SyntaxError.new( "Invalid CSS after \"#{after}\": expected #{expected}, was \"#{was}\"", :line => line) end # Avoid allocating lots of new strings for `#tok`. # This is important because `#tok` is called all the time. NEWLINE = "\n" def tok(rx) res = @scanner.scan(rx) if res @line += res.count(NEWLINE) @expected = nil if !@strs.empty? && rx != COMMENT && rx != SINGLE_LINE_COMMENT @strs.each {|s| s << res} end res end end end end end ././@LongLink0000644000000000000000000000015212255653646011656 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/rx.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/0000664000175000017500000001036412206724733033530 0ustar jamespagejamespagemodule Sass module SCSS # A module containing regular expressions used # for lexing tokens in an SCSS document. # Most of these are taken from [the CSS3 spec](http://www.w3.org/TR/css3-syntax/#lexical), # although some have been modified for various reasons. module RX # Takes a string and returns a CSS identifier # that will have the value of the given string. # # @param str [String] The string to escape # @return [String] The escaped string def self.escape_ident(str) return "" if str.empty? return "\\#{str}" if str == '-' || str == '_' out = "" value = str.dup out << value.slice!(0...1) if value =~ /^[-_]/ if value[0...1] =~ NMSTART out << value.slice!(0...1) else out << escape_char(value.slice!(0...1)) end out << value.gsub(/[^a-zA-Z0-9_-]/) {|c| escape_char c} return out end # Escapes a single character for a CSS identifier. # # @param c [String] The character to escape. Should have length 1 # @return [String] The escaped character # @private def self.escape_char(c) return "\\%06x" % Sass::Util.ord(c) unless c =~ /[ -\/:-~]/ return "\\#{c}" end # Creates a Regexp from a plain text string, # escaping all significant characters. # # @param str [String] The text of the regexp # @param flags [Fixnum] Flags for the created regular expression # @return [Regexp] # @private def self.quote(str, flags = 0) Regexp.new(Regexp.quote(str), flags) end H = /[0-9a-fA-F]/ NL = /\n|\r\n|\r|\f/ UNICODE = /\\#{H}{1,6}[ \t\r\n\f]?/ s = if Sass::Util.ruby1_8? '\200-\377' else '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}' end NONASCII = /[#{s}]/ ESCAPE = /#{UNICODE}|\\[ -~#{s}]/ NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/ NMCHAR = /[a-zA-Z0-9_-]|#{NONASCII}|#{ESCAPE}/ STRING1 = /\"((?:[^\n\r\f\\"]|\\#{NL}|#{ESCAPE})*)\"/ STRING2 = /\'((?:[^\n\r\f\\']|\\#{NL}|#{ESCAPE})*)\'/ IDENT = /-?#{NMSTART}#{NMCHAR}*/ NAME = /#{NMCHAR}+/ NUM = /[0-9]+|[0-9]*\.[0-9]+/ STRING = /#{STRING1}|#{STRING2}/ URLCHAR = /[#%&*-~]|#{NONASCII}|#{ESCAPE}/ URL = /(#{URLCHAR}*)/ W = /[ \t\r\n\f]*/ VARIABLE = /(\$)(#{Sass::SCSS::RX::IDENT})/ # This is more liberal than the spec's definition, # but that definition didn't work well with the greediness rules RANGE = /(?:#{H}|\?){1,6}/ ## S = /[ \t\r\n\f]+/ COMMENT = /\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\// SINGLE_LINE_COMMENT = /\/\/.*(\n[ \t]*\/\/.*)*/ CDO = quote("") INCLUDES = quote("~=") DASHMATCH = quote("|=") PREFIXMATCH = quote("^=") SUFFIXMATCH = quote("$=") SUBSTRINGMATCH = quote("*=") HASH = /##{NAME}/ IMPORTANT = /!#{W}important/i DEFAULT = /!#{W}default/i NUMBER = /#{NUM}(?:#{IDENT}|%)?/ URI = /url\(#{W}(?:#{STRING}|#{URL})#{W}\)/i FUNCTION = /#{IDENT}\(/ UNICODERANGE = /u\+(?:#{H}{1,6}-#{H}{1,6}|#{RANGE})/i # Defined in http://www.w3.org/TR/css3-selectors/#lex PLUS = /#{W}\+/ GREATER = /#{W}>/ TILDE = /#{W}~/ NOT = quote(":not(", Regexp::IGNORECASE) # Custom HEXCOLOR = /\#[0-9a-fA-F]+/ INTERP_START = /#\{/ MOZ_ANY = quote(":-moz-any(", Regexp::IGNORECASE) STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\"/ STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\'/ STRING_NOINTERP = /#{STRING1_NOINTERP}|#{STRING2_NOINTERP}/ # Can't use IDENT here, because it seems to take exponential time on 1.8. # We could use it for 1.9 only, but I don't want to introduce a cross-version # behavior difference. # In any case, almost all CSS idents will be matched by this. STATIC_VALUE = /(-?#{NMSTART}|#{STRING_NOINTERP}|\s(?!%)|#[a-f0-9]|[,%]|#{NUM})+(?=[;}])/i STATIC_SELECTOR = /(#{NMCHAR}|\s|[,>+*]|[:#.]#{NMSTART})+(?=[{])/i end end end ././@LongLink0000644000000000000000000000016212255653646011657 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/css_parser.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/0000664000175000017500000000256212206724733033531 0ustar jamespagejamespagerequire 'sass/script/css_parser' module Sass module SCSS # This is a subclass of {Parser} which only parses plain CSS. # It doesn't support any Sass extensions, such as interpolation, # parent references, nested selectors, and so forth. # It does support all the same CSS hacks as the SCSS parser, though. class CssParser < StaticParser # Parse a selector, and return its value as a string. # # @return [String, nil] The parsed selector, or nil if no selector was parsed # @raise [Sass::SyntaxError] if there's a syntax error in the selector def parse_selector_string init_scanner! str {return unless selector} end private def parent_selector; nil; end def interpolation; nil; end def interp_string; tok(STRING); end def interp_ident(ident = IDENT); tok(ident); end def use_css_import?; true; end def block_child(context) case context when :ruleset declaration when :stylesheet directive || ruleset when :directive directive || declaration_or_ruleset end end def nested_properties!(node, space) expected('expression (e.g. 1px, bold)'); end @sass_script_parser = Class.new(Sass::Script::CssParser) @sass_script_parser.send(:include, ScriptParser) end end end ././@LongLink0000644000000000000000000000016412255653646011661 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/script_lexer.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/0000664000175000017500000000064612206724733033532 0ustar jamespagejamespagemodule Sass module SCSS # A mixin for subclasses of {Sass::Script::Lexer} # that makes them usable by {SCSS::Parser} to parse SassScript. # In particular, the lexer doesn't support `!` for a variable prefix. module ScriptLexer private def variable return [:raw, "!important"] if scan(Sass::SCSS::RX::IMPORTANT) _variable(Sass::SCSS::RX::VARIABLE) end end end end ././@LongLink0000644000000000000000000000016512255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/script_parser.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/scss/0000664000175000017500000000133212206724733033523 0ustar jamespagejamespagemodule Sass module SCSS # A mixin for subclasses of {Sass::Script::Parser} # that makes them usable by {SCSS::Parser} to parse SassScript. # In particular, the parser won't raise an error # when there's more content in the lexer once lexing is done. # In addition, the parser doesn't support `!` for a variable prefix. module ScriptParser private # @private def lexer_class klass = Class.new(super) klass.send(:include, ScriptLexer) klass end # Instead of raising an error when the parser is done, # rewind the StringScanner so that it hasn't consumed the final token. def assert_done @lexer.unpeek! end end end end ././@LongLink0000644000000000000000000000014712255653646011662 Lustar rootrootstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/less.rbstapler-stapler-parent-1.218/jruby/src/main/resources/gem/gems/haml-3.1.1/vendor/sass/lib/sass/less.0000775000175000017500000002644512206724733033534 0ustar jamespagejamespage#!/usr/bin/env ruby require 'less' module Less # This is the class that Treetop defines for parsing Less files. # Since not everything gets parsed into the AST but is instead resolved at parse-time, # we need to override some of it so that it can be converted into Sass. module StyleSheet # Selector mixins that don't have arguments. # This depends only on the syntax at the call site; # if it doesn't use parens, it hits this production, # regardless of whether the mixin being called has arguments or not. module Mixin4 def build_with_sass(env) selectors.build(env, :mixin).each do |path| el = path.inject(env.root) do |current, node| current.descend(node.selector, node) or raise MixinNameError, "#{selectors.text_value} in #{env}" end if el.is_a?(Node::Mixin::Def) # Calling a mixin with arguments, which gets compiled to a Sass mixin env << Node::Mixin::Call.new(el, [], env) else # Calling a mixin without arguments, which gets compiled to @extend sel = selector_str(path) base = selector_str(selector_base(path)) if base == sel env << Node::SassNode.new(Sass::Tree::ExtendNode.new([sel])) else Sass::Util.sass_warn <