Text-Sass-v1.0.3000755000765000024 012622171406 12617 5ustar00rmpstaff000000000000Text-Sass-v1.0.3/Build.PL000444000765000024 323712622171406 14255 0ustar00rmpstaff000000000000######### # Author: rmp # Last Modified: $Date: 2011-11-05 22:04:35 +0000 (Sat, 05 Nov 2011) $ # Id: $Id: Build.PL 62 2011-11-05 22:04:35Z zerojinx $ # Source: $Source$ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/Build.PL $ # use strict; use warnings; use Module::Build; use lib qw(lib); my $builder = Module::Build->new( module_name => 'Text-Sass', dist_author => 'Roger Pettett ', dist_version_from => 'lib/Text/Sass.pm', dist_abstract => q[Text-Sass - Perl implementation of http://sass-lang.com/], license => 'perl', requires => { 'Carp' => '1.04', 'English' => '1.02', 'Readonly' => '1.03', 'strict' => '1.03', 'warnings' => '1.05', 'Convert::Color' => '0.05', 'POSIX' => '1.09', }, recommends => { 'Data::Dumper' => '2.125', }, build_requires => { 'Test::More' => '0.8', 'Try::Tiny' => '0.06', }, build_recommends => { 'Test::Distribution' => '2.00', 'Test::Perl::Critic' => '1.01', }, 'meta_merge' => { 'keywords' => [ 'Sass', 'SCSS', 'CSS', ], 'resources' => { 'repository' => 'https://github.com/rmp/libtext-sass-perl' } }, script_files => qw(bin/sass2css.pl), # sign => 1, ); $builder->create_build_script(); Text-Sass-v1.0.3/Changes000444000765000024 243112622171406 14247 0ustar00rmpstaff000000000000Changelog for Text-Sass 1.0.1 - support custom functions. use Text::Sass Functions => [qw(package package)]; 1.0.0 - PR#2 (annulen:multiline_var) from Konstantin Tokarev 0.97 - #80831 comma-separated selectors from BGRIMM #80927 scss to css for nested includes from BGRIMM 0.96 - #77718 pod encoding bug from ANDK - improved URL handling, tests from Dan Markham 0.95 - bugfix for RT#74181 from Andrei Arsenin 0.94 - bugfix for RT#74160 from Andrei Arsenin 0.93 - kicked version number 0.9.3 - downgraded POSIX requirement - RT#72204 0.9.2 - background: url(xxx) no-repeat fix from mk@bluepipe.dk RT#66349 0.9.1 - test fixes - fpu platform differences & RT#63256 0.9 - Function & SCSS support from Bjørn-Olav 0.8 - Flexible indentation fixes, from Bjørn-Olav Retain declaration order, from Bjørn-Olav 0.7 - Better whitespace handling. Very hacky though. A handful of new tests. 0.6 - Better nesting, lots of haphazard debugging; Thanks to tests & queries from Bjørn-Olav Strand 0.4 - Mixins, very rough. Already regretting not using a proper parser/grammar/tokeniser etc. 0.3 - Variables, operators, colour handling 0.2 - Simple nesting; a few more tests 0.1 - Started implementing examples from sass-lang homepage. Basic static conversion seems to work ok. Text-Sass-v1.0.3/LICENSE000444000765000024 1373212622171406 14007 0ustar00rmpstaff000000000000 The "Artistic License" Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder as specified below. "Copyright Holder" is whoever is named in the copyright or copyrights for the package. "You" is you, if you're thinking about copying or distributing this Package. "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as uunet.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) give non-standard executables non-standard names, and clearly document the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. You may embed this Package's interpreter within an executable of yours (by linking); this shall be construed as a mere form of aggregation, provided that the complete Standard Version of the interpreter is so embedded. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whoever generated them, and may be sold commercially, and may be aggregated with this Package. If such scripts or library files are aggregated with this Package via the so-called "undump" or "unexec" methods of producing a binary executable image, then distribution of such an image shall neither be construed as a distribution of this Package nor shall it fall under the restrictions of Paragraphs 3 and 4, provided that you do not represent such an executable image as a Standard Version of this Package. 7. C subroutines (or comparably compiled subroutines in other languages) supplied by you and linked into this Package in order to emulate subroutines and variables of the language defined by this Package shall not be considered part of this Package, but are the equivalent of input as in Paragraph 6, provided these subroutines do not change the language in any way that would cause it to fail the regression tests for the language. 8. Aggregation of this Package with a commercial distribution is always permitted provided that the use of this Package is embedded; that is, when no overt attempt is made to make this Package's interfaces visible to the end user of the commercial distribution. Such use shall not be construed as a distribution of this Package. 9. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End Text-Sass-v1.0.3/Makefile000444000765000024 315512622171406 14420 0ustar00rmpstaff000000000000MAJOR ?= 1 MINOR ?= 0 PATCH ?= 3 CODENAME ?= $(shell lsb_release -cs) MD5SUM = md5sum SEDI = sed -i ifeq ($(shell uname), Darwin) MD5SUM = md5 -r SEDI = sed -i "" endif all: setup ./Build versions: find lib bin -type f -exec perl -i -pe 's/VERSION\s+=\s+q[[\d.]+]/VERSION = q[$(MAJOR).$(MINOR).$(PATCH)]/g' {} \; setup: versions perl Build.PL manifest: setup ./Build manifest clean: setup ./Build clean touch tmp rm -rf build.tap *META*yml _build Build blib cover_db *gz *deb *rpm tmp MANIFEST.bak test: all TEST_AUTHOR=1 ./Build test verbose=1 cover: clean setup HARNESS_PERL_SWITCHES=-MDevel::Cover prove -Ilib t -MDevel::Cover cover -ignore_re t/ install: setup ./Build install dist: setup ./Build dist deb: manifest make test touch tmp rm -rf tmp mkdir -p tmp/usr/lib/perl5 cp -pR deb-src/* tmp/ cp tmp/DEBIAN/control.tt2 tmp/DEBIAN/control $(SEDI) "s/MAJOR/$(MAJOR)/g" tmp/DEBIAN/control $(SEDI) "s/MINOR/$(MINOR)/g" tmp/DEBIAN/control $(SEDI) "s/PATCH/$(PATCH)/g" tmp/DEBIAN/control $(SEDI) "s/RELEASE/$(RELEASE)/g" tmp/DEBIAN/control $(SEDI) "s/CODENAME/$(CODENAME)/g" tmp/DEBIAN/control rsync --exclude .svn --exclude .git -va lib/* tmp/usr/lib/perl5/ rsync --exclude .svn --exclude .git -va bin/* tmp/usr/bin/ find tmp -type f ! -regex '.*\(\bDEBIAN\b\|\.\bsvn\b\|\bdeb-src\b\|\.\bgit\b\|\.\bsass-cache\b\|\.\bnetbeans\b\).*' -exec $(MD5SUM) {} \; | sed 's/tmp\///' > tmp/DEBIAN/md5sums (cd tmp; fakeroot dpkg -b . ../libtext-sass-perl-$(MAJOR).$(MINOR)-$(PATCH)~$(CODENAME).deb) cpan: clean make dist cpan-upload Text-Sass-v$(MAJOR).$(MINOR).$(PATCH).tar.gz Text-Sass-v1.0.3/MANIFEST000444000765000024 175612622171406 14116 0ustar00rmpstaff000000000000bin/sass2css.pl Build.PL Changes deb-src/DEBIAN/changelog deb-src/DEBIAN/control.tt2 examples/README lib/Text/Sass.pm lib/Text/Sass/Expr.pm lib/Text/Sass/Functions.pm lib/Text/Sass/Token.pm LICENSE Makefile MANIFEST This list of files MANIFEST.SKIP README t/00-critic.t t/00-distribution.t t/00-pod.t t/00-podcoverage.t t/05-expr.t t/10-beauty.t t/20-nesting.t t/21-nesting.t t/22-deep.t t/30-variables.t t/40-mixins.t t/50-space.t t/60-functions-extended.t t/60-functions.t t/61-keyword-arguments.t t/62-nested-calls.t t/81-sass-ex.t t/82-sass-ex.t t/90-regression-aa-74181.t t/90-regression-aa.t t/90-regression-background.t t/90-regression-bos.t t/90-regression-wikipedia-nowhitespace.t t/90-regression-wikipedia-parentref.t t/90-regression-wikipedia.t t/91-keep-order.t t/92-no-whitespace.t t/93-parentref-comma.t t/94-scss-linebreaks.t t/lib/special.pm t/RT-62474-accept-spaces.t t/RT-80831-commasep-selectors.t t/RT-80927-nested-includes.t t/RT-80978-nested-ampersand-includes.t META.yml META.json Text-Sass-v1.0.3/MANIFEST.SKIP000444000765000024 21112622171406 14624 0ustar00rmpstaff000000000000^MYMETA.json$ ^MYMETA.yml$ ^META.json$ ^META.yml$ .git .svn _build blib ^Build$ MANIFEST.bak .deb$ .tar.gz$ .rpm$ Text-Sass cover_db tmp Text-Sass-v1.0.3/META.json000444000765000024 337212622171406 14402 0ustar00rmpstaff000000000000{ "abstract" : "Text-Sass - Perl implementation of http://sass-lang.com/", "author" : [ "Roger Pettett " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.4214", "keywords" : [ "Sass", "SCSS", "CSS" ], "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Text-Sass", "prereqs" : { "build" : { "requires" : { "Test::More" : "0.8", "Try::Tiny" : "0.06" } }, "configure" : { "requires" : { "Module::Build" : "0.42" } }, "runtime" : { "recommends" : { "Data::Dumper" : "2.125" }, "requires" : { "Carp" : "1.04", "Convert::Color" : "0.05", "English" : "1.02", "POSIX" : "1.09", "Readonly" : "1.03", "strict" : "1.03", "warnings" : "1.05" } } }, "provides" : { "Text::Sass" : { "file" : "lib/Text/Sass.pm", "version" : "v1.0.3" }, "Text::Sass::Expr" : { "file" : "lib/Text/Sass/Expr.pm", "version" : "v1.0.3" }, "Text::Sass::Functions" : { "file" : "lib/Text/Sass/Functions.pm", "version" : "v1.0.3" }, "Text::Sass::Token" : { "file" : "lib/Text/Sass/Token.pm", "version" : "v1.0.3" } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "https://github.com/rmp/libtext-sass-perl" } }, "version" : "v1.0.3" } Text-Sass-v1.0.3/META.yml000444000765000024 206312622171406 14226 0ustar00rmpstaff000000000000--- abstract: 'Text-Sass - Perl implementation of http://sass-lang.com/' author: - 'Roger Pettett ' build_requires: Test::More: '0.8' Try::Tiny: '0.06' configure_requires: Module::Build: '0.42' dynamic_config: 1 generated_by: 'Module::Build version 0.4214, CPAN::Meta::Converter version 2.150001' keywords: - Sass - SCSS - CSS license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Text-Sass provides: Text::Sass: file: lib/Text/Sass.pm version: v1.0.3 Text::Sass::Expr: file: lib/Text/Sass/Expr.pm version: v1.0.3 Text::Sass::Functions: file: lib/Text/Sass/Functions.pm version: v1.0.3 Text::Sass::Token: file: lib/Text/Sass/Token.pm version: v1.0.3 recommends: Data::Dumper: '2.125' requires: Carp: '1.04' Convert::Color: '0.05' English: '1.02' POSIX: '1.09' Readonly: '1.03' strict: '1.03' warnings: '1.05' resources: license: http://dev.perl.org/licenses/ repository: https://github.com/rmp/libtext-sass-perl version: v1.0.3 Text-Sass-v1.0.3/README000444000765000024 221212622171406 13631 0ustar00rmpstaff000000000000Text-Sass - A Naieve Perl implementation of Sass & SCSS http://sass-lang.com/ ============================================================================= https://github.com/rmp/libtext-sass-perl This is most definitely a work-in-progress. It only implements a subset of the specification but it's being actively developed so if there's functionality missing, drop me a line at rmp@psyphi.net and send me patches and tests. And yes, this should all really be done with a proper language tools, i.e. grammar, parser, tokeniser etc. Bugs & Limitations - Compound class/id/element are unreliable: .element1, .element2 ... - Variables are currently global. This can be quite unpleasant. - There is no support for colorfunctions. - There is no support for @extends. - No support of default for values. - No support for #{} interpolation. - No support for @import of sass and scss. - No support for @debug. - No support for @warn. - No support for @if. - No support for @for. - No support for @while. Other than that, you're good to go. Thanks to Bjørn-Olav Strand, Andreas König, Dan Markham, Konstantin Tokarev and others for patches. Text-Sass-v1.0.3/bin000755000765000024 012622171406 13367 5ustar00rmpstaff000000000000Text-Sass-v1.0.3/bin/sass2css.pl000555000765000024 110012622171406 15620 0ustar00rmpstaff000000000000#!/usr/bin/env perl ######### # Author: rmp # Last Modified: $Date: 2010-10-28 17:09:19 +0100 (Thu, 28 Oct 2010) $ # Id: $Id: sass2css.pl 19 2010-10-28 16:09:19Z zerojinx $ # Source: $Source$ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/bin/sass2css.pl $ # use strict; use warnings; use lib qw(lib); use Text::Sass; use Carp; use English qw(-no_match_vars); our $VERSION = '1.00'; my $sass = Text::Sass->new(); if(!scalar @ARGV) { local $RS = undef; my $str = <>; print $sass->sass2css($str) or croak $ERRNO; } Text-Sass-v1.0.3/deb-src000755000765000024 012622171406 14136 5ustar00rmpstaff000000000000Text-Sass-v1.0.3/deb-src/DEBIAN000755000765000024 012622171406 15060 5ustar00rmpstaff000000000000Text-Sass-v1.0.3/deb-src/DEBIAN/changelog000444000765000024 21212622171406 17042 0ustar00rmpstaff000000000000libtext-sass-perl (0.97) unstable; urgency=low * TSP-1 placeholder -- Roger Pettett Fri, 7 Mar 2014 10:56:00 +0000 Text-Sass-v1.0.3/deb-src/DEBIAN/control.tt2000555000765000024 60612622171406 17315 0ustar00rmpstaff000000000000Package: libtext-sass-perl Version: MAJOR.MINOR-PATCH~CODENAME Section: base Priority: optional Architecture: all Source: libtext-sass-perl Depends: libreadonly-perl,libconvert-color-perl Recommends: libtest-perl-critic-perl, libtest-pod-coverage-perl, libtest-pod-perl,libtry-tiny-perl Maintainer: Roger Pettett Description: Naive implementation of Sass/SCSS preprocessor Text-Sass-v1.0.3/examples000755000765000024 012622171406 14435 5ustar00rmpstaff000000000000Text-Sass-v1.0.3/examples/README000444000765000024 10212622171406 15423 0ustar00rmpstaff000000000000For examples, you're probably best off looking at the tests in t/ Text-Sass-v1.0.3/lib000755000765000024 012622171406 13365 5ustar00rmpstaff000000000000Text-Sass-v1.0.3/lib/Text000755000765000024 012622171406 14311 5ustar00rmpstaff000000000000Text-Sass-v1.0.3/lib/Text/Sass.pm000444000765000024 4710312622171406 15742 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-11-10 16:33:37 +0000 (Sat, 10 Nov 2012) $ # Id: $Id: Sass.pm 75 2012-11-10 16:33:37Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/lib/Text/Sass.pm $ # # Note to reader: # Recursive regex processing can be very bad for your health. # Sass & SCSS are both pretty cool. This module is not. # package Text::Sass; use strict; use warnings; use Carp; use English qw(-no_match_vars); use Text::Sass::Expr; use Text::Sass::Functions; use Text::Sass::Token; use Data::Dumper; use Readonly; our $VERSION = q[1.0.3]; our $DEBUG = 0; our $FUNCTIONS = [qw(Text::Sass::Functions)]; Readonly::Scalar our $DEBUG_SEPARATOR => 30; sub import { my ($class, @args) = @_; if(!scalar @args % 2) { my $args = {@args}; if($args->{Functions}) { for my $functions (@{$args->{Functions}}) { eval "require $functions" or carp qq[Could not require $functions: $EVAL_ERROR]; ## no critic (ProhibitStringyEval) push @{$FUNCTIONS}, $functions; } } } return 1; } sub new { my ($class, $ref) = @_; if(!$ref) { $ref = {}; } bless $ref, $class; return $ref; } sub css2sass { my ($self, $str) = @_; if(!ref $self) { $self = $self->new; } my $symbols = {}; my $stash = []; $self->_parse_css($str, $stash, $symbols); return $self->_stash2sass($stash, $symbols); } sub sass2css { my ($self, $str) = @_; if(!ref $self) { $self = $self->new; } my $symbols = {}; my $stash = []; my $chain = []; $self->{_sass_indent} = 0; $self->_parse_sass($str, $stash, $symbols, $chain); return $self->_stash2css($stash, $symbols); } sub scss2css { my ($self, $str) = @_; if(!ref $self) { $self = $self->new; } my $symbols = {}; my $stash = []; $self->_parse_css($str, $stash, $symbols); return $self->_stash2css($stash, $symbols); } sub _parse_sass { my ($self, $str, $substash, $symbols, $chain) = @_; $DEBUG and print {*STDERR} q[=]x$DEBUG_SEPARATOR, q[begin _parse_sass], q[=]x$DEBUG_SEPARATOR, "\n"; ######### # insert blank links after code2: # code1 # code2 # code3 # code4 # $str =~ s/\n(\S)/\n\n$1/smxg; ######### # strip blank lines from: # # code # $str =~ s/^\s*\n(\s+)/$1/smxg; my $groups = [split /\n\s*?\n/smx, $str]; for my $g (@{$groups}) { $self->_parse_sass_group($substash, $symbols, $chain, $g); } $DEBUG and print {*STDERR} q[=]x$DEBUG_SEPARATOR, q[ end _parse_sass ], q[=]x$DEBUG_SEPARATOR, "\n"; return 1; } sub _parse_sass_group { my ($self, $substash, $symbols, $chain, $group) = @_; my @lines = split /\n/smx, $group; while(my $line = shift @lines) { ######### # /* comment */ # /* comment # $line =~ s{/[*].*?[*]/\s*}{}smx; $line =~ s{/[*].*$}{}smx; ######### # !x = y variable declarations # $line =~ s{^\!(\S+)\s*=\s*(.*?)$}{ $symbols->{variables}->{$1} = $2; $DEBUG and carp qq[VARIABLE $1 = $2]; q[]; }smxegi; ######### # $x : y variable declarations # $line =~ s{^\$(\S+)\s*:\s*(.*?)$}{ $symbols->{variables}->{$1} = $2; $DEBUG and carp qq[VARIABLE $1 = $2]; q[]; }smxegi; ######### # =x | =x(!var) # bla | bla # # mixin declaration # $line =~ s{^=(.*?)$}{ my $mixin_stash = {}; my $remaining = join "\n", @lines; @lines = (); my $proto = $1; my ($func) = $1 =~ /^([^(]+)/smx; ######### # mixins are interpolated later, so we just store the string here # $symbols->{mixins}->{$func} = "$proto\n$remaining\n"; $DEBUG and carp qq[MIXIN $func]; q[]; }smxegi; ######### # @include # # mixin usage # $line =~ s{^\@include\s*(.*?)(?:[(](.*?)[)])?$}{ my ($func, $argstr) = ($1, $2); my $mixin_str = $symbols->{mixins}->{$func}; my $subsymbols = $symbols; # todo: correct scoping - is better as {%{$symbols}} my $values = $argstr ? [split /\s*,\s*/smx, $argstr] : []; my ($varstr) = $mixin_str =~ /^.*?[(](.*?)[)]/smx; my $vars = $varstr ? [split /\s*,\s*/smx, $varstr] : []; for my $var (@{$vars}) { $var =~ s/^[\!\$]//smx; $subsymbols->{variables}->{$var} = shift @{$values}; } $mixin_str =~ s/^.*?\n//smx; my $result = []; $self->_parse_sass($mixin_str, $result, $subsymbols, [@{$chain}]); push @{$substash}, {"+$func" => $result}; $DEBUG and carp qq[DYNAMIC MIXIN $func]; q[]; }smxegi; ######### # @mixin name # bla # # mixin declaration # $line =~ s{^\@mixin\s+(.*?)$}{ my $mixin_stash = {}; my $remaining = join "\n", @lines; @lines = (); my $proto = $1; my ($func) = $1 =~ /^([^(]+)/smx; ######### # mixins are interpolated later, so we just store the string here # $symbols->{mixins}->{$func} = "$proto\n$remaining\n"; $DEBUG and carp qq[MIXIN $func]; q[]; }smxegi; ######### # static +mixin # $line =~ s{^[+]([^(]+)$}{ my $func = $1; my $mixin_str = $symbols->{mixins}->{$func}; $mixin_str =~ s/^.*?\n//smx; my $result = []; $self->_parse_sass($mixin_str, $result, $symbols, [@{$chain}]); my $mixin_tag = (keys %{$result->[0]})[0]; push @{$substash}, {$mixin_tag => (values %{$result->[0]})[0]}; $DEBUG and carp qq[STATIC MIXIN $func / $mixin_tag]; q[]; }smxegi; ######### # interpolated +mixin(value) # $line =~ s{^[+](.*?)[(](.*?)[)]$}{ my ($func, $argstr) = ($1, $2); my $mixin_str = $symbols->{mixins}->{$func}; my $subsymbols = $symbols; # todo: correct scoping - is better as {%{$symbols}} my $values = [split /\s*,\s*/smx, $argstr]; my ($varstr) = $mixin_str =~ /^.*?[(](.*?)[)]/smx; my $vars = [split /\s*,\s*/smx, $varstr]; for my $var (@{$vars}) { $var =~ s/^[\!\$]//smx; $subsymbols->{variables}->{$var} = shift @{$values}; } $mixin_str =~ s/^.*?\n//smx; my $result = []; $self->_parse_sass($mixin_str, $result, $subsymbols, [@{$chain}]); push @{$substash}, {"+$func" => $result}; $DEBUG and carp qq[DYNAMIC MIXIN $func]; q[]; }smxegi; ######### # parent ref # # tag # attribute: value # &:pseudoclass # attribute: value2 # $line =~ s{^(&\s*.*?)$}{$self->_parse_sass_parentref($substash, $symbols, $chain, \@lines, $1)}smxegi; ######### # static and dynamic attr: value # color: #aaa # $line =~ s{^(\S+)\s*[:=]\s*(.*?)$}{ my $key = $1; my $val = $2; $DEBUG and carp qq[ATTR $key = $val]; if($val =~ /^\s*$/smx) { my $remaining = join "\n", @lines; @lines = (); my $ssubstash = []; $self->_parse_sass($remaining, $ssubstash, $symbols, [@{$chain}]); push @{$substash}, { "$key:" => $ssubstash }; } else { push @{$substash}, { $key => $val }; } q[]; }smxegi; ######### # # if ($line =~ /^([ ]+)(\S.*)$/smx) { my $indent = $1; # Indented if (!$self->{_sass_indent}) { $self->{_sass_indent} = length $1; } if ($line =~ /^[ ]{$self->{_sass_indent}}(\S.*)$/smx) { my $process = []; while (my $l = shift @lines) { if($l =~ /^[ ]{$self->{_sass_indent}}(.*)$/smx) { push @{$process}, $1; } elsif ($l !~ /^\s*$/xms) { ######### # put it back where it came from # unshift @lines, $l; last; } } my $remaining = join "\n", $1, @{$process}; $DEBUG and carp qq[INDENTED $line CALLING DOWN REMAINING=$remaining ].Dumper($substash); $self->_parse_sass($remaining, $substash, $symbols, [@{$chain}]); $line = q[]; } else { croak qq[Illegal indent @{[length $indent]} we're using @{[$self->{_sass_indent}]} ($line)]; } } ######### # .class # #id # element # element2, element2 # # $line =~ s{^(\S+.*?)$}{ my $one = $1; $one =~ s/\s+/ /smxg; my $remaining = join "\n", @lines; @lines = (); my $subsubstash = []; $DEBUG and carp qq[ELEMENT $one descending with REMAINING=$remaining]; $DEBUG and carp Dumper($substash); $self->_parse_sass($remaining, $subsubstash, $symbols, [@{$chain}, $one]); push @{$substash}, { $one => $subsubstash }; $DEBUG and carp qq[ELEMENT $one returned]; $DEBUG and carp Dumper($substash); q[]; }smxegi; $DEBUG and $line and carp qq[REMAINING $line]; } return 1; } sub _parse_sass_parentref { ## no critic (ProhibitManyArgs) # todo: tidy this up! my ($self, $substash, $symbols, $chain, $lines, $pseudo) = @_; my $remaining = join "\n", @{$lines}; @{$lines} = (); my $newkey = join q[ ], @{$chain}; $pseudo =~ s/&/&$newkey/smx; my $subsubstash = []; $self->_parse_sass($remaining, $subsubstash, $symbols, ['TBD']); push @{$substash}, {$pseudo => $subsubstash}; return q[]; } sub _css_nestedgroups { my ($self, $str) = @_; my $groups = []; my $groupstr = q[]; my $indent = 0; for my $i (0..length $str ) { my $char = substr $str, $i, 1; $groupstr .= $char; if ($char eq '{') { $indent++; } if ($char eq '}') { $indent--; if ($indent == 0) { push @{$groups}, $groupstr; $groupstr = q[]; } } } return $groups; } sub _css_kvs { my ($self, $str) = @_; my $groups = []; my $groupstr = q[]; my $indent = 0; for my $i (0..length $str) { my $char = substr $str, $i, 1; if ($char eq q[;] and $indent == 0) { push @{$groups}, $groupstr; $groupstr = q[]; } else { $groupstr .= $char; } if ($char eq '{') { $indent++; } if ($char eq '}') { $indent--; if ($indent == 0) { push @{$groups}, $groupstr; $groupstr = q[]; } } } return $groups; } sub _parse_css { my ($self, $str, $substash, $symbols) = @_; $str =~ s{/[*].*?[*]/}{}smxg; # Normalize line breaks $str =~ s/\n//sg; ## no critic (RegularExpressions) $str =~ s/;/;\n/sg; ## no critic (RegularExpressions) $str =~ s/{/{\n/sg; ## no critic (RegularExpressions) $str =~ s/}/}\n/sg; ## no critic (RegularExpressions) ######### # scss definitions # $str =~ s{^\s*\$(\S+)\s*:\s*(.*?)\s*\;}{ $symbols->{variables}->{$1} = $2; $DEBUG and carp qq[VARIABLE $1 = $2]; q[]; }smxegi; my $groups = $self->_css_nestedgroups($str); for my $g (@{$groups}) { my ($tokens, $block) = $g =~ m/([^{]*)[{](.*)[}]/smxg; $tokens =~ s/^\s+//smx; $tokens =~ s/\s+$//smx; $tokens =~ s/\n\s+/\n/smx; $tokens =~ s/\s+\n/\n/smx; if ($tokens =~ /^\s*\@mixin\s+(.*)$/smx) { my $proto = $1; my ($func) = $1 =~ /^([^(]+)/smx; $symbols->{mixins}->{$func} = "$proto {\n$block\n}\n"; $DEBUG and carp qq[MIXIN $func]; next; } my $kvs = $self->_css_kvs($block); my $ssubstash = []; for my $kv (@{$kvs}) { $kv =~ s/^\s+//smx; $kv =~ s/\s+$//smx; if(!$kv) { next; } if ($kv =~ /[{].*[}]/smx) { $self->_parse_css( $kv, $ssubstash, $symbols ); next; } if ($kv =~ /^\s*\@include\s+(.*?)(?:[(](.*?)[)])?$/xms) { my ($func, $argstr) = ($1, $2); my $mixin_str = $symbols->{mixins}->{$func}; my $subsymbols = $symbols; # todo: correct scoping - is better as {%{$symbols}} my $values = $argstr ? [split /\s*,\s*/smx, $argstr] : []; my ($varstr) = $mixin_str =~ /^.*?[(](.*?)[)]/smx; my ($proto) = $mixin_str =~ /^\s*([^{]*\S)\s*[{]/smx; my $vars = $varstr ? [split /\s*,\s*/smx, $varstr] : []; for my $var (@{$vars}) { $var =~ s/^[\!\$]//smx; $subsymbols->{variables}->{$var} = shift @{$values}; } my $result = []; $self->_parse_css($mixin_str, $result, $subsymbols); push @{$ssubstash}, @{$result->[0]->{$proto}}; $DEBUG and carp qq[DYNAMIC MIXIN $func]; next; } if ($kv =~ /^\s*\@extend\s+(.*?)$/xms) { my ($selector) = ($1, $2); carp q[@extend not yet implemented]; ## no critic (RequireInterpolationOfMetachars) next; } my ($key, $value) = split /:/smx, $kv, 2; $key =~ s/^\s+//smx; $key =~ s/\s+$//smx; $value =~ s/^\s+//smx; $value =~ s/\s+$//smx; push @{$ssubstash}, { $key => $value }; } ######### # post-process parent references '&' # my $parent_processed = []; #carp qq[SUBSTASH=].Dumper($substash); for my $child (@{$ssubstash}) { #carp qq[CHILD=].Dumper($child); my ($k) = keys %{$child}; my ($v) = $child->{$k}; #carp qq[post-process k=$k v=$v tokens=$tokens]; $k =~ s{(.*)&}{&$1$tokens}smx; #carp qq[post-process kafter=$k]; push @{$parent_processed}, { $k => $v }; #carp Dumper($substash); #carp Dumper({$tokens => $parent_processed}); } push @{$substash}, { $tokens => $parent_processed }; } return 1; } sub _stash2css { my ($self, $stash, $symbols) = @_; my $groups = []; my $delayed = []; #carp qq[STASH2CSS: ].Dumper($stash); for my $stash_line (@{$stash}) { for my $k (keys %{$stash_line}) { my $vk = $k; $vk =~ s/\s+/ /smx; if($k =~ /&/smx) { ($vk) = $k =~ /&(.*)$/smx; $stash_line->{$vk} = $stash_line->{$k}; delete $stash_line->{$k}; $k = $vk; } my $str = "$vk {\n"; if(!ref $stash_line->{$k}) { $str .= sprintf q[ %s: %s], $vk, $stash_line->{$k}; } else { for my $attr_line (@{$stash_line->{$k}}) { for my $attr (sort keys %{$attr_line}) { my $val = $attr_line->{$attr}; if($attr =~ /^[+]/smx) { $attr = q[]; } if($attr =~ /:$/smx) { ######### # font: # family: foo; # size: bar; # my $rattr = $attr; $rattr =~ s/:$//smx; for my $val_line (@{$val}) { for my $k2 (sort keys %{$val_line}) { $str .= sprintf qq[ %s-%s: %s;\n], $rattr, $k2, $self->_expr($stash, $symbols, $val_line->{$k2}); } } next; } if(ref $val) { if($attr) { $attr = sprintf q[ %s], $attr; } my $rattr = $k . ($attr ? $attr : q[]); if($k =~ /,/smx) { $rattr = join q[, ], map { "$_$attr" } split /\s*,\s*/smx, $k; } if($attr =~ /,/smx) { $attr =~ s/^\s//smx; $rattr = join q[, ], map { "$k $_" } split /\s*,\s*/smx, $attr; } # TODO: What if both have ,? push @{$delayed}, $self->_stash2css([{$rattr => $val}], $symbols); next; } $str .= sprintf qq[ %s: %s;\n], $attr, $self->_expr($stash, $symbols, $val); } } } $str .= "}\n"; if($str !~ /[{]\s*[}]/smx) { push @{$groups}, $str; } push @{$groups}, @{$delayed}; $delayed = []; } } return join "\n", @{$groups}; } sub _expr { my ($self, $stash, $symbols, $expr) = @_; my $vars = $symbols->{variables} || {}; ######### # Do variable expansion # $expr =~ s/\!($Text::Sass::Token::IDENT)/{$vars->{$1}||"\!$1"}/smxeg; $expr =~ s/\$($Text::Sass::Token::IDENT)/{$vars->{$1}||"\$$1"}/smxeg; # TODO: should have lwp, so that url() will work { # Functions while ($expr =~ /^(.*?)((\S+)\s*[(]([^)]+)[)](.*)$)/smx) { my $start = $1; my $mstr = $2; my $func = $3; my $varstr = $4; my $end = $5; ######### # We want hyphenated 'adjust-hue' to work # $func =~ s/\-/_/gsmx; my ($implementor) = [grep { $_->can($func); } @{$FUNCTIONS}]->[0]; if (!$implementor) { $start = $self->_expr($stash, $symbols, $start); $end = $self->_expr($stash, $symbols, $end); ######### # not happy with this here. It probably at least belongs in Expr # - and should include any other CSS stop-words # if($end =~ /repeat|left|top|right|bottom/smx) { ## no-repeat, repeat-x, repeat-y $end = q[]; } $expr = $start . $mstr . $end; last; } ######### # TODO: Should support darken(#323, something(4+5, 5)) # my @vars = split /,/smx, $varstr; for my $var (@vars) { $var =~ s/^\s//smx; $var = $self->_expr($stash, $symbols, $var); } my $res = $implementor->$func(@vars); $expr =~ s/\Q$mstr\E/$res/smx; last; } } my @parts = split /\s+/smx, $expr; Readonly::Scalar my $BINARY_OP_PARTS => 3; if(scalar @parts == $BINARY_OP_PARTS) { my $ret = Text::Sass::Expr->expr(@parts); if (defined $ret) { return $ret; } } return $expr; } sub _stash2sass { my ($self, $stash, $symbols) = @_; my $groups = []; # TODO: Write symbols for my $stashline (@{$stash}) { for my $k (keys %{$stashline}) { my $str = "$k\n"; for my $attrline (@{$stashline->{$k}}){ for my $attr (sort keys %{$attrline}) { my $val = $attrline->{$attr}; $str .= sprintf qq[ %s: %s\n], $attr, $val; } } push @{$groups}, $str; } } return join "\n", @{$groups}; } 1; __END__ =encoding utf8 =head1 NAME Text::Sass - A Naieve Perl implementation of Sass & SCSS. =head1 VERSION See Text/Sass.pm =head1 SYNOPSIS use Text::Sass; my $sass = Text::Sass->new(); print $sass->sass2css(<<'EOF'); $font-stack: Helvetica, sans-serif $primary-color: #333 body font: 100% $font-stack color: $primary-color EOF print $sass->scss2css(<<'EOF'); $font-stack: Helvetica, sans-serif; $primary-color: #333; body { font: 100% $font-stack; color: $primary-color; } EOF =head1 DESCRIPTION This is a pure perl implementation of Sass and SCSS languages. Currently it implements only a subset of the specification. L =head1 SUBROUTINES/METHODS =head2 new - Constructor - nothing special my $oSass = Text::Sass->new; =head2 css2sass - Translate CSS to Sass my $sSass = $oSass->css2sass($sCSS); =head2 sass2css - Translate Sass to CSS my $sCSS = $oSass->sass2css($sSass); =head2 scss2css - Translate Scss to CSS my $sCSS = $oSass->scss2css($sScss); =head1 DEPENDENCIES =over =item L =item L =back =head1 INCOMPATIBILITIES All variables are currently global. This can be quite unpleasant. =head1 BUGS AND LIMITATIONS See README =head1 SEE ALSO L - Perl binding for libsass. Consider using it if you need higher level of language conformance and/or faster execution. L - Yet another libsass binding. L - Sass and SCSS support for all Plack frameworks. Can use this module as one of its backends. =head1 AUTHOR Roger Pettett Ermp@psyphi.netE =head1 DIAGNOSTICS Set $Text::Sass::DEBUG = 1; =head1 CONFIGURATION AND ENVIRONMENT Nothing required beyond $DEBUG =head1 LICENSE AND COPYRIGHT This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.10 or, at your option, any later version of Perl 5 you may have available. =cut Text-Sass-v1.0.3/lib/Text/Sass000755000765000024 012622171406 15222 5ustar00rmpstaff000000000000Text-Sass-v1.0.3/lib/Text/Sass/Expr.pm000444000765000024 1104312622171406 16652 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: Expr.pm 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/lib/Text/Sass/Expr.pm $ # package Text::Sass::Expr; use strict; use warnings; use Carp; use Readonly; our $VERSION = q[1.0.3]; Readonly::Scalar our $SHADE_MAX => 255; # yes, this should be tokenised and probably use overloading our $OPS = { q[-] => sub { my ($x, $y) = @_; return $x - $y; }, q[+] => sub { my ($x, $y) = @_; return $x + $y; }, q[/] => sub { my ($x, $y) = @_; return $x / $y; }, q[*] => sub { my ($x, $y) = @_; return $x * $y; }, q[#-] => sub { my ($x, $y) = @_; my ($xr, $xg, $xb) = @{$x}; my ($yr, $yg, $yb) = @{$y}; my $nr = $xr-$yr; my $ng = $xg-$yg; my $nb = $xb-$yb; if($nr < 0) { $nr = 0; } if($ng < 0) { $ng = 0; } if($nb < 0) { $nb = 0; } return rgb_to_hex(undef,[$nr, $ng, $nb]); }, q[#+] => sub { my ($x, $y) = @_; my ($xr, $xg, $xb) = @{$x}; my ($yr, $yg, $yb) = @{$y}; my $nr = $xr+$yr; my $ng = $xg+$yg; my $nb = $xb+$yb; if($nr > $SHADE_MAX) { $nr = $SHADE_MAX; } if($ng > $SHADE_MAX) { $ng = $SHADE_MAX; } if($nb > $SHADE_MAX) { $nb = $SHADE_MAX; } return rgb_to_hex(undef,[$nr, $ng, $nb]); }, }; Readonly::Scalar our $MM2CM => 0.1; Readonly::Scalar our $CM2MM => 10; Readonly::Scalar our $IN2CM => 2.54; Readonly::Scalar our $CM2IN => 1/2.54; Readonly::Scalar our $IN2MM => 25.4; Readonly::Scalar our $MM2IN => 1/25.4; Readonly::Scalar our $PC2PT => 12; Readonly::Scalar our $PT2PC => 1/12; our $CONV = { q[mm:cm] => sub { my ($v) = @_; return $v*$MM2CM; }, q[cm:mm] => sub { my ($v) = @_; return $v*$CM2MM; }, q[in:cm] => sub { my ($v) = @_; return $v*$IN2CM; }, q[cm:in] => sub { my ($v) = @_; return $v*$CM2IN; }, q[in:mm] => sub { my ($v) = @_; return $v*$IN2MM; }, q[mm:in] => sub { my ($v) = @_; return $v*$MM2IN; }, q[pc|pt] => sub { my ($v) = @_; return $v*$PC2PT; }, q[pt|pc] => sub { my ($v) = @_; return $v*$PT2PC; }, }; sub expr { my ($pkg, $part1, $op, $part2) = @_; $part1 =~ s/[#](.)(.)(.)(\b)/#${1}${1}${2}${2}${3}${3}$4/smxgi; $part2 =~ s/[#](.)(.)(.)(\b)/#${1}${1}${2}${2}${3}${3}$4/smxgi; my ($p1, $u1) = @{$pkg->units($part1)}; my ($p2, $u2) = @{$pkg->units($part2)}; return if(!defined $p1); if(!$u1) { $u1 = q[]; } if(!$u2) { $u2 = q[]; } if(!$u1 && $u2) { $u1 = $u2; } if(!$u2 && $u1) { $u2 = $u1; } if($u1 ne $u2 && $u1 ne q[#] && $u2 ne q[#]) { $p2 = $pkg->convert($p2, $u2, $u1); $u2 = $u1; } if(!exists $OPS->{$op}) { if ($op =~ /^\w/smx) { return; } elsif ($op =~ /\S{2,}/smx) { return; } croak qq[Cannot "$op"]; } if($u1 eq q[#]) { my $cb = $OPS->{"#$op"}; return sprintf q[#%s], $cb->($p1||[0,0,0], $p2||[0,0,0]); } return sprintf q[%s%s], $OPS->{$op}->($p1||0, $p2||0), $u1; } sub units { my ($pkg, $token) = @_; if($token =~ /^[#]/smx) { $token =~ s/^[#]//smx; return [$pkg->hex_to_rgb($token), q[#]]; } my ($val, $units) = $token =~ /([\d.]+)(px|pt|pc|em|ex|mm|cm|in|%|)/smx; return [$val, $units]; } sub rgb_to_hex { my ($pkg, $triple_ref) = @_; return sprintf q[%02x%02x%02x], @{$triple_ref}; } sub hex_to_rgb { my ($pkg, $hex) = @_; my ($r, $g, $b) = unpack q[A2A2A2], $hex; return [hex $r, hex $g, hex $b]; } sub convert { my ($pkg, $val, $from, $to) = @_; my $fromto = "$from:$to"; if(!exists $CONV->{$fromto}) { croak qq[Cannot convert from $from to $to]; } return $CONV->{$fromto}->($val); } 1; __END__ =encoding utf8 =head1 NAME Text::Sass::Expr =head1 VERSION $LastChangedRevision: 71 $ =head1 SYNOPSIS =head1 DESCRIPTION =head1 SUBROUTINES/METHODS =head2 expr =head2 units =head2 rgb_to_hex =head2 hex_to_rgb =head2 convert =head1 DIAGNOSTICS =head1 CONFIGURATION AND ENVIRONMENT =head1 DEPENDENCIES =over =item strict =item warnings =item Carp =item Readonly =back =head1 INCOMPATIBILITIES =head1 BUGS AND LIMITATIONS =head1 AUTHOR $Author: Roger Pettett$ =head1 LICENSE AND COPYRIGHT This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.10 or, at your option, any later version of Perl 5 you may have available. =cut Text-Sass-v1.0.3/lib/Text/Sass/Functions.pm000444000765000024 1766012622171406 17717 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: bolav # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: Functions.pm 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/lib/Text/Sass/Functions.pm $ # package Text::Sass::Functions; use strict; use warnings; use Carp; use Convert::Color; use Text::Sass::Expr; use POSIX qw(); use Readonly; our $VERSION = q[1.0.3]; Readonly::Scalar my $PERC => 100; sub _color { my ($self, $color) = @_; $color =~ s/[#](.)(.)(.)(\b)/#${1}${1}${2}${2}${3}${3}$4/smxgi; $color = Text::Sass::Expr->units($color); if ($color->[1] eq q[#]) { return Convert::Color->new(q[rgb8:].$color->[0]->[0].q[,].$color->[0]->[1].q[,].$color->[0]->[2]); } croak 'not a color '.$color; } sub _value { my ($self, $value) = @_; $value = Text::Sass::Expr->units($value); if ($value->[1] eq q[%]) { return $value->[0] / $PERC; } elsif ($value->[1] eq q[]) { return $value->[0]; } croak 'Unknown unit '.$value->[1].' for value'; } ######### # RGB Functions # sub rgb { my ($self, $r, $g, $b) = @_; my $cc = Convert::Color->new( "rgb8:$r,$g,$b" ); return q[#].$cc->as_rgb8->hex; } # TODO: rgba sub red { my ($self, $color) = @_; return $self->_color($color)->as_rgb8->red; } sub green { my ($self, $color) = @_; return $self->_color($color)->as_rgb8->green; } sub blue { my ($self, $color) = @_; return $self->_color($color)->as_rgb8->blue; } sub mix { my ($self, $c1, $c2, $w) = @_; # TODO: Weight not supported $w ||= '50%'; $c1 = $self->_color($c1); $c2 = $self->_color($c2); $w = $self->_value($w); my $w2 = 1-$w; my $r = int(($c1->as_rgb8->red * $w) + ($c2->as_rgb8->red * $w2)) ; my $g = int(($c1->as_rgb8->green * $w) + ($c2->as_rgb8->green * $w2)) ; my $b = int(($c1->as_rgb8->blue * $w) + ($c2->as_rgb8->blue * $w2)) ; return q[#].Convert::Color->new("rgb8:$r,$g,$b")->hex; } ######### # HSL functions # sub hsl { my ($self, $h, $s, $l) = @_; $s = $self->_value($s); $l = $self->_value($l); my $cc = Convert::Color->new( "hsl:$h,$s,$l" ); return q[#].$cc->as_rgb8->hex; } # TODO: hsla sub hue { my ($self, $color) = @_; return $self->_color($color)->as_hsl->hue; } sub saturation { my ($self, $color) = @_; return $self->_color($color)->as_hsl->saturation; } sub lightness { my ($self, $color) = @_; return $self->_color($color)->as_hsl->lightness; } sub adjust_hue { my ($self, $color, $value) = @_; my $cc = $self->_color($color); my $hsl = $cc->as_hsl; my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s], $hsl->hue+$value, $hsl->saturation, $hsl->lightness ); return q[#].$new_hsl->as_rgb8->hex; } sub lighten { my ($self, $color, $value) = @_; $value = $self->_value($value); my $cc = $self->_color($color); my $hsl = $cc->as_hsl; my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s], $hsl->hue, $hsl->saturation, $hsl->lightness+$value ); return q[#].$new_hsl->as_rgb8->hex; } sub darken { my ($self, $color, $value) = @_; $value = $self->_value($value); my $cc = $self->_color($color); my $hsl = $cc->as_hsl; my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s], $hsl->hue, $hsl->saturation, $hsl->lightness-$value ); return q[#].$new_hsl->as_rgb8->hex; } sub saturate { my ($self, $color, $value) = @_; $value = $self->_value($value); my $cc = $self->_color($color); my $hsl = $cc->as_hsl; my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s], $hsl->hue, $hsl->saturation+$value, $hsl->lightness ); return q[#].$new_hsl->as_rgb8->hex; } sub desaturate { my ($self, $color, $value) = @_; $value = $self->_value($value); my $cc = $self->_color($color); my $hsl = $cc->as_hsl; my $sat = ($hsl->saturation-$value); if ($sat < 0) { $sat = 0; } my $new_hsl = Convert::Color->new( sprintf q[hsl:%s,%s,%s], $hsl->hue, $sat, $hsl->lightness ); return q[#].$new_hsl->as_rgb8->hex; } sub grayscale { my ($self, $color) = @_; return $self->desaturate($color, "$PERC%"); } sub complement { my ($self, $color) = @_; Readonly::Scalar my $COMP_DEGREES => 180; return $self->adjust_hue($color, $COMP_DEGREES); } ######### # STRING Functions # sub unquote { my ($self, $str) = @_; $str =~ s/^\"(.*)\"/$1/xms; $str =~ s/^\'(.*)\'/$1/xms; return $str; } sub quote { my ($self, $str) = @_; if ($str =~ /^\"(.*)\"/xms) { return $str; } if ($str =~ /^\'(.*)\'/xms) { return $str; } return qq["$str"]; } # NUMBER functions sub percentage { my ($self, $num) = @_; return ($num * $PERC) . q[%]; } sub round { my ($self, $str) = @_; my $num = Text::Sass::Expr->units($str); return sprintf q[%.0f%s], $num->[0], $num->[1]; } sub ceil { my ($self, $str) = @_; my $num = Text::Sass::Expr->units($str); return POSIX::ceil($num->[0]).$num->[1]; } sub floor { my ($self, $str) = @_; my $num = Text::Sass::Expr->units($str); return POSIX::floor($num->[0]).$num->[1]; } sub abs { ## no critic (Homonym) my ($self, $str) = @_; my $num = Text::Sass::Expr->units($str); return POSIX::abs($num->[0]).$num->[1]; } ######### # Introspective functions # sub unit { my ($self, $str) = @_; my $num = Text::Sass::Expr->units($str); return q["].$num->[1].q["]; } sub unitless { my ($self, $str) = @_; my $num = Text::Sass::Expr->units($str); return $num->[1] ? 0 : 1; } 1; __END__ =encoding utf8 =head1 NAME Text::Sass::Functions =head1 VERSION $LastChangedRevision: 71 $ =head1 SYNOPSIS =head1 DESCRIPTION =head1 SUBROUTINES/METHODS =head2 rgb(red, green, blue) Converts triplet into a color. =head2 red(color) Returns the red part of a color. =head2 green(color) Returns the green part of a color. =head2 blue(color) Returns the blue part og a color. =head2 mix(color1, color2, weight = 50%) Mixes two colors together. =head2 hsl(hue, saturation, lightness) Converts as hsl triplet into a color. =head2 hue(color) Returns the hue part of a color. =head2 saturation(color) Returns the saturation part of a color. =head2 lightness(color) Returns the lightness part of a color. =head2 adjust_hue(color) Changes the hue of a color, can be called as adjust-hue. =head2 lighten(color, amount) Makes a color lighter. =head2 darken(color, amount) Makes a color darker. =head2 saturate(color, amount) Makes a color more saturated. =head2 desaturate(color, amount) Makes a color less saturated. =head2 grayscale(color) Converts a color to grayscale. =head2 complement(color) Returns the complement of a color. =head2 unquote(str) Removes the quotes from a string. =head2 quote(str) Adds quotes to a string. =head2 percentage(num) Converts a unitless number to a percentage. =head2 round(num) Rounds a number to the nearest whole number. =head2 ceil(num) Rounds a number up to the nearest whole number. =head2 floor(num) Rounds a number down to the nearest whole number. =head2 abs(num) Returns the absolute value of a number. =head2 unit(num) Returns the unit of a value. =head2 unitless(num) Returns true if the number has no unit. =head1 DIAGNOSTICS =head1 CONFIGURATION AND ENVIRONMENT =head1 DEPENDENCIES =over =item strict =item warnings =item Carp =item POSIX =item Readonly =item Convert::Color =item Text::Sass::Expr =back =head1 INCOMPATIBILITIES =head1 BUGS AND LIMITATIONS Missing alpha routines rgba & hsla methods. mix() doesn't support weight. =head1 AUTHOR Author: Bjørn-Olav Strand =head1 LICENSE AND COPYRIGHT This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.10 or, at your option, any later version of Perl 5 you may have available. =cut Text-Sass-v1.0.3/lib/Text/Sass/Token.pm000444000765000024 222112622171406 16772 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: annulen # Last Modified: $Date$ # Id: $Id$ # $HeadURL$ # package Text::Sass::Token; use strict; use warnings; use Readonly; our $VERSION = q[1.0.3]; # TODO: Use token patterns from original sass and use them consistently Readonly our $ESCAPE => qr/\\./smx; Readonly our $NMCHAR => qr/[^\s:\\]|$ESCAPE/smx; Readonly our $IDENT => qr/(?:$NMCHAR)+/smx; 1; __END__ =encoding utf8 =head1 NAME Text::Sass::Token =head1 VERSION =head1 SYNOPSIS use Text::Sass::Token; =head1 DESCRIPTION =head1 SUBROUTINES/METHODS =head1 DEPENDENCIES =over =item L =back =head1 INCOMPATIBILITIES =head1 BUGS AND LIMITATIONS See README =head1 SEE ALSO =head1 AUTHOR Roger Pettett Ermp@psyphi.netE =head1 DIAGNOSTICS =head1 CONFIGURATION AND ENVIRONMENT =head1 LICENSE AND COPYRIGHT This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.10 or, at your option, any later version of Perl 5 you may have available. =cut Text-Sass-v1.0.3/t000755000765000024 012622171406 13062 5ustar00rmpstaff000000000000Text-Sass-v1.0.3/t/00-critic.t000444000765000024 203412622171406 15075 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-11-10 16:33:37 +0000 (Sat, 10 Nov 2012) $ # Id: $Id: 00-critic.t 75 2012-11-10 16:33:37Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/00-critic.t $ # package critic; use strict; use warnings; use Test::More; use English qw(-no_match_vars); our $VERSION = 1; if ( not $ENV{TEST_AUTHOR} ) { my $msg = 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.'; plan( skip_all => $msg ); } eval { require Test::Perl::Critic; }; if($EVAL_ERROR) { plan skip_all => 'Test::Perl::Critic not installed'; } else { Test::Perl::Critic->import( -severity => 1, -exclude => [qw(CodeLayout::RequireTidyCode NamingConventions::Capitalization PodSpelling ValuesAndExpressions::RequireConstantVersion ControlStructures::ProhibitDeepNests)], ); all_critic_ok(); } 1; Text-Sass-v1.0.3/t/00-distribution.t000444000765000024 133112622171406 16336 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 00-distribution.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/00-distribution.t $ # package distribution; use strict; use warnings; use Test::More; use English qw(-no_match_vars); our $VERSION = 1; eval { require Test::Distribution; }; if($EVAL_ERROR) { plan skip_all => 'Test::Distribution not installed'; } else { Test::Distribution->import('not' => 'prereq'); # Having issues with Test::Dist seeing my PREREQ_PM :( } 1; Text-Sass-v1.0.3/t/00-pod.t000444000765000024 104112622171406 14377 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 00-pod.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/00-pod.t $ # use strict; use warnings; use Test::More; eval { require Test::Pod; Test::Pod->import(); }; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; all_pod_files_ok(); Text-Sass-v1.0.3/t/00-podcoverage.t000444000765000024 103412622171406 16115 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 00-podcoverage.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/00-podcoverage.t $ # use Test::More; eval "use Test::Pod::Coverage 1.00"; plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage" if $@; all_pod_coverage_ok(); Text-Sass-v1.0.3/t/05-expr.t000444000765000024 230712622171406 14606 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 05-expr.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/05-expr.t $ # use strict; use warnings; use Test::More; our @CONVS = ( [1, "cm", 10, "mm"], [1, 'in', 2.54, 'cm'], [1, 'in', 25.4, 'mm'], ); our @EXPRS = ( ["10cm - 1cm", "9cm"], ["10cm - 1mm", "9.9cm"], ["1in / 10cm", "0.254in"], ["#3bbfce - #111111", "#2aaebd"], ); plan tests => 7 + scalar @EXPRS; my $pkg = 'Text::Sass::Expr'; use_ok($pkg); { is_deeply($pkg->units('10px'), [10, 'px'], '10px units'); } { is_deeply($pkg->units('2'), [2, ''], '2 units'); } { is_deeply($pkg->units('#efefff'), [[239,239,255], '#'], '#efefff units'); } for my $set (@CONVS) { is($pkg->convert($set->[0], $set->[1], $set->[3]), $set->[2], "$set->[0]$set->[1] = $set->[2]$set->[3]"); } for my $set (@EXPRS) { my @bits = split /\s/smx, $set->[0]; is($pkg->expr(@bits), $set->[1], "$set->[0] = $set->[1]"); } Text-Sass-v1.0.3/t/10-beauty.t000444000765000024 153712622171406 15121 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 10-beauty.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/10-beauty.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 2; my $sass_str = <<"EOT"; h1 height: 118px margin-top: 1em .tagline font-size: 26px text-align: right EOT my $css_str = <<"EOT"; h1 { height: 118px; margin-top: 1em; } .tagline { font-size: 26px; text-align: right; } EOT { my $sass = Text::Sass->new(); is($sass->css2sass($css_str), $sass_str, 'css2sass'); } { my $sass = Text::Sass->new(); is($sass->sass2css($sass_str), $css_str, 'sass2css'); } Text-Sass-v1.0.3/t/20-nesting.t000444000765000024 177712622171406 15306 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 20-nesting.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/20-nesting.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 2; { my $sass_str = <new(); is($sass->sass2css($sass_str), $css_str, 'sass2css'); } { my $sass_str = <new(); is($sass->sass2css($sass_str), $css_str, 'sass2css'); } Text-Sass-v1.0.3/t/21-nesting.t000444000765000024 250412622171406 15274 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 21-nesting.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/21-nesting.t $ # use strict; use Test::More tests => 2; use Text::Sass; { my $sass_str = <new(); is($sass->sass2css($sass_str), $css_str, 'sass2css multilevel nesting'); } { my $sass_str = <new(); is($sass->sass2css($sass_str), $css_str, 'sass2css multilevel nesting'); } Text-Sass-v1.0.3/t/22-deep.t000444000765000024 161412622171406 14544 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 22-deep.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/22-deep.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 1; { my $sass_str = <new(); is($sass->sass2css($sass_str), $css_str, 'sass2css'); } Text-Sass-v1.0.3/t/30-variables.t000444000765000024 230012622171406 15567 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 30-variables.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/30-variables.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 2; { my $sass_str = <<"EOT"; !blue = #3bbfce !margin = 16px .content_navigation border-color = !blue color = !blue - #111 .border padding = !margin / 2 margin = !margin / 2 border-color = !blue EOT my $css_str = <<"EOT"; .content_navigation { border-color: #3bbfce; color: #2aaebd; } .border { padding: 8px; margin: 8px; border-color: #3bbfce; } EOT my $sass = Text::Sass->new(); is($sass->sass2css($sass_str), $css_str, 'sass variables'); } { my $sass_str = <<'EOT'; !blue\: = #3bbfce .content_navigation border-color = !blue\: EOT my $css_str = <<"EOT"; .content_navigation { border-color: #3bbfce; } EOT my $sass = Text::Sass->new(); is($sass->sass2css($sass_str), $css_str, 'sass variable with escaped colon in name'); } Text-Sass-v1.0.3/t/40-mixins.t000444000765000024 311712622171406 15136 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 40-mixins.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/40-mixins.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 3; # $Text::Sass::DEBUG = 1; { my $sass_str = <new(); is($sass->sass2css($sass_str), $css_str, 'static mixin'); } { my $sass_str = <new(); is($sass->sass2css($sass_str), $css_str, 'dynamic mixin, one variable'); } { my $sass_str = <new(); is($sass->sass2css($sass_str), $css_str, 'complex mixin, static + dynamic'); } } Text-Sass-v1.0.3/t/50-space.t000444000765000024 225512622171406 14725 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 50-space.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/50-space.t $ # use strict; use warnings; use Test::More tests => 2; use Text::Sass; { my $sass = <new; is($ts->sass2css($sass), $css, 'without extra whitespace'); } { my $sass = <new; is($ts->sass2css($sass), $css, 'with extra whitespace'); } Text-Sass-v1.0.3/t/60-functions-extended.t000444000765000024 140412622171406 17434 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 60-functions.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/60-functions.t $ # use strict; use warnings; use Test::More tests => 1; use lib qw(t/lib); use Text::Sass Functions => [qw(special)]; my $scss = <<'EOT'; $string: bla $color: #ffffff li background: darken($color, 10%) content: funky($string) EOT my $css = <<'EOT'; li { background: #e5e5e5; content: funky bla; } EOT { my $ts = Text::Sass->new(); is($ts->sass2css($scss), $css, "custom function"); } Text-Sass-v1.0.3/t/60-functions.t000444000765000024 505112622171406 15640 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 60-functions.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/60-functions.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 39; use_ok('Text::Sass::Functions'); # $Text::Sass::DEBUG = 1; my $cf = 'Text::Sass::Functions'; { isa_ok($cf, 'Text::Sass::Functions'); ok($cf->can('darken'),'can darken'); } # RGB { is($cf->rgb(10,10,10), '#0a0a0a', 'rgb'); # rgba is($cf->red('#806040'), 128, 'red'); is($cf->green('#806040'), 96, 'green'); is($cf->blue('#806040'), 64, 'blue'); is($cf->mix('#f00', '#00f'), '#7f007f', 'mix 1'); is($cf->mix('#f00', '#00f', '25%'), '#3f00bf', 'mix 2'); } # HSL { is($cf->hsl(90,'50%','50%'), '#7fbf3f', 'hsl'); # hsla is($cf->hue('#7fbf3f'), 90, 'hue'); is((sprintf q[%0.2f], $cf->saturation('#7fbf3f')), (sprintf q[%0.2f], 0.503937007874016), 'saturation'); is((sprintf q[%0.2f], $cf->lightness('#7fbf3f')), (sprintf q[%0.2f], 0.498039215686275), 'lightness'); is($cf->adjust_hue('#811', 45), '#886a10', 'adjust-hue'); is($cf->lighten('#800', '20%'), '#ee0000', 'lighten'); is($cf->darken('#3bbfce', '9%'), '#2ba1af', 'darken 1'); is($cf->darken('#800', '20%'), '#220000', 'darken 2'); is($cf->saturate('#855', '20%'), '#9e3e3e', 'saturate'); is($cf->desaturate('#855', '20%'), '#716b6b', 'desaturate'); is($cf->grayscale('#855'), $cf->desaturate('#855', '100%'), 'grayscale'); is($cf->complement('#f00'), $cf->adjust_hue('#f00', 180), 'complement'); } # String { is($cf->unquote('"foo"'), 'foo', 'unquote 1'); is($cf->unquote('foo'), 'foo', 'unquote 2'); is($cf->quote('"foo"'), '"foo"', 'quote 1'); is($cf->quote('foo'), '"foo"', 'quote 2'); } # Numbers { is($cf->percentage(2), '200%', 'percentage'); is($cf->round('10.4px'), '10px', 'round 1'); is($cf->round('10.6px'), '11px', 'round 2'); is($cf->ceil('10.4px'), '11px', 'ceil 1'); is($cf->ceil('10.6px'), '11px', 'ceil 2'); is($cf->floor('10.4px'), '10px', 'floor 1'); is($cf->floor('10.6px'), '10px', 'floor 2'); is($cf->abs('10px'), '10px', 'abs 1'); is($cf->abs('-10px'), '10px', 'abs 2'); } # Introspective { is($cf->unit(100), '""', 'unit 1'); is($cf->unit('100px'), '"px"', 'unit 2'); is($cf->unit('3em'), '"em"', 'unit 3'); ok($cf->unitless(100), 'unitless 1'); ok(!$cf->unitless('100px'), 'unitless 2'); } Text-Sass-v1.0.3/t/61-keyword-arguments.t000444000765000024 123612622171406 17321 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### use strict; use warnings; use Text::Sass; use Test::More tests => 2; # TODO: Check whole CSS when keyword arguments are implemented { my $scss = <<'EOT'; $s: bla; li { content: quote($string: $s); } EOT my $ts = Text::Sass->new(); like($ts->scss2css($scss), qr/\bbla\b/, "variable substitution in keyword argument"); } { my $scss = <<'EOT'; $s: bla; li { content: quote($string:$s); } EOT my $ts = Text::Sass->new(); like($ts->scss2css($scss), qr/\bbla\b/, "variable substitution in keyword argument after missing space"); } Text-Sass-v1.0.3/t/62-nested-calls.t000444000765000024 133612622171406 16212 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### use strict; use warnings; use Text::Sass; use Test::More tests => 2; { my $scss = <<'EOT'; li { background: darken(darken(#3bbfce, 9%), 1%); } EOT SKIP: { skip "Nested function calls don't work", 1; my $ts = Text::Sass->new(); like($ts->scss2css($scss), qr/\Qbackground: #299daa;\E/, "nested function calls"); } } { my $scss = <<'EOT'; $blue: #3bbfce; $darkBlue: darken($blue, 9%); li { background: darken($darkBlue, 1%); } EOT my $ts = Text::Sass->new(); like($ts->scss2css($scss), qr/\Qbackground: #299daa;\E/, "nested function calls created via intermediate variable"); } Text-Sass-v1.0.3/t/81-sass-ex.t000444000765000024 467712622171406 15233 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 81-sass-ex.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/81-sass-ex.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 4; # $Text::Sass::DEBUG = 1; { my $css = <new(); is($ts->sass2css($sass), $css, "variables examples"); } { my $sass = <new(); is($ts->sass2css($sass), $css, "nesting example"); } { my $sass = <new(); # BOS: This looks like is wrongly implemented in sass-lang.com/try.html as well. local $TODO = "no support for extend yet"; is($ts->sass2css($sass), $css, "inherintance example"); } { my $sass = <new(); #local $TODO = "no support for extend yet"; is($ts->sass2css($sass), $css, "mixin example"); } Text-Sass-v1.0.3/t/82-sass-ex.t000444000765000024 455712622171406 15231 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 82-sass-ex.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/82-sass-ex.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 4; # $Text::Sass::DEBUG = 1; { my $css = <new(); is($ts->scss2css($scss), $css, "variables examples"); } { my $css = <new(); is($ts->scss2css($scss), $css, "nested example"); } { my $scss = <new(); is($ts->scss2css($scss), $css, "mixin example"); } { my $scss = <new(); is($ts->scss2css($scss), $css, "Selector Inheritance example"); } Text-Sass-v1.0.3/t/90-regression-aa-74181.t000444000765000024 232012622171406 17050 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-11-10 16:33:37 +0000 (Sat, 10 Nov 2012) $ # Id: $Id: 90-regression-aa-74181.t 75 2012-11-10 16:33:37Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/90-regression-aa-74181.t $ # use strict; use warnings; use Text::Sass '0.97'; use Test::More tests => 2; { my $css = <new(); is($ts->scss2css($scss), $css, "simple parent reference"); } { my $css = <new(); is($ts->scss2css($scss), $css, "complex parent reference"); } Text-Sass-v1.0.3/t/90-regression-aa.t000444000765000024 133312622171406 16371 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 90-regression-aa.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/90-regression-aa.t $ # use strict; use warnings; use Text::Sass '0.94'; use Test::More tests => 1; { my $css = <new(); is($ts->scss2css($scss), $css, "scss to css conversion ok"); } Text-Sass-v1.0.3/t/90-regression-background.t000444000765000024 363612622171406 20137 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 90-regression-background.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/90-regression-background.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 5; { my $scss = q[.x-panel-body { background: white url(/images/RegH_logo_RGB.gif) no-repeat; }]; my $ts = Text::Sass->new; is($ts->scss2css($scss), <<'EOT', 'local background + colour'); .x-panel-body { background: white url(/images/RegH_logo_RGB.gif) no-repeat; } EOT } { my $scss = q[.x-panel-body { background: url(/images/RegH_logo_RGB.gif) no-repeat; }]; my $ts = Text::Sass->new; is($ts->scss2css($scss), <<'EOT', 'local background'); .x-panel-body { background: url(/images/RegH_logo_RGB.gif) no-repeat; } EOT } { my $scss = q[.x-panel-body { background: url(http://images/RegH_logo_RGB.gif) no-repeat; }]; my $ts = Text::Sass->new; is($ts->scss2css($scss), <<'EOT', 'http/remote background'); .x-panel-body { background: url(http://images/RegH_logo_RGB.gif) no-repeat; } EOT } { my $scss = q[.x-panel-body { background: url("http://images/RegH_logo_RGB.gif") no-repeat; }]; my $ts = Text::Sass->new; is($ts->scss2css($scss), <<'EOT', 'http remote background, double-quoted'); .x-panel-body { background: url("http://images/RegH_logo_RGB.gif") no-repeat; } EOT } { my $scss = q[.x-panel-body { background: url('https://images/RegH_logo_RGB.gif') no-repeat 0 0; }]; my $ts = Text::Sass->new; is($ts->scss2css($scss), <<'EOT', 'https remote background, single-quoted'); .x-panel-body { background: url('https://images/RegH_logo_RGB.gif') no-repeat 0 0; } EOT } Text-Sass-v1.0.3/t/90-regression-bos.t000444000765000024 174512622171406 16602 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 90-regression-bos.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/90-regression-bos.t $ # use strict; use warnings; use Text::Sass '0.5'; use Test::More tests => 4; { my $css = <new(); is($ts->css2sass($css), $sass, "css to sass conversion ok"); is($ts->sass2css($sass), $css, "sass to css conversion ok"); } { my $css = <new(); # $Text::Sass::DEBUG = 1; is($ts->css2sass($css), $sass, "css to sass conversion ok"); is($ts->sass2css($sass), $css, "sass to css conversion ok"); } Text-Sass-v1.0.3/t/90-regression-wikipedia-nowhitespace.t000444000765000024 166212622171406 22452 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 90-regression-wikipedia-nowhitespace.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/90-regression-wikipedia-nowhitespace.t $ # use strict; use warnings; use Test::More tests => 1; use Text::Sass; my $sass = <new; is($ts->sass2css($sass), $css, 'wikipedia example 1'); Text-Sass-v1.0.3/t/90-regression-wikipedia-parentref.t000444000765000024 140412622171406 21741 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 90-regression-wikipedia-parentref.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/90-regression-wikipedia-parentref.t $ # use strict; use warnings; use Test::More tests => 1; use Text::Sass; my $sass = <new; is($ts->sass2css($sass), $css, 'wikipedia example parent "&" reference'); Text-Sass-v1.0.3/t/90-regression-wikipedia.t000444000765000024 163212622171406 17760 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 90-regression-wikipedia.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/90-regression-wikipedia.t $ # use strict; use warnings; use Test::More tests => 1; use Text::Sass; my $sass = <new; is($ts->sass2css($sass), $css, 'wikipedia example 1'); Text-Sass-v1.0.3/t/91-keep-order.t000444000765000024 172612622171406 15676 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 91-keep-order.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/91-keep-order.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 2; # $Text::Sass::DEBUG = 1; { my $css = <new(); is($ts->sass2css($sass), $css, "sass to css conversion ok"); } { my $css = <new(); is($ts->sass2css($sass), $css, "sass to css conversion ok"); } Text-Sass-v1.0.3/t/92-no-whitespace.t000444000765000024 124712622171406 16406 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 92-no-whitespace.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/92-no-whitespace.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 1; { my $css = <new(); is($ts->sass2css($sass), $css, "sass to css conversion ok"); } Text-Sass-v1.0.3/t/93-parentref-comma.t000444000765000024 203512622171406 16715 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: 93-parentref-comma.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/93-parentref-comma.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 1; { our $TODO = "Parent ref with commas not working"; my $css = <new(); is($ts->sass2css($sass), $css, "sass to css conversion ok"); } } Text-Sass-v1.0.3/t/94-scss-linebreaks.t000444000765000024 276712622171406 16742 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### use strict; use warnings; use Text::Sass; use Test::More tests => 6; # $Text::Sass::DEBUG = 1; my $css = <<'EOT'; .border { margin: 16px; } EOT { my $scss = <<'EOT'; $margin : 16px; .border { margin: $margin; } EOT my $ts = Text::Sass->new(); is($ts->scss2css($scss), $css, "multiline scss variable declaration"); } { my $scss = <<'EOT'; $margin: 16px ; .border { margin: $margin; } EOT my $ts = Text::Sass->new(); is($ts->scss2css($scss), $css, "line break after scss variable declaration"); } { my $scss = <<'EOT'; $margin : floor(33px / 2); .border { margin: $margin; } EOT my $ts = Text::Sass->new(); is($ts->scss2css($scss), $css, "multiline scss variable declaration with function call"); } { my $scss = <<'EOT'; .border { margin: 16px ; } EOT my $ts = Text::Sass->new(); is($ts->scss2css($scss), $css, "line break in simple property declaration"); } # This snippet was causing infinite loop { my $scss = <<'EOT'; $margin: 16px; .border { margin: $margin; } EOT my $ts = Text::Sass->new(); is($ts->scss2css($scss), $css, "line break in property declaration with variable"); } { my $scss = <<'EOT'; $margin: 16px; .title { margin: foo( $margin: 1 ); } .border { margin: $margin; } EOT my $ts = Text::Sass->new(); like($ts->scss2css($scss), qr/\Q$css\E/, "line break in property declaration with variable"); } Text-Sass-v1.0.3/t/RT-62474-accept-spaces.t000444000765000024 204112622171406 17123 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-09-12 09:42:30 +0100 (Wed, 12 Sep 2012) $ # Id: $Id: RT-62474-accept-spaces.t 71 2012-09-12 08:42:30Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/RT-62474-accept-spaces.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 3; use Try::Tiny; { my $css = <new(); is($ts->sass2css($sass), $css, "sass to css conversion ok"); } { my $css = <new(); is($ts->sass2css($sass), $css, "sass to css conversion ok"); } { my $sass = <new(); try { diag $ts->sass2css($sass); } catch { ok(1, "dieing from illegal indent $_"); } }Text-Sass-v1.0.3/t/RT-80831-commasep-selectors.t000444000765000024 134312622171406 20216 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-11-10 16:33:37 +0000 (Sat, 10 Nov 2012) $ # Id: $Id: RT-80831-commasep-selectors.t 75 2012-11-10 16:33:37Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/RT-80831-commasep-selectors.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 1; { my $sass = <new(); is($ts->scss2css($sass), $css, "RT#80831 scss to css for comma-separated selectors"); } Text-Sass-v1.0.3/t/RT-80927-nested-includes.t000444000765000024 144212622171406 17505 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-11-10 16:33:37 +0000 (Sat, 10 Nov 2012) $ # Id: $Id: RT-80927-nested-includes.t 75 2012-11-10 16:33:37Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/RT-80927-nested-includes.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 1; { my $sass = <<'EOT'; @mixin test { color: #fff; } p { .a { .b { @include test; } } .c { @include test; } } EOT my $css = <new(); is($ts->scss2css($sass), $css, "RT#80927 scss to css for nested includes"); } Text-Sass-v1.0.3/t/RT-80978-nested-ampersand-includes.t000444000765000024 145112622171406 21463 0ustar00rmpstaff000000000000# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*- # vim:ts=8:sw=2:et:sta:sts=2 ######### # Author: rmp # Last Modified: $Date: 2012-11-10 16:33:37 +0000 (Sat, 10 Nov 2012) $ # Id: $Id: RT-80978-nested-ampersand-includes.t 75 2012-11-10 16:33:37Z zerojinx $ # $HeadURL: https://text-sass.svn.sourceforge.net/svnroot/text-sass/trunk/t/RT-80978-nested-ampersand-includes.t $ # use strict; use warnings; use Text::Sass; use Test::More tests => 1; { my $sass = <<'EOT'; a { b { &.this { color: #fff; } } } EOT my $css = <new(); is($ts->scss2css($sass), $css, "RT#80978 scss to css for nested ampersand includes"); } } Text-Sass-v1.0.3/t/lib000755000765000024 012622171406 13630 5ustar00rmpstaff000000000000Text-Sass-v1.0.3/t/lib/special.pm000444000765000024 15412622171406 15723 0ustar00rmpstaff000000000000package special; use strict; use warnings; sub funky { my ($class, $str) = @_; return "funky $str"; }; 1;