1
0
mirror of https://github.com/mgerb/mywebsite synced 2026-01-14 19:42:49 +00:00

Added files

This commit is contained in:
2015-06-25 16:28:41 -05:00
parent 656dca9289
commit eb27b55a54
5621 changed files with 1630154 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
node_modules
test

View File

@@ -0,0 +1,4 @@
language: node_js
node_js:
- 0.8
- 0.10

View File

@@ -0,0 +1,118 @@
[![Build Status](https://travis-ci.org/visionmedia/nib.png?branch=master)](https://travis-ci.org/visionmedia/nib)
# Nib
Stylus mixins, utilities, components, and gradient image generation. Don't forget to check out the [documentation](http://visionmedia.github.com/nib/).
## Installation
```bash
$ npm install nib
```
If the image generation features of Nib are desired, such as generating the linear gradient images, install [node-canvas](http://github.com/learnboost/node-canvas):
```bash
$ npm install canvas
```
## JavaScript API
Below is an example of how to utilize nib and stylus with the connect framework (or express).
```javascript
var connect = require('connect')
, stylus = require('stylus')
, nib = require('nib');
var server = connect();
function compile(str, path) {
return stylus(str)
.set('filename', path)
.set('compress', true)
.use(nib());
}
server.use(stylus.middleware({
src: __dirname
, compile: compile
}));
```
## Stylus API
To gain access to everything nib has to offer, simply add:
```css
@import 'nib'
```
Or you may also pick and choose based on the directory structure in `./lib`, for example:
```css
@import 'nib/gradients'
@import 'nib/overflow'
```
to be continued....
## More Information
- Introduction [screencast](http://www.screenr.com/M6a)
## Testing
You will first need to install the dependencies:
```bash
$ npm install -d
```
Run the automated test cases:
```bash
$ npm test
```
For visual testing run the test server:
```bash
$ npm run-script test-server
```
Then visit `localhost:3000` in your browser.
## Contributors
I would love more contributors. And if you have helped out, you are awesome! I want to give a huge thanks to these people:
- [TJ Holowaychuk](https://github.com/visionmedia) (Original Creator)
- [Sean Lang](https://github.com/slang800) (Current Maintainer)
- [Isaac Johnston](https://github.com/superstructor)
- [Everyone Else](https://github.com/visionmedia/nib/contributors)
## License
(The MIT License)
Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
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.

View File

@@ -0,0 +1,95 @@
<html>
<head>
<link rel="stylesheet" href="iconic.css" type="text/css" media="screen" title="no title" charset="utf-8">
<style>
body {
font-size:21px;
}
</style>
</head>
<body>
<ul>
<li><a name='home' class='iconic home'></a> Home</li>
<li><a name='at' class='iconic at'></a> At Symbol</li>
<li><a name='quote' class='iconic quote'></a> Quote</li>
<li><a name='quote-alt' class='iconic quote-alt'></a> Quote (alternate)</li>
<li><a name='arrow-up' class='iconic arrow-up'></a> Arrow Up</li>
<li><a name='arrow-right' class='iconic arrow-right'></a> Arrow Right</li>
<li><a name='arrow-bottom' class='iconic arrow-bottom'></a> Arrow Bottom</li>
<li><a name='arrow-left' class='iconic arrow-left'></a> Arrow Left</li>
<li><a name='arrow-up-alt' class='iconic arrow-up-alt'></a> Arrow Up (alternate)</li>
<li><a name='arrow-right-alt' class='iconic arrow-right-alt'></a> Arrow Right (alternate)</li>
<li><a name='arrow-bottom-alt' class='iconic arrow-bottom-alt'></a> Arrow Bottom (alternate)</li>
<li><a name='arrow-left-alt' class='iconic arrow-left-alt'></a> Arrow Left (alternate)</li>
<li><a name='move' class='iconic move'></a> Move</li>
<li><a name='move-vertical' class='iconic move-vertical'></a> Move Vertical</li>
<li><a name='move-horizontal' class='iconic move-horizontal'></a> Move Horizontal</li>
<li><a name='move-alt' class='iconic move-alt'></a> Move (alternate)</li>
<li><a name='move-vertical-alt' class='iconic move-vertical-alt'></a> Move Vertical (alternate)</li>
<li><a name='move-horizontal-alt' class='iconic move-horizontal-alt'></a> Move Horizontal (alternate)</li>
<li><a name='cursor' class='iconic cursor'></a> Cursor</li>
<li><a name='plus' class='iconic plus'></a> Plus</li>
<li><a name='plus-alt' class='iconic plus-alt'></a> Plus (alternate)</li>
<li><a name='minus' class='iconic minus'></a> Minus</li>
<li><a name='minus-alt' class='iconic minus-alt'></a> Minus (alternate)</li>
<li><a name='new-window' class='iconic new-window'></a> New Window</li>
<li><a name='dial' class='iconic dial'></a> Dial</li>
<li><a name='lightbulb' class='iconic lightbulb'></a> Lightbulb</li>
<li><a name='link' class='iconic link'></a> Link</li>
<li><a name='image' class='iconic image'></a> Image</li>
<li><a name='article' class='iconic article'></a> Article</li>
<li><a name='read-more' class='iconic read-more'></a> Read More</li>
<li><a name='headphones' class='iconic headphones'></a> Headphones</li>
<li><a name='equalizer' class='iconic equalizer'></a> Equalizer</li>
<li><a name='fullscreen' class='iconic fullscreen'></a> Fullscreen</li>
<li><a name='exit-fullscreen' class='iconic exit-fullscreen'></a> Exit Fullscreen</li>
<li><a name='spin' class='iconic spin'></a> Spin</li>
<li><a name='spin-alt' class='iconic spin-alt'></a> Spin (alternate)</li>
<li><a name='moon' class='iconic moon'></a> Moon</li>
<li><a name='sun' class='iconic sun'></a> Sun</li>
<li><a name='map-pin' class='iconic map-pin'></a> Map Pin</li>
<li><a name='pin' class='iconic pin'></a> Pin</li>
<li><a name='eyedropper' class='iconic eyedropper'></a> Eyedropper</li>
<li><a name='denied' class='iconic denied'></a> Denied</li>
<li><a name='calendar' class='iconic calendar'></a> Calendar</li>
<li><a name='calendar-alt' class='iconic calendar-alt'></a> Calendar (alternate)</li>
<li><a name='bolt' class='iconic bolt'></a> Bolt</li>
<li><a name='clock' class='iconic clock'></a> Clock</li>
<li><a name='document' class='iconic document'></a> Document</li>
<li><a name='book' class='iconic book'></a> Book</li>
<li><a name='book-alt' class='iconic book-alt'></a> Book (alternate)</li>
<li><a name='magnifying-glass' class='iconic magnifying-glass'></a> Magnifying Glass</li>
<li><a name='tag' class='iconic tag'></a> Tag</li>
<li><a name='heart' class='iconic heart'></a> Heart</li>
<li><a name='info' class='iconic info'></a> Info</li>
<li><a name='chat' class='iconic chat'></a> Chat</li>
<li><a name='chat-alt' class='iconic chat-alt'></a> Chat (alternate)</li>
<li><a name='key' class='iconic key'></a> Key</li>
<li><a name='unlocked' class='iconic unlocked'></a> Unlocked</li>
<li><a name='locked' class='iconic locked'></a> Locked</li>
<li><a name='mail' class='iconic mail'></a> Mail</li>
<li><a name='mail' class='iconic mail-alt'></a> Mail (alternate)</li>
<li><a name='phone' class='iconic phone'></a> Phone</li>
<li><a name='box' class='iconic box'></a> Box</li>
<li><a name='pencil' class='iconic pencil'></a> Pencil</li>
<li><a name='pencil-alt' class='iconic pencil-alt'></a> Pencil (alternate)</li>
<li><a name='comment' class='iconic comment'></a> Comment</li>
<li><a name='comment' class='iconic comment-alt'></a> Comment (alternate)</li>
<li><a name='rss' class='iconic rss'></a> RSS</li>
<li><a name='star' class='iconic star'></a> Star</li>
<li><a name='trash' class='iconic trash'></a> Trash</li>
<li><a name='user' class='iconic user'></a> User</li>
<li><a name='volume' class='iconic volume'></a> Volume</li>
<li><a name='mute' class='iconic mute'></a> Mute</li>
<li><a name='cog' class='iconic cog'></a> Cog</li>
<li><a name='cog-alt' class='iconic cog-alt'></a> Cog (alternate)</li>
<li><a name='x' class='iconic x'></a> X</li>
<li><a name='x' class='iconic x-alt'></a> X (alternate)</li>
<li><a name='check' class='iconic check'></a> Check</li>
<li><a name='check-alt' class='iconic check-alt'></a> Check (alternate)</li>
<li><a name='beaker' class='iconic beaker'></a> Beaker</li>
<li><a name='beaker-alt' class='iconic beaker-alt'></a> Beaker (alternate)</li>
</ul>
</body>
</html>

View File

@@ -0,0 +1,97 @@
@font-face {
font-family: 'IconicStroke';
src: url("iconic_stroke.eot");
src: local('IconicStroke'),
url("iconic_stroke.svg#iconic") format('svg'),
url("iconic_stroke.otf") format('opentype');
}
.iconic {
color:inherit;
font-family: "IconicStroke";
}
a.iconic:hover {
color:inherit;
}
.iconic.home:before { content: '!'; }
.iconic.at:before { content: "@"; }
.iconic.quote:before { content: '"'; }
.iconic.quote-alt:before { content: "'"; }
.iconic.arrow-up:before { content: "3"; }
.iconic.arrow-right:before { content: "4"; }
.iconic.arrow-bottom:before { content: "5"; }
.iconic.arrow-left:before { content: "6"; }
.iconic.arrow-up-alt:before { content: "#"; }
.iconic.arrow-right-alt:before { content: "$"; }
.iconic.arrow-bottom-alt:before { content: "%"; }
.iconic.arrow-left-alt:before { content: "^"; }
.iconic.move:before { content: "9"; }
.iconic.move-vertical:before { content: "8"; }
.iconic.move-horizontal:before { content: "7"; }
.iconic.move-alt:before { content: "("; }
.iconic.move-vertical-alt:before { content: "*"; }
.iconic.move-horizontal-alt:before { content: "&"; }
.iconic.cursor:before { content: ")"; }
.iconic.plus:before { content: "+"; }
.iconic.plus-alt:before { content: "="; }
.iconic.minus:before { content: "-"; }
.iconic.minus-alt:before { content: "_"; }
.iconic.new-window:before { content: "1"; }
.iconic.dial:before { content: "2"; }
.iconic.lightbulb:before { content: "0"; }
.iconic.link:before { content: "/"; }
.iconic.image:before { content: "?"; }
.iconic.article:before { content: ">"; }
.iconic.read-more:before { content: "."; }
.iconic.headphones:before { content: ","; }
.iconic.equalizer:before { content: "<"; }
.iconic.fullscreen:before { content: ":"; }
.iconic.exit-fullscreen:before { content: ";"; }
.iconic.spin:before { content: "["; }
.iconic.spin-alt:before { content: "{"; }
.iconic.moon:before { content: "]"; }
.iconic.sun:before { content: "}"; }
.iconic.map-pin:before { content: "\\"; }
.iconic.pin:before { content: "|"; }
.iconic.eyedropper:before { content: "~"; }
.iconic.denied:before { content: "`"; }
.iconic.calendar:before { content: "a"; }
.iconic.calendar-alt:before { content: "A"; }
.iconic.bolt:before { content: "b"; }
.iconic.clock:before { content: "c"; }
.iconic.document:before { content: "d"; }
.iconic.book:before { content: "e"; }
.iconic.book-alt:before { content: "E"; }
.iconic.magnifying-glass:before { content: "f"; }
.iconic.tag:before { content: "g"; }
.iconic.heart:before { content: "h"; }
.iconic.info:before { content: "i"; }
.iconic.chat:before { content: "j"; }
.iconic.chat-alt:before { content: "J"; }
.iconic.key:before { content: "k"; }
.iconic.unlocked:before { content: "l"; }
.iconic.locked:before { content: "L"; }
.iconic.mail:before { content: "m"; }
.iconic.mail-alt:before { content: "M"; }
.iconic.phone:before { content: "n"; }
.iconic.box:before { content: "o"; }
.iconic.pencil:before { content: "p"; }
.iconic.pencil-alt:before { content: "P"; }
.iconic.comment:before { content: "q"; }
.iconic.comment-alt:before { content: "Q"; }
.iconic.rss:before { content: "r"; }
.iconic.star:before { content: "s"; }
.iconic.trash:before { content: "t"; }
.iconic.user:before { content: "u"; }
.iconic.volume:before { content: "v"; }
.iconic.mute:before { content: "V"; }
.iconic.cog:before { content: "w"; }
.iconic.cog-alt:before { content: "W"; }
.iconic.x:before { content: "x"; }
.iconic.x-alt:before { content: "X"; }
.iconic.check:before { content: "y"; }
.iconic.check-alt:before { content: "Y"; }
.iconic.beaker:before { content: "z"; }
.iconic.beaker-alt:before { content: "Z"; }

View File

@@ -0,0 +1,393 @@
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" > <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<defs >
<font id="iconic" horiz-adv-x="1330" ><font-face
font-family="Iconic Stroke"
units-per-em="2048"
panose-1="2 11 6 3 2 1 2 2 2 4"
ascent="1434"
descent="-389"
alphabetic="0" />
<missing-glyph horiz-adv-x="512" />
<glyph unicode=" " glyph-name="null" horiz-adv-x="512" />
<glyph unicode="!" glyph-name="null" horiz-adv-x="1502" d="M687 1372L1373 686H1201V0H172V686H0L687 1372ZM1030 171V786L687 1029L343 786V171H601V429H772V171H1030Z" />
<glyph unicode="&quot;" glyph-name="null" horiz-adv-x="1669" d="M856 180V694Q856 800 896 893T1006 1056T1169 1166T1370 1207V1036Q1299 1036 1237 1009T1128 936T1054 827T1027 694H1370V180H856ZM0 180V694Q0 800 40 893T150 1056T313 1166T514 1207V1036Q443
1036 381 1009T272 936T198 827T171 694H514V180H0Z" />
<glyph unicode="#" glyph-name="null" horiz-adv-x="1551" d="M0 685Q0 780 24 867T93 1031T200 1169T339 1276T503 1345T685 1370Q779 1370 866 1346T1030 1277T1169 1170T1276 1031T1345 868T1370 685Q1370 543 1316 419T1169 201T952 54T685 0Q543 0 419 54T201
201T54 418T0 685ZM685 1027L344 686H599V342H770V686H1027L685 1027Z" />
<glyph unicode="$" glyph-name="null" horiz-adv-x="1551" d="M686 1372Q828 1372 953 1318T1171 1171T1318 953T1372 686Q1372 544 1318 419T1171 201T953 54T686 0Q544 0 419 54T201 201T54 419T0 686Q0 828 54 953T201 1171T419 1318T686 1372ZM1029 686L687
1028V772H343V600H687V343L1029 686Z" />
<glyph unicode="%" glyph-name="null" horiz-adv-x="1551" d="M1372 686Q1372 544 1318 419T1171 201T953 54T686 0Q544 0 419 54T201 201T54 419T0 686Q0 828 54 953T201 1171T419 1318T686 1372Q828 1372 953 1318T1171 1171T1318 953T1372 686ZM686 343L1028
685H772V1029H600V685H343L686 343Z" />
<glyph unicode="&amp;" glyph-name="null" horiz-adv-x="1551" d="M1370 685Q1370 591 1346 504T1277 340T1170 201T1031 94T868 25T685 0Q543 0 419 54T201 201T54 418T0 685Q0 827 54 951T201 1169T418 1316T685 1370Q780 1370 867 1346T1031 1277T1169 1170T1276
1031T1345 867T1370 685ZM943 599V514L1114 685L943 856V770H429V856L258 685L429 514V599H943Z" />
<glyph unicode="&apos;" glyph-name="null" horiz-adv-x="1669" d="M856 180V694L1370 1207V180H856ZM0 180V694L514 1207V180H0Z" />
<glyph unicode="(" glyph-name="null" horiz-adv-x="1551" d="M686 1372Q828 1372 953 1318T1171 1171T1318 953T1372 686Q1372 544 1318 419T1171 201T953 54T686 0Q544 0 419 54T201 201T54 419T0 686Q0 828 54 953T201 1171T419 1318T686 1372ZM1115 686L943
858V772H772V944H857L686 1115L514 944H600V772H429V858L257 686L429 515V601H600V429H514L686 257L857 429H772V601H943V515L1115 686Z" />
<glyph unicode=")" glyph-name="null" horiz-adv-x="1542" d="M1372 172L1200 0L600 601L343 344L0 1373L1029 1030L772 772L1372 172V172Z" />
<glyph unicode="*" glyph-name="null" horiz-adv-x="1551" d="M685 1370Q779 1370 866 1346T1030 1277T1169 1170T1276 1031T1345 868T1370 685Q1370 543 1316 419T1169 201T952 54T685 0Q543 0 419 54T201 201T54 418T0 685Q0 780 24 867T93 1031T200 1169T339
1276T503 1345T685 1370ZM770 943H856L685 1114L514 943H599V429H514L685 258L856 429H770V943Z" />
<glyph unicode="+" glyph-name="null" horiz-adv-x="1542" d="M1370 514H856V0H514V514H0V856H514V1370H856V856H1370V514Z" />
<glyph unicode="," glyph-name="null" horiz-adv-x="1669" d="M1286 644Q1322 644 1347 619T1372 558V215Q1372 180 1347 155T1286 130H1029V644V816Q1029 887 1002 949T929 1058T820 1132T686 1159Q615 1159 553 1132T444 1059T370 950T343 816V644V130H86Q50
130 25 155T0 215V558Q0 594 25 619T86 644H171V816Q171 922 211 1016T322 1179T485 1289T686 1330Q792 1330 886 1290T1049 1180T1159 1016T1200 816V644H1286V644Z" />
<glyph unicode="-" glyph-name="null" horiz-adv-x="1586" d="M0 560V903H1372V560H0V560Z" />
<glyph unicode="." glyph-name="null" horiz-adv-x="1576" d="M1370 1199H0V1370H1370V1199ZM856 856H0V1027H856V856ZM1370 510H0V681H1370V510ZM171 85Q171 50 146 25T85 0Q50 0 25 25T0 85Q0 121 25 146T85 171Q121 171 146 146T171 85ZM514 85Q514 67 507
52T489 25T461 7T427 0Q410 0 395 6T368 24T349 51T342 85Q342 103 349 118T367 146T394 164T427 171Q463 171 488 146T514 85ZM856 85Q856 50 831 25T770 0Q735 0 710 25T685 85Q685 121 710 146T770 171Q806 171 831 146T856 85Z" />
<glyph unicode="/" glyph-name="null" horiz-adv-x="1556" d="M1344 1344Q1370 1319 1370 1284T1344 1223L1170 1049Q1212 986 1229 915T1239 772T1201 633T1115 510L859 253Q796 190 718 159T556 127Q494 127 435 145T321 199L145 25Q133 12 118 6T85 0Q68 0
53 6T25 25Q0 50 0 85T25 145L199 321Q158 383 141 454T130 596T168 736T254 859L511 1115Q574 1178 652 1209T813 1241Q875 1241 935 1224T1050 1170L1224 1344Q1249 1370 1284 1370T1344 1344ZM1070 812Q1070 871 1044 923L914 793Q902 779 887 773T854 767Q837
767 822 773T793 793Q767 818 767 853T793 914L924 1044Q898 1056 870 1063T813 1070Q761 1070 715 1051T632 995L374 738Q338 701 319 655T299 556Q299 497 325 447L454 574Q479 599 513 599T574 574Q599 548 599 513T574 453L447 325Q499 299 556 299Q608 299
654 318T739 374L995 632Q1031 668 1050 714T1070 812Z" />
<glyph unicode="0" glyph-name="null" horiz-adv-x="1055" d="M429 1201Q376 1201 329 1181T247 1125T192 1043T172 943Q172 882 198 829T274 738Q347 683 380 625T423 516H435Q440 541 450 569T479 625T523 682T585 738Q634 775 660 828T687 943Q687 996 667
1043T611 1125T529 1180T429 1201ZM429 1373Q518 1373 596 1339T732 1247T824 1110T858 943Q858 837 812 749T688 601Q652 574 627 538T601 454V344H258V454Q258 502 233 538T171 601Q93 660 47 748T0 943Q0 1032 34 1110T126 1246T262 1339T429 1373ZM258 172H601V0H258V172Z"
/>
<glyph unicode="1" glyph-name="null" horiz-adv-x="1586" d="M1373 343H1030V0H0V1030H343V1373H1373V343ZM858 343H343V686H172V172H858V343ZM1201 1030H515V515H1201V1030Z" />
<glyph unicode="2" glyph-name="null" horiz-adv-x="1556" d="M685 856Q721 856 752 843T806 806T842 752T856 685Q856 649 843 618T806 564T752 528T685 514Q649 514 618 527T564 564T528 618T514 685Q514 721 527 752T564 806T618 842T685 856ZM1222 1104Q1291
1017 1330 911T1370 685Q1370 543 1316 419T1169 201T952 54T685 0Q543 0 419 54T201 201T54 418T0 685Q0 804 38 909T144 1103Q155 1095 167 1090T195 1084Q213 1084 228 1090T255 1109T274 1136T281 1170Q281 1184 276 1197T262 1221Q334 1278 419 1314T600 1363Q603
1330 627 1308T685 1285Q718 1285 741 1307T769 1362Q864 1351 948 1315T1104 1223Q1095 1213 1090 1200T1084 1170Q1084 1134 1109 1109T1169 1084Q1184 1084 1197 1089T1222 1104ZM685 342Q756 342 818 369T926 442T1000 551T1027 685Q1027 757 1001 819T926
927L685 1170L443 927Q396 881 369 819T342 685Q342 614 369 552T442 443T551 369T685 342Z" />
<glyph unicode="3" glyph-name="null" horiz-adv-x="1537" d="M685 1370L1370 685L1128 443L856 714V0H514V714Q463 663 414 615T327 528L242 443L0 685L685 1370Z" />
<glyph unicode="4" glyph-name="null" horiz-adv-x="1537" d="M1372 686L687 0L444 243L714 514H0V858H714Q663 909 615 957T529 1044L444 1129L687 1372L1372 686Z" />
<glyph unicode="5" glyph-name="null" horiz-adv-x="1537" d="M686 0L0 686L243 929L514 658V1372H858V658L1044 844L1129 929L1372 686L686 0Z" />
<glyph unicode="6" glyph-name="null" horiz-adv-x="1561" d="M0 685L684 1370L926 1128L656 856H1370V512H656L841 327L926 242L684 0L0 685Z" />
<glyph unicode="7" glyph-name="null" horiz-adv-x="1546" d="M514 601H256V430L0 686L256 944V772H514V601ZM856 772H1112V944L1370 686L1112 430V601H856V772Z" />
<glyph unicode="8" glyph-name="null" horiz-adv-x="702" d="M343 514V257H514L257 0L0 257H171V514H343V514ZM171 857V1115H0L257 1372L514 1115H343V857H171V857Z" />
<glyph unicode="9" glyph-name="null" horiz-adv-x="1522" d="M772 514V257H944L686 0L429 257H601V514H772V514ZM601 857V1115H429L686 1372L944 1115H772V857H601V857ZM515 600H257V429L0 686L257 943V772H515V600V600ZM858 772H1115V943L1372 686L1115 429V600H858V772V772Z"
/>
<glyph unicode=":" glyph-name="null" horiz-adv-x="1669" d="M1370 514V0H856L1052 196L856 393L977 514L1174 318L1370 514ZM318 1174L511 980L390 858L196 1052L0 856V1370H514L318 1174ZM318 196L514 0H0V514L196 318L393 514L514 393L318 196ZM1370 856L1174
1052L980 858L858 980L1052 1174L856 1370H1370V856Z" />
<glyph unicode=";" glyph-name="null" horiz-adv-x="1566" d="M856 0V514H1370L1174 318L1370 122L1249 0L1054 197L856 0ZM197 1054L3 1248L123 1369L318 1174L514 1370V856H0L197 1054ZM197 318L0 514H514V0L318 197L122 0L0 122L197 318ZM856 1370L1054 1174L1248
1369L1369 1248L1174 1054L1370 856H856V1370Z" />
<glyph unicode="&lt;" glyph-name="null" horiz-adv-x="1586" d="M858 343H772V86Q772 50 747 25T687 0Q651 0 626 25T601 86V343H515V514H601V1286Q601 1322 626 1347T687 1372Q722 1372 747 1347T772 1286V514H858V343ZM1373 857H1287V86Q1287 50 1262 25T1201
0Q1183 0 1168 6T1141 25T1122 52T1115 86V857H1030V1029H1115V1286Q1115 1304 1122 1319T1140 1347T1167 1365T1201 1372Q1237 1372 1262 1347T1287 1286V1029H1373V857ZM343 686H258V86Q258 50 233 25T172 0Q154 0 139 6T112 25T93 52T86 86V686H0V857H86V1286Q86
1304 93 1319T111 1347T138 1365T172 1372Q208 1372 233 1347T258 1286V857H343V686Z" />
<glyph unicode="=" glyph-name="null" horiz-adv-x="1551" d="M686 1372Q828 1372 953 1318T1171 1171T1318 953T1372 686Q1372 544 1318 419T1171 201T953 54T686 0Q544 0 419 54T201 201T54 419T0 686Q0 828 54 953T201 1171T419 1318T686 1372ZM1029 772H772V1029H600V772H343V600H600V343H772V600H1029V772Z"
/>
<glyph unicode="&gt;" glyph-name="null" horiz-adv-x="1581" d="M1370 1199H0V1370H1370V1199ZM856 856H0V1027H856V856ZM1370 342H0V514H1370V342ZM1027 0H0V171H1027V0ZM1370 86Q1370 50 1345 25T1285 0Q1249 0 1224 25T1199 86Q1199 121 1224 146T1285 171Q1320
171 1345 146T1370 86Z" />
<glyph unicode="?" glyph-name="null" horiz-adv-x="1576" d="M342 342V685L514 856L685 685L1027 1027L1370 685V342H342ZM1370 171L1199 0H171H0V171V1199L171 1370V171H1370Z" />
<glyph unicode="@" glyph-name="null" horiz-adv-x="1546" d="M1029 343Q987 343 953 362T894 414Q850 380 798 361T686 342Q615 342 553 369T444 442T370 551T343 685Q343 756 370 818T443 927T552 1001T686 1028H1029V515H1168L1169 513Q1184 554 1192 597T1201
686Q1201 792 1161 886T1050 1050T886 1160T686 1201Q579 1201 486 1161T322 1050T212 886T171 686Q171 580 211 487T322 323T485 213T686 172Q793 172 886 212T1050 323L1171 201Q1077 107 953 54T686 0Q591 0 504 24T340 94T201 201T94 340T25 503T0 686Q0 828
54 953T201 1171T419 1319T686 1373Q828 1373 953 1319T1171 1172T1318 953T1372 686Q1372 592 1348 506T1280 343H1029ZM857 856H686Q651 856 620 843T565 806T528 751T514 685Q514 649 527 618T564 564T619 527T686 513Q721 513 752 526T806 563T843 618T857
685V772V856Z" />
<glyph unicode="A" glyph-name="null" horiz-adv-x="1591" d="M1026 1201H1373V1029H1026H854H511H340H0V1201H340V1372H511V1201H854V1372H1026V1201ZM1201 343H172V514H1201V343V343ZM1201 686H172V858H1201V686V686ZM1030 0H172V171H1201L1030 0V0Z" />
<glyph unicode="B" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="C" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="D" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="E" glyph-name="null" horiz-adv-x="1502" d="M515 1029H857V857H515V1029ZM1371 856H1200V0H172Q136 0 105 13T51 50T14 105T0 172V1201Q0 1237 13 1268T50 1322T105 1358T172 1372H1200V1200H1373L1200 1027L1371 856ZM1029 1201H343V172H1029V1201Z" />
<glyph unicode="F" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="G" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="H" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="I" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="J" glyph-name="null" horiz-adv-x="1605" d="M1111 847Q1163 837 1210 814T1293 750T1349 651T1370 514Q1370 421 1341 356T1263 250T1153 190T1027 171H856Q821 171 790 158T735 121T699 67T685 0Q614 0 552 27T443 100T369 209T342 342V514Q342
560 351 599H514Q518 599 521 598T529 596Q514 563 514 514V342Q514 300 532 265T582 206Q629 269 700 305T856 342H1027Q1070 342 1099 352T1148 377T1177 412T1192 450T1198 486T1199 514Q1199 531 1197 556T1183 606T1146 652T1074 681Q1091 719 1101 760T1111
847ZM342 1199Q278 1199 243 1180T192 1133T174 1076T171 1027Q171 1011 173 983T192 926T243 877T342 856H514Q598 856 669 819T788 719Q819 743 837 778T856 856V1027Q856 1083 838 1117T794 1169T739 1193T685 1199H342ZM685 1370Q749 1370 810 1350T920 1287T997
1180T1027 1027V856Q1027 785 1000 723T927 615T818 541T685 514Q685 549 672 580T635 634T580 671T514 685H342Q278 685 217 704T107 764T30 870T0 1027Q0 1122 29 1187T107 1293T216 1352T342 1370H685Z" />
<glyph unicode="K" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="L" glyph-name="null" horiz-adv-x="1325" d="M600 1370Q688 1370 766 1337T902 1245T993 1108T1027 941V256Q1027 203 1007 157T952 75T871 20T771 0H258Q204 0 157 20T75 75T20 156T0 256V856H171V941Q171 1030 205 1108T297 1244T433 1336T600
1370ZM342 856H856V941Q856 995 836 1042T781 1124T700 1179T600 1199Q547 1199 500 1179T418 1124T363 1042T342 941V856ZM771 171Q789 171 804 178T831 196T849 223T856 256V685H171V256Q171 239 178 224T196 197T224 178T258 171H771ZM600 427Q600 410 594 395T575
368T548 349T514 342Q496 342 481 349T454 367T436 394T429 427Q429 445 435 461T453 488T480 507T514 514Q550 514 575 489T600 427Z" />
<glyph unicode="M" glyph-name="null" horiz-adv-x="1669" d="M1372 1209V180H0V1209H1372ZM306 1037L625 718Q651 693 686 693T747 718L1066 1037H306ZM1200 351V929L868 597Q830 559 783 540T686 521Q636 521 589 540T504 597L171 929V351H1200Z" />
<glyph unicode="N" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="O" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="P" glyph-name="null" horiz-adv-x="1586" d="M1272 1271Q1322 1221 1347 1158T1372 1029T1347 900T1272 786L486 0H0L1 486L787 1271Q838 1322 901 1347T1030 1372Q1096 1372 1158 1347T1272 1271ZM1151 907L908 1150L173 415V343H343V171H415L1151 907Z" />
<glyph unicode="Q" glyph-name="null" horiz-adv-x="1596" d="M687 1037Q286 1037 199 826Q180 781 175 732T173 634T188 537T215 447Q251 472 287 487T368 510T469 520T601 523H1169Q1182 561 1191 606T1201 694Q1201 736 1196 777T1173 857T1122 928T1031 985T890
1023T687 1037ZM687 1209Q773 1209 857 1201T1017 1171T1159 1112T1271 1018T1346 881T1373 694Q1373 629 1359 568T1328 458Q1309 402 1284 351H601Q537 351 492 350T414 345T355 330T303 300T246 252T172 180Q140 212 106 273T45 413T7 580T5 758T57 928T177
1072T382 1172T687 1209Z" />
<glyph unicode="R" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="S" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="T" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="U" glyph-name="null" horiz-adv-x="1707" />
<glyph unicode="V" glyph-name="null" horiz-adv-x="1581" d="M342 351Q271 351 209 378T101 451T27 560T0 694Q0 765 27 827T100 935T209 1009T342 1036V351ZM514 1036L856 1207V180L514 351V1036ZM1370 607H1027V779H1370V607Z" />
<glyph unicode="W" glyph-name="null" horiz-adv-x="1571" d="M1167 514Q1163 501 1158 489T1148 464L1291 322L1048 79L906 222Q893 217 881 214T856 206V0H514V206Q501 210 489 213T464 222L322 79L79 322L223 464Q217 477 212 489T203 514H0V856H203Q207 869
212 881T223 906L79 1048L322 1291L464 1147Q477 1153 489 1156T514 1164V1370H856V1164Q869 1160 881 1157T906 1147L1048 1291L1291 1048L1148 906Q1153 893 1158 881T1167 856H1370V514H1167ZM685 510Q721 510 752 523T806 560T842 614T856 681Q856 716 843
747T806 801T752 838T685 852Q649 852 618 839T564 802T528 747T514 681Q514 645 527 614T564 560T618 524T685 510Z" />
<glyph unicode="X" glyph-name="null" horiz-adv-x="1551" d="M686 1372Q828 1372 953 1318T1171 1171T1318 953T1372 686Q1372 544 1318 419T1171 201T953 54T686 0Q544 0 419 54T201 201T54 419T0 686Q0 828 54 953T201 1171T419 1318T686 1372ZM807 686L1025
904L904 1025L686 807L468 1025L347 904L565 686L347 468L468 346L686 565L904 346L1025 468L807 686Z" />
<glyph unicode="Y" glyph-name="null" horiz-adv-x="1551" d="M686 1373Q828 1373 953 1319T1171 1172T1318 953T1372 686Q1372 591 1348 504T1279 340T1172 202T1033 94T869 25T686 0Q591 0 504 24T340 94T201 201T94 340T25 503T0 686Q0 828 54 953T201 1171T419
1319T686 1373ZM1113 904L992 1025L580 612L385 807L264 686L580 370L1113 904Z" />
<glyph unicode="Z" glyph-name="null" horiz-adv-x="972" d="M426 985Q426 968 414 956T385 943Q368 943 356 955T344 985Q344 1002 356 1014T385 1026Q402 1026 414 1014T426 985ZM599 1370Q635 1370 660 1345T685 1284V342Q685 271 658 209T585 101T476 27T342
0Q271 0 209 27T101 100T27 209T0 342V1284Q0 1320 25 1345T85 1370H599ZM215 514Q232 514 244 526T256 555Q256 572 244 584T215 596Q198 596 186 584T174 555Q174 538 186 526T215 514ZM427 342Q445 342 461 349T488 367T507 394T514 427Q514 463 489 488T427
514Q410 514 395 507T368 489T349 461T342 427Q342 392 367 367T427 342ZM514 1199H171V685H258Q258 720 283 745T344 770Q380 770 405 745T430 685H514V1199Z" />
<glyph unicode="[" glyph-name="null" horiz-adv-x="1360" d="M1023 1110Q1109 1024 1154 915T1199 685Q1199 602 1178 526T1117 383T1024 261T902 167T759 107T600 85V0L429 171L600 342V256Q688 256 766 290T902 382T993 518T1027 685Q1027 772 996 849T903
988L1023 1110ZM600 1027V1112Q511 1112 433 1079T297 987T205 851T171 685Q171 598 203 521T297 382L177 260Q91 346 46 455T0 685Q0 767 21 843T82 987T176 1108T297 1202T440 1262T600 1284V1370L771 1199L600 1027Z" />
<glyph unicode="\" glyph-name="null" horiz-adv-x="1055" d="M429 1200Q377 1200 330 1181T247 1125Q210 1088 191 1042T171 943Q171 892 190 845T247 762Q250 759 266 742T308 695T364 623T429 529Q462 581 493 623T550 695T592 742T612 763Q647 798 666 845T686
943Q686 995 667 1041T611 1125Q574 1162 527 1181T429 1200ZM429 1372Q511 1372 590 1341T732 1246Q795 1183 826 1104T857 943T826 782T732 640Q647 552 580 449Q551 405 524 354T476 245T442 126T429 0Q429 64 416 126T382 245T333 353T277 449Q210 552 126
640Q63 703 32 782T0 943T31 1104T126 1246Q189 1309 267 1340T429 1372ZM514 943Q514 925 508 910T490 883T463 864T429 857Q411 857 396 864T368 882T350 909T343 943Q343 979 368 1004T429 1029Q464 1029 489 1004T514 943Z" />
<glyph unicode="]" glyph-name="null" horiz-adv-x="1571" d="M253 980Q214 918 193 848T172 702Q172 592 213 496T327 327T495 214T701 172Q777 172 847 193T980 253Q836 267 710 328T486 486T328 709T253 980ZM508 1373Q467 1302 444 1223T421 1057Q421 925
471 810T607 608T808 471T1056 421Q1144 421 1223 444T1372 508Q1340 398 1277 305T1125 145T929 39T701 0Q604 0 515 25T347 95T205 205T96 348T25 515T0 702Q0 822 38 929T144 1125T305 1277T508 1373Z" />
<glyph unicode="^" glyph-name="null" horiz-adv-x="1551" d="M686 0Q591 0 504 24T340 94T201 201T94 340T25 503T0 686Q0 828 54 953T201 1171T419 1319T686 1373Q828 1373 953 1319T1171 1172T1318 953T1372 686Q1372 591 1348 504T1279 340T1172 202T1033
94T869 25T686 0ZM343 686L685 345V601H1029V772H685V1030L343 686Z" />
<glyph unicode="_" glyph-name="null" horiz-adv-x="1551" d="M685 1370Q827 1370 951 1316T1169 1169T1316 952T1370 685Q1370 543 1316 419T1169 201T952 54T685 0Q543 0 419 54T201 201T54 418T0 685Q0 827 54 951T201 1169T418 1316T685 1370ZM1027 770H342V599H1027V770Z"
/>
<glyph unicode="`" glyph-name="null" horiz-adv-x="1551" d="M687 1372Q782 1372 869 1348T1033 1279T1171 1172T1279 1033T1348 869T1373 686Q1373 591 1349 504T1279 340T1172 201T1033 94T869 25T687 0Q545 0 420 54T202 201T54 419T0 686Q0 828 54 953T201
1171T420 1318T687 1372ZM687 1200Q580 1200 487 1160T323 1049T213 886T172 686Q172 602 197 527T268 388L984 1104Q921 1149 846 1174T687 1200ZM687 171Q793 171 886 211T1050 322T1160 485T1201 686Q1201 769 1176 844T1105 983L389 267Q452 222 527 197T687
171Z" />
<glyph unicode="a" glyph-name="null" horiz-adv-x="1674" d="M1373 0H0V1201H172V172H1201V1201H1373V0ZM429 686H258V858H429V686ZM772 686H601V858H772V686ZM1115 686H944V858H1115V686ZM429 343H258V515H429V343ZM772 343H601V515H772V343ZM944 343V515H1115L944
343ZM343 1115V1287Q343 1305 350 1320T368 1347T395 1365T429 1372Q465 1372 490 1347T515 1287V1115Q515 1097 509 1082T490 1055T463 1036T429 1029Q411 1029 396 1036T369 1054T350 1081T343 1115ZM858 1115V1287Q858 1322 883 1347T944 1372Q962 1372 977
1366T1004 1348T1023 1321T1030 1287V1115Q1030 1097 1023 1082T1005 1055T978 1036T944 1029Q926 1029 911 1036T883 1054T865 1081T858 1115Z" />
<glyph unicode="b" glyph-name="null" horiz-adv-x="1561" d="M770 685L1027 514L0 0L599 514L342 685L1370 1370L770 685Z" />
<glyph unicode="c" glyph-name="null" horiz-adv-x="1551" d="M685 1199Q578 1199 485 1159T322 1049T212 885T171 685Q171 578 211 485T321 322T484 212T685 171Q791 171 885 211T1048 321T1158 484T1199 685Q1199 791 1159 885T1049 1048T885 1158T685 1199ZM685
1370Q827 1370 951 1316T1169 1169T1316 952T1370 685Q1370 543 1316 419T1169 201T952 54T685 0Q543 0 419 54T201 201T54 418T0 685Q0 827 54 951T201 1169T418 1316T685 1370ZM796 453L629 621Q615 633 607 649T599 685V1027H771V721L918 574L796 453Z" />
<glyph unicode="d" glyph-name="null" horiz-adv-x="1674" d="M1373 943V0L1033 284L690 0L346 284L0 2V1372H945L1373 943ZM1202 689H687V1203H172V345L347 483L690 200L1028 480Q1029 481 1030 481T1032 483L1033 484L1202 345V689ZM1202 860L859 1203V860H1202Z" />
<glyph unicode="e" glyph-name="null" horiz-adv-x="1497" d="M1200 1372V0H171Q136 0 105 13T50 50T14 104T0 171V1200Q0 1236 13 1267T50 1321T104 1358T171 1372H1200ZM1029 1200H858V855L685 1027L514 856V1200H343V171H1029V1200Z" />
<glyph unicode="f" glyph-name="null" horiz-adv-x="1532" d="M862 1370Q967 1370 1059 1330T1221 1222T1330 1061T1370 863Q1370 758 1330 666T1221 504T1060 395T862 355Q811 355 765 365T673 392L281 0L0 282L392 674Q375 718 364 765T353 863Q353 968 393
1060T502 1221T664 1330T862 1370ZM862 526Q932 526 993 552T1100 624T1172 731T1199 863Q1199 932 1173 993T1100 1101T993 1173T862 1200Q793 1200 732 1174T624 1101T552 994T525 863Q525 793 551 732T624 625T731 553T862 526Z" />
<glyph unicode="g" glyph-name="null" horiz-adv-x="1546" d="M500 1000Q500 973 490 949T462 908T421 880T370 870Q342 870 318 880T275 907T247 949T236 1000Q236 1027 246 1051T275 1093T317 1122T370 1133Q397 1133 420 1122T461 1093T489 1051T500 1000ZM569
1370L1370 569H801V0L0 801V1370H569ZM151 1215V863Q159 855 188 827T260 756T352 663T455 560T557 457T647 366V719H1000Q961 759 911 809T809 912T706 1016T612 1109T541 1179T503 1215H151Z" />
<glyph unicode="h" glyph-name="null" horiz-adv-x="1581" d="M992 1109Q959 1109 929 1094T876 1062Q849 1042 826 1016L687 867L547 1016Q523 1042 497 1062Q474 1079 444 1094T382 1109Q342 1109 307 1095T244 1057T198 1000T174 929L687 341L1199 929Q1193
967 1175 1000T1130 1057T1067 1095T992 1109ZM992 1280Q1071 1280 1140 1250T1261 1168T1343 1047T1373 899V867L687 80L0 867V899Q0 978 30 1047T112 1168T233 1250T382 1280Q479 1280 556 1234T687 1115Q739 1188 817 1234T992 1280Z" />
<glyph unicode="i" glyph-name="null" horiz-adv-x="859" d="M85 686Q121 686 146 661T171 601V258Q171 222 146 197T85 172H0V0H686V172H600Q582 172 567 178T540 197T521 224T514 258V858H0V686H85ZM514 1201Q514 1165 501 1134T464 1080T409 1043T343 1029Q307
1029 276 1042T222 1079T185 1134T171 1201Q171 1237 184 1268T221 1322T276 1359T343 1373Q378 1373 409 1360T463 1323T500 1268T514 1201Z" />
<glyph unicode="j" glyph-name="null" horiz-adv-x="1600" d="M1027 856Q1091 856 1153 838T1263 780T1340 674T1370 514Q1370 422 1341 357T1263 251T1153 190T1027 171H856Q821 171 790 158T735 121T699 67T685 0Q614 0 552 27T443 100T369 209T342 342V514Q342
565 353 607T382 685H342Q278 685 217 704T107 764T30 870T0 1027Q0 1122 29 1187T107 1293T216 1352T342 1370H685Q749 1370 810 1350T920 1288T997 1181T1027 1027V856ZM514 856Q598 856 669 819T788 719Q819 743 837 778T856 856V1027Q856 1083 839 1117T795
1169T739 1193T685 1199H342Q278 1199 243 1180T192 1133T174 1077T171 1027Q171 1011 173 983T192 926T243 877T342 856H514ZM1027 342Q1070 342 1099 352T1148 377T1177 412T1192 450T1198 486T1199 514Q1199 533 1197 562T1178 619T1126 665T1027 685H980Q958
647 927 616T858 562T776 527T685 514Q685 564 660 603T592 664Q562 646 538 610T514 514V342Q514 300 532 265T582 206Q630 269 700 305T856 342H1027ZM1015 771Q1014 768 1013 765T1011 759Q1012 762 1013 765T1015 771Z" />
<glyph unicode="k" glyph-name="null" horiz-adv-x="1527" d="M941 1199Q888 1199 842 1179T761 1123T706 1041T685 941Q685 930 687 920T692 893L706 804L644 743L171 270V171H342V342H514V514H685V585L736 633L743 644L808 706L897 688Q910 686 920 686T941
685Q995 685 1042 705T1124 760T1179 841T1199 941Q1199 994 1179 1041T1124 1123T1042 1178T941 1199ZM941 1370Q1030 1370 1108 1337T1244 1245T1336 1108T1370 941Q1370 853 1337 775T1245 639T1108 548T941 514Q921 514 903 515T863 521L856 514V342H685V171H514V0H0V342L521
863Q517 884 516 902T514 941Q514 1030 547 1108T639 1244T775 1336T941 1370ZM1027 941Q1027 905 1002 881T941 856Q905 856 881 880T856 941Q856 977 880 1002T941 1027Q977 1027 1002 1002T1027 941Z" />
<glyph unicode="l" glyph-name="null" horiz-adv-x="1306" d="M601 1372Q689 1372 767 1338T903 1246T995 1110T1029 943V257Q1029 204 1009 157T954 75T872 20T772 0H257Q204 0 157 20T75 75T20 157T0 257V857H858V943Q858 996 838 1043T782 1125T701 1180T601
1200Q548 1200 501 1180T419 1125T364 1043T343 943H172Q172 1031 205 1109T297 1246T434 1338T601 1372ZM772 171Q790 171 805 177T832 196T851 223T858 257V686H172V257Q172 221 197 196T257 171H772ZM600 428Q600 393 575 368T515 343Q479 343 454 368T429 428Q429
464 454 489T515 514Q550 514 575 489T600 428Z" />
<glyph unicode="m" glyph-name="null" horiz-adv-x="1669" d="M689 718L0 1042V1209H1372V1041L689 718ZM690 528L1372 852V180H0V852L690 528Z" />
<glyph unicode="n" glyph-name="null" horiz-adv-x="1325" d="M685 1370Q756 1370 818 1343T926 1270T1000 1161T1027 1027V342Q1027 271 1000 209T927 101T818 27T685 0H342Q271 0 209 27T101 100T27 209T0 342V1027Q0 1098 27 1160T100 1269T209 1343T342 1370H685ZM514
82Q550 82 575 108T601 171Q601 207 576 233T514 259Q495 259 479 252T451 233T432 205T425 171Q425 134 450 108T514 82ZM856 1027Q856 1063 843 1094T806 1148T752 1185T685 1199H342Q307 1199 276 1186T221 1149T185 1094T171 1027V342H856V1027Z" />
<glyph unicode="o" glyph-name="null" horiz-adv-x="1669" d="M1370 0H0V856H1370V0ZM770 1370H1199L1370 1027H770V1370ZM599 1027H0L171 1370H599V1027Z" />
<glyph unicode="p" glyph-name="null" horiz-adv-x="1586" d="M1272 1272Q1322 1222 1347 1159T1372 1030T1347 901T1272 787L486 0H0L2 486L787 1272Q838 1323 901 1347T1030 1372Q1096 1372 1158 1348T1272 1272ZM1149 906L907 1149L180 422Q205 444 235 454T297
465T358 452T412 416Q437 390 449 359T462 294T450 229T412 172H415L1149 906Z" />
<glyph unicode="q" glyph-name="null" horiz-adv-x="1581" d="M429 1119Q376 1119 329 1099T247 1043T192 961T171 861V433Q171 391 190 355T240 295Q288 358 359 395T514 433H857Q928 433 990 460T1099 533T1173 642T1200 776Q1200 847 1173 909T1100 1018T991
1092T857 1119H429ZM857 1290Q964 1290 1058 1250T1221 1140T1331 976T1372 776Q1372 669 1332 576T1222 412T1058 302T857 261H514Q479 261 448 248T393 211T357 156T343 90Q272 90 210 117T101 190T27 299T0 433V861Q0 950 33 1028T125 1164T262 1256T429 1290H857Z"
/>
<glyph unicode="r" glyph-name="null" horiz-adv-x="1669" d="M342 171Q342 136 329 105T292 50T238 14T171 0Q136 0 105 13T50 50T14 104T0 171Q0 207 13 238T50 292T104 328T171 342Q207 342 238 329T292 292T328 238T342 171ZM258 685Q347 685 425 652T561
560T652 423T686 256H515Q515 310 495 357T440 439T358 494T258 514V685ZM256 1027Q362 1027 461 1000T645 922T801 802T922 646T999 461T1027 256H856Q856 339 835 415T774 559T681 680T559 774T416 834T256 856V1027ZM256 1370Q409 1370 551 1330T817 1218T1043
1044T1217 818T1330 552T1370 256H1199Q1199 386 1165 506T1070 732T922 923T731 1070T506 1165T256 1199V1370Z" />
<glyph unicode="s" glyph-name="null" horiz-adv-x="1591" d="M1112 0L685 329L256 0L422 530L0 856H514L685 1370L856 856H1370L947 529L1112 0Z" />
<glyph unicode="t" glyph-name="null" horiz-adv-x="1551" d="M1372 1029H1201V257Q1201 204 1181 158T1125 76T1043 21T943 0H429Q376 0 329 20T247 76T192 157T171 257V1029H0V1201H171H343Q343 1237 356 1268T393 1322T447 1358T514 1372H857Q893 1372 924
1359T978 1322T1015 1268T1029 1201H1201H1372V1029ZM1029 1029H343V257Q343 239 350 224T368 197T395 179T429 172H943Q979 172 1004 197T1029 257V1029ZM600 429Q600 411 594 396T575 369T548 350T514 343Q496 343 481 350T454 368T436 395T429 429Q429 447 435
462T453 489T480 508T514 515Q532 515 547 508T575 490T593 463T600 429ZM600 772Q600 754 594 739T575 712T548 693T514 686Q496 686 481 693T454 711T436 738T429 772Q429 790 435 805T453 832T480 851T514 858Q532 858 547 851T575 833T593 806T600 772ZM943
429Q943 411 937 396T918 369T891 350T857 343Q839 343 824 350T797 368T779 395T772 429Q772 447 778 462T796 489T823 508T857 515Q875 515 890 508T918 490T936 463T943 429ZM943 772Q943 754 937 739T918 712T891 693T857 686Q839 686 824 693T797 711T779
738T772 772Q772 790 778 805T796 832T823 851T857 858Q875 858 890 851T918 833T936 806T943 772Z" />
<glyph unicode="u" glyph-name="null" horiz-adv-x="1311" d="M514 686Q407 686 314 646T151 536T41 372T0 171Q0 136 13 105T50 50T104 14T171 0H857Q893 0 924 13T978 50T1015 104T1029 171Q1029 278 989 372T878 535T714 645T514 686ZM771 1115Q771 1062 751
1015T696 933T614 878T514 857Q461 857 414 877T332 933T277 1015T257 1115Q257 1168 277 1215T332 1297T414 1352T514 1372Q567 1372 614 1352T696 1297T751 1215T771 1115Z" />
<glyph unicode="v" glyph-name="null" horiz-adv-x="1556" d="M342 361Q271 361 209 388T101 461T27 570T0 704Q0 776 27 838T100 947T209 1019T342 1046V361ZM514 1046L856 1217V190L514 361V1046ZM1027 361V532Q1038 532 1048 534T1069 539Q1097 547 1121 562T1162
599T1189 647T1199 704Q1199 733 1189 760T1162 809T1121 847T1069 871Q1058 874 1048 874T1027 875V1046Q1048 1046 1068 1043T1110 1035Q1167 1021 1215 990T1297 915T1351 817T1370 704Q1370 645 1351 591T1298 494T1215 418T1110 371Q1070 361 1027 361Z" />
<glyph unicode="w" glyph-name="null" horiz-adv-x="1556" d="M1164 514Q1160 501 1156 490T1147 467L1230 263L1110 141L904 223Q893 218 881 214T856 204L771 0H600L514 203Q490 210 464 223L262 140L141 260L222 463Q210 488 201 514L0 599V770L201 856Q206
869 211 882T222 907L138 1108L260 1229L463 1148Q476 1153 488 1158T512 1167L597 1370H769L856 1167Q869 1162 880 1158T903 1147L1107 1232L1229 1110L1145 904Q1152 893 1156 882T1164 858L1370 773V601L1164 514ZM684 429Q737 429 783 449T865 504T920 585T940
685Q940 738 920 785T865 867T784 922T684 943Q630 943 583 923T501 867T446 785T426 685Q426 632 446 586T501 504T583 449T684 429Z" />
<glyph unicode="x" glyph-name="null" horiz-adv-x="1473" d="M1200 325L960 85L600 445L240 85L0 325L360 685L0 1045L240 1285L600 925L960 1285L1200 1045L839 685L1200 325V325Z" />
<glyph unicode="y" glyph-name="null" horiz-adv-x="1560" d="M512 160L0 672L244 917L512 649L1128 1265L1372 1020L512 160V160V160Z" />
<glyph unicode="z" glyph-name="null" horiz-adv-x="982" d="M599 1370Q635 1370 660 1345T685 1284V342Q685 271 658 209T585 101T476 27T342 0Q271 0 209 27T101 100T27 209T0 342V1284Q0 1320 25 1345T85 1370H599ZM427 342Q445 342 461 349T488 367T507 394T514
427Q514 463 489 488T427 514Q410 514 395 507T368 489T349 461T342 427Q342 392 367 367T427 342ZM514 1199H171V685H258Q258 720 283 745T344 770Q380 770 405 745T430 685H514V1199Z" />
<glyph unicode="{" glyph-name="null" horiz-adv-x="1551" d="M200 200Q103 298 52 422T0 685Q0 827 54 951T201 1169T418 1316T685 1370L770 1284L685 1199Q578 1199 485 1159T322 1049T212 885T171 685Q171 582 210 488T322 322L216 308L200 200ZM685 0L599
85L685 171Q791 171 885 211T1048 321T1158 484T1199 685Q1199 788 1160 881T1048 1048L1154 1062L1169 1170Q1267 1072 1318 947T1370 685Q1370 543 1316 419T1169 201T952 54T685 0Z" />
<glyph unicode="|" glyph-name="null" horiz-adv-x="1542" d="M1372 1029Q1372 981 1359 937T1323 854T1267 784T1195 730Q1196 719 1197 709T1199 687Q1199 580 1159 487T1048 323T884 213T684 172Q605 172 533 195T398 260L0 0L261 395Q218 458 194 531T170
687Q170 793 210 887T320 1050T483 1160T684 1201Q696 1201 708 1200T731 1197Q753 1236 784 1268T854 1323T936 1359T1029 1372Q1100 1372 1162 1345T1271 1272T1345 1163T1372 1029ZM684 344Q755 344 817 371T926 444T1000 553T1027 686Q1004 686 982 689T939
699L804 564Q779 539 748 527T683 514T619 526T562 564Q537 589 525 620T512 685T524 750T562 807L698 943Q693 963 690 984T686 1029V1031V1030H684Q613 1030 551 1003T442 930T368 821T341 687Q341 616 368 554T441 445T550 371T684 344ZM1029 857Q1064 857 1095
870T1149 907T1186 962T1200 1029Q1200 1064 1187 1095T1150 1149T1095 1186T1029 1200Q993 1200 962 1187T908 1150T871 1095T857 1029Q857 993 870 962T907 908T962 871T1029 857Z" />
<glyph unicode="}" glyph-name="null" horiz-adv-x="1537" d="M1029 686Q1029 615 1002 553T929 444T820 370T686 343Q615 343 553 370T444 443T370 552T343 686Q343 757 370 819T443 928T552 1002T686 1029Q757 1029 819 1002T928 929T1002 820T1029 686ZM686
1230Q641 1230 600 1223T517 1201H514L686 1373L857 1201H855Q815 1215 773 1222T686 1230ZM686 143Q731 143 773 150T855 172H857L686 0L514 172H517Q558 158 599 151T686 143ZM1230 686Q1230 731 1222 773T1200 855V858L1372 686L1200 515V517Q1214 558 1222
599T1230 686ZM142 686Q142 641 150 600T171 517V515L0 686L171 858V855Q158 815 150 773T142 686ZM1071 302Q1103 334 1126 369T1169 442L1171 444V201H929L930 203Q968 223 1003 246T1071 302ZM301 1071Q269 1039 246 1004T203 931L201 929V1172H444L441 1170Q403
1150 368 1127T301 1071ZM301 302Q333 270 368 247T441 203L444 201H201V444L203 442Q222 404 245 369T301 302ZM1071 1071Q1039 1103 1004 1126T930 1170L929 1172H1171V929L1169 931Q1150 969 1127 1004T1071 1071Z" />
<glyph unicode="~" glyph-name="null" horiz-adv-x="1586" d="M1244 759L1367 636L1247 515L1123 638L485 0H169L0 171V481L640 1122L512 1249L633 1370L760 1243L786 1267Q837 1318 899 1342T1027 1367Q1093 1367 1156 1343T1270 1267Q1320 1217 1345 1154T1370
1026T1345 897T1270 784L1244 759ZM1003 759L762 1000L208 447Q253 445 295 429T373 378Q410 341 426 294T441 199L1003 759Z" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="-59" />
<hkern g1="null" g2="null" k="-18" />
<hkern g1="null" g2="null" k="-25" />
<hkern g1="null" g2="null" k="59" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="51" />
<hkern g1="null" g2="null" k="66" />
<hkern g1="null" g2="null" k="-47" />
<hkern g1="null" g2="null" k="-47" />
<hkern g1="null" g2="null" k="20" />
<hkern g1="null" g2="null" k="-25" />
<hkern g1="null" g2="null" k="-12" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="29" />
<hkern g1="null" g2="null" k="121" />
<hkern g1="null" g2="null" k="-25" />
<hkern g1="null" g2="null" k="47" />
<hkern g1="null" g2="null" k="57" />
<hkern g1="null" g2="null" k="55" />
<hkern g1="null" g2="null" k="59" />
<hkern g1="null" g2="null" k="57" />
<hkern g1="null" g2="null" k="72" />
<hkern g1="null" g2="null" k="111" />
<hkern g1="null" g2="null" k="51" />
<hkern g1="null" g2="null" k="-16" />
<hkern g1="null" g2="null" k="51" />
<hkern g1="null" g2="null" k="55" />
<hkern g1="null" g2="null" k="174" />
<hkern g1="null" g2="null" k="111" />
<hkern g1="null" g2="null" k="178" />
<hkern g1="null" g2="null" k="86" />
<hkern g1="null" g2="null" k="31" />
<hkern g1="null" g2="null" k="131" />
<hkern g1="null" g2="null" k="41" />
<hkern g1="null" g2="null" k="-12" />
<hkern g1="null" g2="null" k="41" />
<hkern g1="null" g2="null" k="53" />
<hkern g1="null" g2="null" k="70" />
<hkern g1="null" g2="null" k="-45" />
<hkern g1="null" g2="null" k="-53" />
<hkern g1="null" g2="null" k="-45" />
<hkern g1="null" g2="null" k="47" />
<hkern g1="null" g2="null" k="78" />
<hkern g1="null" g2="null" k="74" />
<hkern g1="null" g2="null" k="121" />
<hkern g1="null" g2="null" k="14" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="16" />
<hkern g1="null" g2="null" k="-39" />
<hkern g1="null" g2="null" k="20" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="16" />
<hkern g1="null" g2="null" k="39" />
<hkern g1="null" g2="null" k="33" />
<hkern g1="null" g2="null" k="47" />
<hkern g1="null" g2="null" k="33" />
<hkern g1="null" g2="null" k="115" />
<hkern g1="null" g2="null" k="102" />
<hkern g1="null" g2="null" k="156" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="92" />
<hkern g1="null" g2="null" k="94" />
<hkern g1="null" g2="null" k="-16" />
<hkern g1="null" g2="null" k="94" />
<hkern g1="null" g2="null" k="53" />
<hkern g1="null" g2="null" k="57" />
<hkern g1="null" g2="null" k="74" />
<hkern g1="null" g2="null" k="70" />
<hkern g1="null" g2="null" k="63" />
<hkern g1="null" g2="null" k="61" />
<hkern g1="null" g2="null" k="66" />
<hkern g1="null" g2="null" k="51" />
<hkern g1="null" g2="null" k="53" />
<hkern g1="null" g2="null" k="-8" />
<hkern g1="null" g2="null" k="76" />
<hkern g1="null" g2="null" k="-29" />
<hkern g1="null" g2="null" k="76" />
<hkern g1="null" g2="null" k="51" />
<hkern g1="null" g2="null" k="66" />
<hkern g1="null" g2="null" k="57" />
<hkern g1="null" g2="null" k="51" />
<hkern g1="null" g2="null" k="49" />
<hkern g1="null" g2="null" k="55" />
<hkern g1="null" g2="null" k="45" />
<hkern g1="null" g2="null" k="49" />
<hkern g1="null" g2="null" k="-8" />
<hkern g1="null" g2="null" k="49" />
<hkern g1="null" g2="null" k="53" />
<hkern g1="null" g2="null" k="57" />
<hkern g1="null" g2="null" k="70" />
<hkern g1="null" g2="null" k="123" />
<hkern g1="null" g2="null" k="49" />
<hkern g1="null" g2="null" k="121" />
<hkern g1="null" g2="null" k="92" />
<hkern g1="null" g2="null" k="98" />
<hkern g1="null" g2="null" k="109" />
<hkern g1="null" g2="null" k="117" />
<hkern g1="null" g2="null" k="111" />
<hkern g1="null" g2="null" k="106" />
<hkern g1="null" g2="null" k="115" />
<hkern g1="null" g2="null" k="80" />
<hkern g1="null" g2="null" k="86" />
<hkern g1="null" g2="null" k="27" />
<hkern g1="null" g2="null" k="25" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="35" />
<hkern g1="null" g2="null" k="14" />
<hkern g1="null" g2="null" k="8" />
<hkern g1="null" g2="null" k="25" />
<hkern g1="null" g2="null" k="-10" />
<hkern g1="null" g2="null" k="-10" />
<hkern g1="null" g2="null" k="12" />
<hkern g1="null" g2="null" k="25" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="25" />
<hkern g1="null" g2="null" k="37" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="-45" />
<hkern g1="null" g2="null" k="12" />
<hkern g1="null" g2="null" k="12" />
<hkern g1="null" g2="null" k="12" />
<hkern g1="null" g2="null" k="20" />
<hkern g1="null" g2="null" k="-18" />
<hkern g1="null" g2="null" k="-39" />
<hkern g1="null" g2="null" k="29" />
<hkern g1="null" g2="null" k="-37" />
<hkern g1="null" g2="null" k="-10" />
<hkern g1="null" g2="null" k="-35" />
<hkern g1="null" g2="null" k="14" />
<hkern g1="null" g2="null" k="27" />
<hkern g1="null" g2="null" k="-37" />
<hkern g1="null" g2="null" k="29" />
<hkern g1="null" g2="null" k="16" />
<hkern g1="null" g2="null" k="25" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="33" />
<hkern g1="null" g2="null" k="25" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="35" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="25" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="27" />
<hkern g1="null" g2="null" k="37" />
<hkern g1="null" g2="null" k="27" />
<hkern g1="null" g2="null" k="76" />
<hkern g1="null" g2="null" k="76" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="-47" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="12" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="8" />
<hkern g1="null" g2="null" k="-25" />
<hkern g1="null" g2="null" k="-41" />
<hkern g1="null" g2="null" k="-49" />
<hkern g1="null" g2="null" k="-45" />
<hkern g1="null" g2="null" k="-31" />
<hkern g1="null" g2="null" k="-49" />
<hkern g1="null" g2="null" k="-10" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="29" />
<hkern g1="null" g2="null" k="37" />
<hkern g1="null" g2="null" k="66" />
<hkern g1="null" g2="null" k="-55" />
<hkern g1="null" g2="null" k="66" />
<hkern g1="null" g2="null" k="8" />
<hkern g1="null" g2="null" k="25" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="23" />
<hkern g1="null" g2="null" k="51" />
<hkern g1="null" g2="null" k="-61" />
<hkern g1="null" g2="null" k="51" />
<hkern g1="null" g2="null" k="10" />
<hkern g1="null" g2="null" k="20" />
<hkern g1="null" g2="null" k="12" />
<hkern g1="null" g2="null" k="12" />
<hkern g1="null" g2="null" k="12" />
<hkern g1="null" g2="null" k="14" />
<hkern g1="null" g2="null" k="14" />
<hkern g1="null" g2="null" k="23" />
<hkern g1="null" g2="null" k="25" />
<hkern g1="null" g2="null" k="27" />
<hkern g1="null" g2="null" k="18" />
<hkern g1="null" g2="null" k="74" />
<hkern g1="null" g2="null" k="-51" />
<hkern g1="null" g2="null" k="72" />
<hkern g1="null" g2="null" k="8" />
<hkern g1="null" g2="null" k="12" />
<hkern g1="null" g2="null" k="29" />
<hkern g1="null" g2="null" k="29" />
<hkern g1="null" g2="null" k="29" />
<hkern g1="null" g2="null" k="25" />
<hkern g1="null" g2="null" k="33" />
</font>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -0,0 +1 @@
@import 'lib/nib/'

View File

@@ -0,0 +1,68 @@
/*!
* nib
* Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var stylus = require('stylus')
, nodes = stylus.nodes
, utils = stylus.utils
, Canvas
exports = module.exports = plugin;
// conditionally expose canvas-based APIs.
try {
Canvas = require('canvas');
var gradient = require('./nodes/gradient')
, colorImage = require('./nodes/color-image')
} catch (err) {
// ignore
}
/**
* Library version.
*/
exports.version = '0.8.2';
/**
* Stylus path.
*/
exports.path = __dirname;
/**
* Return the plugin callback for stylus.
*
* @return {Function}
* @api public
*/
function plugin() {
return function(style){
style.include(__dirname);
if (Canvas) {
style.define('has-canvas', nodes.true);
// gradients
style.define('create-gradient-image', gradient.create)
style.define('gradient-data-uri', gradient.dataURL)
style.define('add-color-stop', gradient.addColorStop)
// color images
style.define('create-color-image', colorImage.create)
style.define('color-data-uri', colorImage.dataURL);
} else {
style.define('has-canvas', nodes.false);
}
}
}

View File

@@ -0,0 +1,11 @@
/*
* border: <color>
* border: ...
*/
border(color, args...)
if color is a 'color'
border: 1px solid color args
else
border: arguments

View File

@@ -0,0 +1,29 @@
/*
* The Magnificent Micro Clearfix
*
* Useful for clearing floats without structural markup.
* Prevents margin-collapsing on child elements in most cases.
*
* Known issues:
*
* 1. For IE 6/7 when applied to an element that contains only left-floated
* children the bottom margin on child elements will be collapsed.
*
* 2. For Firefox versions prior to 3.5 when applied to the first child element
* of body, and the element does not have non-zero padding, extra space will
* appear between the body and the first child.
*
* See http://nicolasgallagher.com/micro-clearfix-hack/
* and http://j.mp/bestclearfix
*
*/
clearfix()
&:before
&:after
content: ""
display: table
&:after
clear: both
zoom: 1 if support-for-ie

View File

@@ -0,0 +1,5 @@
color-image(color)
error('node-canvas is required for color-image()') unless has-canvas
colorImage = create-color-image(color)
'url(%s)' % color-data-uri(colorImage)

View File

@@ -0,0 +1,11 @@
/*
* Support for ie defaulting to true.
*/
support-for-ie ?= true
/*
* Default vendor prefixes.
*/
vendor-prefixes ?= webkit moz o ms official

View File

@@ -0,0 +1,192 @@
/*
* Vendor "display: flex" support with fallback to obsolete versions.
*/
flex-version ?= box flex
//
// 1. Display values
// - http://www.w3.org/TR/css3-flexbox/#flex-containers
//
display(type, args...)
if flex == type || inline-flex == type
if box in flex-version
display: -ms-flexbox args
display: vendor-value(box args, only: moz webkit)
if flex in flex-version
display: vendor-value(arguments, only: webkit official) // overwrites old webkit
else
display: arguments
/*
* New syntax for browsers like Google Chrome.
* Plus a translation to the old syntax, if possible.
*/
//
// 5. Ordering and Orientation
// - http://www.w3.org/TR/css3-flexbox/#ordering-and-orientation
//
-flex-obsolete-direction(direction)
if box in flex-version
if row-reverse == direction || column-reverse == direction
vendor('box-direction', reverse, ignore: ms official)
if row == direction || row-reverse == direction
vendor('box-orient', horizontal, ignore: ms official)
else if column == direction || column-reverse == direction
vendor('box-orient', vertical, ignore: ms official)
-flex-obsolete-wrap(value)
if box in flex-version
// WARN: wrap-reverse does not have a box equivalent. This will render in different manners
// on box vs. flex values.
if 'wrap' == value || wrap-reverse == value
vendor('box-lines', multiple, ignore: ms official)
else if nowrap == value
vendor('box-lines', single, ignore: ms official)
flex-direction(direction)
// obsolete
-flex-obsolete-direction(direction)
// new
if flex in flex-version
vendor('flex-direction', arguments, only: webkit ms official)
flex-wrap(value)
// obsolete
-flex-obsolete-wrap(value)
if flex in flex-version
vendor('flex-wrap', arguments, only: webkit ms official)
flex-flow()
// obsolete
-flex-obsolete-direction(arguments[0])
-flex-obsolete-direction(arguments[1])
-flex-obsolete-wrap(arguments[0])
-flex-obsolete-wrap(arguments[1])
// new
if flex in flex-version
vendor('flex-flow', arguments, only: webkit ms official)
order()
// obsolete
if box in flex-version
vendor('box-ordinal-group', arguments, ignore: ms official)
// new
if flex in flex-version
vendor('flex-order', arguments, only: ms)
vendor('order', arguments, only: webkit official)
//
// 7. Flexibility
// - http://www.w3.org/TR/css3-flexbox/#flexibility
//
flex-grow(growth)
// obsolete
if box in flex-version
vendor('box-flex', growth)
// new
if flex in flex-version
vendor('flex-grow', arguments, only: webkit official)
flex-basis()
if flex in flex-version
vendor('flex-basis', arguments, only: webkit official)
flex-shrink()
if flex in flex-version
vendor('flex-shrink', arguments, only: webkit official)
flex(growth)
// obsolete
if box in flex-version
shrink = 1
if none == growth || initial == growth
// Well known values
shrink = 0 if none == growth
growth = 0
else if is-width(growth) == true
// Basis is defined as the first parameter
growth = arguments[1] || 0
shrink = arguments[2] if 3 <= length(arguments)
else if arguments[1] && is-width(arguments[1]) == false
// Growth is first and shrink is second
shrink = arguments[1]
// Since we can't make the distinction between growing and shrinking in the box model, take
// the one that provides the most flexibility.
vendor('box-flex', max(growth, shrink), ignore: ms)
// new
if flex in flex-version
vendor('flex', arguments, only: webkit ms official)
// converts the justification alignment
-convert-justify(align)
if flex-start == align
return start
else if flex-end == align
return end
else if space-around == align
return distribute
else if space-between == align
return justify
else
return align
//
// 8. Alignment
// - http://www.w3.org/TR/css3-flexbox/#alignment
//
justify-content(align)
// obsolete
if box in flex-version
vendor('box-pack', -convert-justify(align), ignore: ms official)
// new
if flex in flex-version
vendor('flex-pack', -convert-justify(align), only: ms)
vendor('justify-content', align, only: webkit official)
align-content(align)
// WARN: Obsolete spec does not allow for adjustment here
if flex in flex-version
vendor('flex-line-pack', -convert-justify(align), only: ms)
vendor('align-content', align, only: webkit official)
// converts alignment from 'flex' to normal value
-convert-alignment(align)
if flex-start == align
return start
else if flex-end == align
return end
else
return align
align-items(align)
// obsolete
if box in flex-version
vendor('box-align', -convert-alignment(align), ignore: ms official)
// new
if flex in flex-version
vendor('flex-align', -convert-alignment(align), only: ms)
vendor('align-items', arguments, only: webkit official)
align-self(align)
// WARN: Obsolete spec does not allow for overriding alignment on individual items.
if flex in flex-version
vendor('align-self', align, only: webkit official)
vendor('flex-item-align', -convert-alignment(align), only: ms)

View File

@@ -0,0 +1,114 @@
@import 'config'
/*
* Replace the given str with val in the expr.
*/
replace(expr, str, val)
expr = clone(expr)
for e, i in expr
if length(e) > 1
expr[i] = replace(e, str, val)
else
if str == e
expr[i] = val
expr
/*
* Implicit color stop position.
*/
pos-in-stops(i, stops)
len = length(stops)
if len - 1 == i
100%
else if i
unit(i / len * 100, '%')
else
0
/*
* Normalize color stops:
*
* - (color pos) -> (pos color)
* - (color) -> (implied-pos color)
*
*/
normalize-stops(stops)
stops = clone(stops)
for stop, i in stops
if length(stop) == 1
color = stop[0]
stop[0] = pos-in-stops(i, stops)
stop[1] = color
else if typeof(stop[1]) == 'unit'
pos = stop[1]
stop[1] = stop[0]
stop[0] = pos
stops
/*
* Join color stops with the given translation function.
*/
join-stops(stops, translate)
str = ''
len = length(stops)
for stop, i in stops
str += ', ' if i
pos = stop[0]
color = stop[1]
str += translate(color, pos)
unquote(str)
/*
* Standard color stop.
*/
std-stop(color, pos)
'%s %s' % (color pos)
/*
* Create a linear gradient with the given start position
* and variable number of color stops.
*
* Examples:
*
* background: linear-gradient(top, red, green, blue)
* background: linear-gradient(bottom, red, green 50%, blue)
* background: linear-gradient(bottom, red, 50% green, blue)
* background: linear-gradient(bottom, red, 50% green, 90% white, blue)
*
*/
linear-gradient(start, stops...)
error('color stops required') unless length(stops)
// if current-property
// if start is a 'color'
// unshift(stops, start)
// start = top
// if start[0] is a 'unit'
// if has-canvas
// img = linear-gradient-image(start, stops)
// add-property(prop, replace(val, '__CALL__', img))
// start = start[1]
unquote('linear-gradient(' + join(', ',arguments) + ')')
/*
* Create a linear gradient image with the given start position
* and variable number of color stops.
*/
linear-gradient-image(start, stops...)
error('node-canvas is required for linear-gradient-image()') unless has-canvas
stops = stops[0] if length(stops) == 1
error('gradient image size required') unless start[0] is a 'unit'
size = start[0]
start = start[1] or 'top'
grad = create-gradient-image(size, start)
stops = normalize-stops(stops)
add-color-stop(grad, stop[0], stop[1]) for stop in stops
'url(%s)' % gradient-data-uri(grad)

View File

@@ -0,0 +1,8 @@
iconic-stroke(path)
@font-face
font-family: 'IconicStroke'
src: url(path + '/iconic_stroke.eot')
src: local(''), url(path + '/iconic_stroke.ttf') format('truetype'), url(path + '/iconic_stroke.svg#iconic') format('svg')
font-weight: normal
font-style: normal

View File

@@ -0,0 +1,26 @@
/*
* Define background-image as `path` with optional width and height, adding an
* @2x variant.
*
* affected by github.com/LearnBoost/stylus/issues/1050 and
* github.com/LearnBoost/stylus/issues/1038 ... refactor when those are closed
*/
image(path, w = auto, h = auto, min_pixel_ratio = 1.5)
background-image: url(path)
s = 'all and (-webkit-min-device-pixel-ratio:' + min_pixel_ratio + '),'
s = s + '(min--moz-device-pixel-ratio:' + min_pixel_ratio + '),'
s = s + '(-o-min-device-pixel-ratio:' + min_pixel_ratio + '/1),'
s = s + '(min-device-pixel-ratio:' + min_pixel_ratio + '),'
s = s + '(min-resolution:' + unit(min_pixel_ratio*92, dpi) + '),'
s = s + '(min-resolution:' + unit(min_pixel_ratio, dppx) + ')'
@media s
ext = extname(path)
path = pathjoin(dirname(path), basename(path, ext) + '@2x' + ext)
background-image: url(path)
if w in (cover contain) and h == auto
h = null
background-size: w h

View File

@@ -0,0 +1,13 @@
@import 'border'
@import 'clearfix'
@import 'color-image'
@import 'flex'
@import 'gradients'
@import 'iconic'
@import 'image'
@import 'overflow'
@import 'positions'
@import 'reset'
@import 'text'
@import 'vendor'
@import 'size'

View File

@@ -0,0 +1,20 @@
/*
* Overflow utility. Maps to regular overflow, and adds an ellipsis value.
*
* Synopsis:
*
* overflow: <type>
*
* Examples:
*
* overflow: auto
* overflow: hidden
* overflow: ellipsis
*
*/
overflow()
if arguments[0] == ellipsis
ellipsis()
else
overflow: arguments

View File

@@ -0,0 +1,64 @@
// helper
-pos(type, args)
i = 0
position: unquote(type)
{args[i]}: args[i + 1] is a 'unit' ? args[i += 1] : 0
{args[i += 1]}: args[i + 1] is a 'unit' ? args[i += 1] : 0
/*
* Position utility.
*
* Synopsis:
*
* fixed: <pos> [n] <pos> [n]
*
* Examples:
*
* fixed: top left
* fixed: top 5px left
* fixed: top left 5px
* fixed: top 5px left 5px
*
*/
fixed()
-pos('fixed', arguments)
/*
* Position utility.
*
* Synopsis:
*
* absolute: <pos> [n] <pos> [n]
*
* Examples:
*
* absolute: top left
* absolute: top 5px left
* absolute: top left 5px
* absolute: top 5px left 5px
*
*/
absolute()
-pos('absolute', arguments)
/*
* Position utility.
*
* Synopsis:
*
* relative: <pos> [n] <pos> [n]
*
* Examples:
*
* relative: top left
* relative: top 5px left
* relative: top left 5px
* relative: top 5px left 5px
*
*/
relative()
-pos('relative', arguments)

View File

@@ -0,0 +1,79 @@
// Based on [Eric Meyer's reset](http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/)
global-reset()
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td
reset-box-model()
reset-font()
body
reset-body()
ol, ul
list-style: none
table
reset-table()
caption, th, td
reset-table-cell()
a img
border: none
nested-reset()
div, span, object, iframe, h1, h2, h3, h4, h5, h6, p,
pre, a, abbr, acronym, address, code, del, dfn, em, img,
dl, dt, dd, ol, ul, li, fieldset, form, label,
legend, caption, tbody, tfoot, thead, tr
reset-box-model()
reset-font()
table
reset-table()
caption, th, td
reset-table-cell()
a img
border: none
reset-box-model()
margin: 0
padding: 0
border: 0
outline: 0
reset-font()
font-weight: inherit
font-style: inherit
font-family: inherit
font-size: 100%
vertical-align: baseline
reset-body()
line-height: 1
color: black
background: white
reset-table()
border-collapse: separate
border-spacing: 0
vertical-align: middle
reset-table-cell()
text-align: left
font-weight: normal
vertical-align: middle
reset-html5()
article, aside, canvas, details, figcaption,
figure, footer, header, hgroup, menu, nav,
section, summary, main
reset-box-model()
display: block
audio, canvas, video
display inline-block
*display inline
*zoom 1
audio:not([controls]),[hidden]
display none

View File

@@ -0,0 +1,28 @@
/*
* Size utility.
*
* Synopsis:
*
* size: <width> <height> | <width & height>
*
* Examples:
*
* size: 100% 30px
* yields:
* width: 100%
* height: 30px
*
* size: 5px
* yields:
* width: 5px
* height: 5px
*
*/
size()
if length(arguments) == 1
width: arguments[0]
height: arguments[0]
else
width: arguments[0]
height: arguments[1]

View File

@@ -0,0 +1,13 @@
/*
* Alias of "nowrap".
*/
no-wrap = unquote('nowrap')
/*
* Alias of "white-space".
*/
whitespace()
white-space: arguments

View File

@@ -0,0 +1,10 @@
/*
* Ellipsis with wrapping disabled by default.
*/
ellipsis(no-wrap = true)
if no-wrap
white-space: nowrap
overflow: hidden
text-overflow: ellipsis

View File

@@ -0,0 +1,8 @@
/*
* Hide text.
*/
hide-text()
text-indent: 101%
white-space: nowrap
overflow: hidden

View File

@@ -0,0 +1,4 @@
@import './aliases'
@import './ellipsis'
@import './hide-text'
@import './replace-text'

View File

@@ -0,0 +1,9 @@
/*
* Replace text with an image.
*/
replace-text(image, x=50%, y=50%)
hide-text()
background-image image
background-repeat no-repeat
background-position x y

View File

@@ -0,0 +1,573 @@
use('../nodes/vendor-helpers.js')
@import 'config'
/*
* Alias "nowrap" as "no-wrap".
*/
no-wrap = unquote('nowrap')
/*
* Helper to find out if a given value is a width
*/
is-width(val)
if auto == val
return true
else if val && 'unit' == type(val)
// Stylus does not short circuit so we need to perform this as a distinct
// operation to prevent errors
return '' != unit(val)
return false
/*
* Vendor support for the given prop / arguments, optionally specifying the
* only prefixes to utilize, or those which should be ignored.
*/
vendor(prop, args, only = null, ignore = null, vendor-property = true)
need_normalize = !vendor-property or prop in ('transition' 'transition-property' 'border-image' 'border-image-slice')
for prefix in vendor-prefixes
unless (only and !(prefix in only)) or (ignore and prefix in ignore)
if official == prefix
if need_normalize
{prop}: normalize(prop,('%s' % args))
else
{prop}: args
else
newprop = prop
newprop = '-' + prefix + '-' + prop if vendor-property
if need_normalize
{newprop}: normalize(prop,('%s' % args),prefix)
else
{newprop}: args
/*
* Vendorize the given value.
*/
vendor-value(arg, only = null, ignore = null)
prop = current-property[0]
for prefix in vendor-prefixes
unless (only and !(prefix in only)) or (ignore and prefix in ignore) or official == prefix
add-property(prop, '-%s-%s' % (prefix arg))
arg
/*
* Vendor "box-shadow" support.
*/
box-shadow()
vendor('box-shadow', arguments, only: webkit official)
/*
* Vendor "user-select" support.
*/
user-select()
vendor('user-select', arguments, only: webkit moz ms official)
/*
* Vendor "column-count" support.
*/
column-count()
vendor('column-count', arguments, only: webkit moz official)
/*
* Vendor "column-gap" support.
*/
column-gap()
vendor('column-gap', arguments, only: webkit moz official)
/*
* Vendor "column-rule" support.
*/
column-rule()
vendor('column-rule', arguments, only: webkit moz official)
/*
* Vendor "column-rule-color" support.
*/
column-rule-color()
vendor('column-rule-color', arguments, only: webkit moz official)
/*
* Vendor "column-rule-width" support.
*/
column-rule-width()
vendor('column-rule-width', arguments, only: webkit moz official)
/*
* Vendor "column-rule-style" support.
*/
column-rule-style()
vendor('column-rule-style', arguments, only: webkit moz official)
/*
* Vendor "column-width" support.
*/
column-width()
vendor('column-width', arguments, only: webkit moz official)
/*
* Vendor "column-span" support.
*/
column-span()
vendor('column-span', arguments, only: webkit official)
/*
* Vendor "column-fill" support.
*/
column-fill()
vendor('column-fill', arguments, only: moz)
/*
* Legacy syntax support for background-clip and background-origin
*/
legacy-bg-values(property, args)
legacy_args = ()
importance = unquote('')
for subargs in args
for arg in subargs
if arg in (border-box padding-box content-box)
arg = unquote('border') if arg == border-box
arg = unquote('padding') if arg == padding-box
arg = unquote('content') if arg == content-box
if arg != '!important'
push(legacy_args,arg)
else
importance = !important
vendor(property, unquote(join(', ',legacy_args)) importance, only: moz webkit)
/*
* Vendor "background-clip" support.
*/
background-clip()
if arguments[0] == text
vendor('background-clip', arguments, only: webkit)
else
legacy-bg-values('background-clip', arguments)
background-clip: arguments
/*
* Vendor "background-origin" support.
*/
background-origin()
legacy-bg-values('background-origin', arguments)
background-origin: arguments
/*
* Vendor "background-size" support.
*/
background-size()
vendor('background-size', arguments, only: webkit moz official)
/*
* Vendor "transform" support.
*/
transform()
vendor('transform', arguments)
/*
* Vendor "transform-origin" support.
*/
transform-origin()
vendor('transform-origin', arguments)
/*
* Vendor "transform-style" support.
*/
transform-style()
vendor('transform-style', arguments)
/*
* Vendor "border-image" support.
*/
border-image()
vendor('border-image', arguments, only: webkit moz o official)
/*
* Vendor "transition" support.
*/
transition()
vendor('transition', arguments)
/*
* Vendor "transition-property" support.
*/
transition-property()
vendor('transition-property', arguments)
/*
* Vendor "transition-duration" support.
*/
transition-duration()
vendor('transition-duration', arguments)
/*
* Vendor "transition-timing-function" support.
*/
transition-timing-function()
vendor('transition-timing-function', arguments)
/*
* Vendor "transition-delay" support.
*/
transition-delay()
vendor('transition-delay', arguments)
/*
* Vendor "backface-visibility" support.
*/
backface-visibility()
vendor('backface-visibility', arguments, only: webkit moz ms official)
/*
* Vendor "perspective" support.
*/
perspective()
if mixin
vendor('perspective', arguments, only: webkit moz ms official)
else
'perspective(%s)' % arguments
/*
* Vendor "perspective-origin" support.
*/
perspective-origin()
vendor('perspective-origin', arguments, only: webkit moz ms official)
/*
* Opacity with conditional IE support.
*/
opacity(n, args...)
opacity: n args
if support-for-ie
val = round(n * 100)
if val == 100
-ms-filter: none
filter: none
else
-ms-filter: '"progid:DXImageTransform.Microsoft.Alpha(Opacity=%s)"' % val args
filter: 'alpha(opacity=%s)' % val args
/*
* Vendor "text-size-adjust"
*/
text-size-adjust()
vendor('text-size-adjust', arguments)
/*
* Alias the "white-space" property.
*/
whitespace()
white-space: arguments
/*
* Vendor "box-sizing" support.
*/
box-sizing()
vendor('box-sizing', arguments, only: webkit moz official)
/*
* Vendor "box-orient" support.
*/
box-orient()
vendor('box-orient', arguments, only: webkit moz official)
/*
* Vendor "box-flex-group" support.
*/
box-flex-group()
vendor('box-flex-group', arguments, only: webkit moz official)
/*
* Vendor "box-ordinal-group" support.
*/
box-ordinal-group()
vendor('box-ordinal-group', arguments, only: webkit moz ms official)
/*
* Vendor "box-align" support.
*/
box-align()
vendor('box-align', arguments, only: webkit moz ms official)
/*
* Vendor "box-pack" support.
*/
box-pack()
vendor('box-pack', arguments, only: webkit moz ms official)
/*
* Vendor "box-direction" support.
*/
box-direction()
vendor('box-direction', arguments, only: webkit moz ms official)
/*
* Vendor "animation" support.
*/
animation()
vendor('animation', arguments)
/*
* Vendor "animation-name" support.
*/
animation-name()
vendor('animation-name', arguments)
/*
* Vendor "animation-duration" support.
*/
animation-duration()
vendor('animation-duration', arguments)
/*
* Vendor "animation-delay" support.
*/
animation-delay()
vendor('animation-delay', arguments)
/*
* Vendor "animation-direction" support.
*/
animation-direction()
vendor('animation-direction', arguments)
/*
* Vendor "animation-iteration-count" support.
*/
animation-iteration-count()
vendor('animation-iteration-count', arguments)
/*
* Vendor "animation-timing-function" support.
*/
animation-timing-function()
vendor('animation-timing-function', arguments)
/*
* Vendor "animation-play-state" support.
*/
animation-play-state()
vendor('animation-play-state', arguments)
/*
* Vendor "animation-fill-mode" support.
*/
animation-fill-mode()
vendor('animation-fill-mode', arguments)
/*
* Vendor "hyphens" support.
*/
hyphens()
vendor('hyphens', arguments, only: webkit moz ms official)
/*
* Vendor "appearance" support.
*/
appearance()
vendor('appearance', arguments, only: webkit moz official)
/*
* Vendor "tab-size" support.
*/
tab-size()
vendor('tab-size', arguments, only: moz o official)
/*
* Vendor "overflow-scrolling" support.
*/
overflow-scrolling()
vendor('overflow-scrolling', arguments, only: webkit official)
/*
* Vendor "text-overflow" support, , -o- for opera 9.* - 10.*
*/
text-overflow()
vendor('text-overflow', arguments, only: official o)
/*
* Vendor "text-size-adjust" support.
*/
text-size-adjust()
vendor('text-size-adjust', arguments, only: official webkit ms)
/*
* Vendor "font-smoothing" support, webkit only.
*/
font-smoothing()
vendor('font-smoothing', arguments, only: webkit)
/*
* Helper for border-radius().
*/
-apply-border-radius(pos, importance)
if length(pos) == 3
// border-radius: <top | buttom> <left | right> <n>
y = pos[0]
x = pos[1]
// We don't use moz for simple boder-radius anymore
// vendor('border-radius-%s%s' % pos, pos[2], only: moz)
vendor('border-%s-%s-radius' % pos, pos[2] importance, only: webkit official)
else if pos[0] in (top bottom)
// border-radius: <top | bottom> <n>
-apply-border-radius(pos[0] left pos[1], importance)
-apply-border-radius(pos[0] right pos[1], importance)
else if pos[0] in (left right)
// border-radius: <left | right> <n>
unshift(pos, top);
-apply-border-radius(pos, importance)
pos[0] = bottom
-apply-border-radius(pos, importance)
/*
* border-radius supporting vendor prefixes and
* augmented behavior.
*
* Examples:
*
* border-radius: 2px 5px
* border-radius: top 5px bottom 10px
* border-radius: left 5px
* border-radius: top left 5px
* border-radius: top left 10px bottom right 5px
* border-radius: top left 10px, bottom right 5px
*
*/
border-radius()
pos = ()
augmented = false
importance = arguments[length(arguments) - 1] == !important ? !important : unquote('')
for args in arguments
for arg in args
if arg is a 'ident'
append(pos, arg)
augmented = true
else
append(pos, arg)
if augmented
-apply-border-radius(pos, importance)
pos = ()
vendor('border-radius', pos, only: webkit official) unless augmented
/**
* Vendor input-placeholder/placeholder support.
*
* Examples:
* // Default syntax
* body
* placeholder(color #333, font-weight normal)
*
* // The comma is important
* .placeholder-red
* placeholder(color red,)
*
* // We can pass a function
* green-placeholder()
* color green
* .placeholder-green
* placeholder(green-placeholder)
*
* // We can pass a hash
* textarea
* placeholder((font-style italic) (font-weight bold) (padding '4px 10px'))
*/
placeholder()
for v in ':-webkit-input' '-moz' ':-moz' '-ms-input'
&:{v}-placeholder
for pair in arguments
if typeof(pair) == 'function'
pair()
else if pair is not null && pair[0] is not null
{pair[0]}: type(pair[1]) == 'string' ? s(pair[1]) : pair[1]
input-placeholder = placeholder
/*
* Vendor background support (gradients).
*/
background()
if match('-gradient\(', ''+arguments)
vendor('background', arguments, vendor-property: false)
else
background arguments
background-image()
if match('-gradient\(', ''+arguments)
vendor('background-image', arguments, vendor-property: false)
else
background-image arguments
cursor()
if match('-gradient\(', ''+arguments)
vendor('cursor', arguments, vendor-property: false)
else
cursor arguments
list-style()
if match('-gradient\(', ''+arguments)
vendor('list-style', arguments, vendor-property: false)
else
list-style arguments
list-style-image()
if match('-gradient\(', ''+arguments)
vendor('list-style-image', arguments, vendor-property: false)
else
list-style-image arguments

View File

@@ -0,0 +1,84 @@
/**
* Module dependencies.
*/
var stylus = require('stylus')
, Canvas = require('canvas')
, nodes = stylus.nodes
, utils = stylus.utils
/**
* Expose `ColorImage`.
*/
exports = module.exports = ColorImage;
/**
* Create a new `ColorImage` node with the given `color`.
*
* @param {Color} color node
* @return {ColorImage}
* @api public
*/
exports.create = function(color){
utils.assertColor(color);
return new ColorImage(color);
};
/**
* Return the data URI for `colorImage`.
*
* @param {ColorImage} colorImage
* @return {String}
* @api public
*/
exports.dataURL = function(colorImage){
utils.assertType(colorImage, 'colorimage');
return new nodes.String(colorImage.toDataURL());
};
/**
* Initialize a new `ColorImage` node with the given arguments.
*
* @param {Color} color node
* @api private
*/
function ColorImage(color) {
this.color = color;
this.canvas = new Canvas(1, 1);
this.ctx = this.canvas.getContext('2d');
this.ctx.fillStyle = color.toString();
this.ctx.fillRect(0, 0, 1, 1);
};
/**
* Inherit from `nodes.Node.prototype`.
*/
ColorImage.prototype.__proto__ = nodes.Node.prototype;
/**
* Inspect the color.
*
* @return {String}
* @api private
*/
ColorImage.prototype.toString = function(){
return 'ColorImage(' + this.color.toString() + ')';
};
/**
* Return data URI string.
*
* @return {String}
* @api private
*/
ColorImage.prototype.toDataURL = function(){
return this.canvas.toDataURL();
};

View File

@@ -0,0 +1,165 @@
/**
* Module dependencies.
*/
var stylus = require('stylus')
, Canvas = require('canvas')
, nodes = stylus.nodes
, utils = stylus.utils;
/**
* Expose `Gradient`.
*/
exports = module.exports = Gradient;
/**
* Create a new `Gradient` node with the given `size`
* and `start` position.
*
* @param {Number} size
* @param {String|Ident|Literal} start
* @return {Gradient}
* @api public
*/
exports.create = function(size, start){
utils.assertType(size, 'unit', 'size');
utils.assertString(start, 'start');
return new Gradient(size.val, start.string);
};
/**
* Add color stop to `grad`.
*
* @param {Gradient} grad
* @param {Unit} pos
* @param {HSLA|RGBA} color
* @return {Null}
* @api public
*/
exports.addColorStop = function(grad, pos, color){
utils.assertType(grad, 'gradient', 'grad');
utils.assertType(pos, 'unit', 'pos');
utils.assertColor(color, 'color');
grad.addColorStop(pos.val / 100, color.rgba.toString());
return nodes.null;
};
/**
* Return the data URI for `grad`.
*
* @param {Gradient} grad
* @return {String}
* @api public
*/
exports.dataURL = function(grad){
utils.assertType(grad, 'gradient');
return new nodes.String(grad.toDataURL());
};
/**
* Initialize a new `Gradient` node with the given `size`
* and `start` position.
*
* @param {Number} size
* @param {String} start
* @api private
*/
function Gradient(size, start) {
this.size = size;
this.canvas = new Canvas(1, 1);
this.setStartPosition(start);
this.ctx = this.canvas.getContext('2d');
this.grad = this.ctx.createLinearGradient(
this.from[0], this.from[1]
, this.to[0], this.to[1]);
};
/**
* Inspect the gradient.
*
* @return {String}
* @api private
*/
Gradient.prototype.toString = function(){
return 'Gradient(' + this.size + 'px '
+ this.stops.map(function(stop){
return stop[0] + ' ' + stop[1];
}).join(', ') + ')';
};
/**
* Set `start` position.
*
* @param {String} start
* @api private
*/
Gradient.prototype.setStartPosition = function(start){
var size = this.size
, canvas = this.canvas;
switch (start) {
case 'top':
canvas.height = size;
this.from = [canvas.width / 2, 0];
this.to = [canvas.width / 2, canvas.height];
break;
case 'bottom':
canvas.height = size;
this.from = [canvas.width / 2, canvas.height];
this.to = [canvas.width / 2, 0];
break;
case 'left':
canvas.width = size;
this.from = [0, 0];
this.to = [canvas.width, canvas.height];
break;
case 'right':
canvas.width = size;
this.from = [canvas.width, canvas.height];
this.to = [0, 0];
break;
default:
throw new Error('invalid start position "' + start + '"');
}
};
/**
* Add color stop `pos` / `color`.
*
* @param {Number} pos
* @param {String} color
* @api private
*/
Gradient.prototype.addColorStop = function(pos, color){
this.grad.addColorStop(pos, color);
};
/**
* Return data URI string.
*
* @return {String}
* @api private
*/
Gradient.prototype.toDataURL = function(){
var canvas = this.canvas
, ctx = this.ctx;
ctx.fillStyle = this.grad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
return canvas.toDataURL();
};
/**
* Inherit from `nodes.Node.prototype`.
*/
Gradient.prototype.__proto__ = nodes.Node.prototype;

View File

@@ -0,0 +1,79 @@
var RE_GRADIENT_STOPS = /([\(\,]\s*)(-?(?:\d*\.)?\d+(?:%|px|em))(\s+)((hsl|rgb)a?\([^\)]+\)|#[^\)\,]+)/g
, RE_GRADIENT_VAL = /(\(\s*)(?:(-?(\d*\.)?\d+)deg|((to )?(top|bottom|left|right)( (top|bottom|left|right))?))/g
, RE_GRADIENT_TYPE = /((repeating-)?(linear|radial)-gradient\()/g
, RE_TRANSFORM = /\b(transform)\b/g
, RE_FILL_KEYWORD = /\s*\b(fill)\b\s*/g;
var DIRECTIONS = { top: 'bottom', bottom: 'top', left: 'right', right:'left' };
/**
* Expose `normalize`.
*/
function normalize(property, value, prefix){
var result = value.toString()
, args;
/* Fixing the gradients */
if (~result.indexOf('gradient(')) {
/* Normalize color stops */
result = result.replace(RE_GRADIENT_STOPS,'$1$4$3$2');
/* Normalize legacy gradients */
result = result.replace(RE_GRADIENT_VAL, function(){
args = [].slice.call(arguments, 1);
return normalizeGradient(args, prefix);
});
/* Adding prefixes to the legacy gradients */
if (prefix) result = result.replace(RE_GRADIENT_TYPE, '-' + prefix + '-$1');
}
/* Adding prefixes to the `transform` values of legacy `transition` property */
if (prefix && (property == "'transition'" || property == "'transition-property'")) {
result = result.replace(RE_TRANSFORM, '-' + prefix + '-$1');
}
/* Removing `fill` keyword from the legacy `border-image` property */
if (prefix && (property == "'border-image'" || property == "'border-image-slice'")) {
result = result.replace(RE_FILL_KEYWORD, ' ');
}
return result;
}
function normalizeGradient(parts, prefix){
/* Fix the degrees to the legacy syntax */
var val = parts[0];
// when the gradients were unprefixed, the w3c changed the way that the
// angle direction is interpreted. see:
// http://blogs.msdn.com/b/ie/archive/2012/06/25/unprefixed-css3-gradients-in-ie10.aspx
if (parts[1]) val += (prefix ? parseFloat((Math.abs(450 - parts[1]) % 360).toFixed(3)) : parts[1]) + 'deg';
/* Fix the directions to the legacy syntax */
if (prefix && parts[4]) {
// `to top` to `bottom` etc.
if (parts[5]) val += DIRECTIONS[parts[5]];
if (parts[6]) val += ' ' + DIRECTIONS[parts[7]];
} else if (!prefix && !parts[4]) {
// `top` to `to bottom` etc.
if (parts[5]) val += 'to ' + DIRECTIONS[parts[5]];
if (parts[6]) val += ' ' + DIRECTIONS[parts[7]];
} else {
if (parts[3]) val += parts[3];
}
return val;
}
var plugin = function(){
return function(style){
var nodes = this.nodes;
style.define('normalize', function(property, value, prefix) {
return new nodes.Ident(normalize(property, value, prefix));
});
};
};
module.exports = plugin;

View File

@@ -0,0 +1 @@
../stylus/bin/stylus

View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2010 LearnBoost <dev@learnboost.com>
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.

View File

@@ -0,0 +1,163 @@
# Stylus
Stylus is a revolutionary new language, providing an efficient, dynamic, and expressive way to generate CSS. Supporting both an indented syntax and regular CSS style.
## Installation
```bash
$ npm install stylus
```
### Example
```
border-radius()
-webkit-border-radius: arguments
-moz-border-radius: arguments
border-radius: arguments
body a
font: 12px/1.4 "Lucida Grande", Arial, sans-serif
background: black
color: #ccc
form input
padding: 5px
border: 1px solid
border-radius: 5px
```
compiles to:
```css
body a {
font: 12px/1.4 "Lucida Grande", Arial, sans-serif;
background: #000;
color: #ccc;
}
form input {
padding: 5px;
border: 1px solid;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
```
the following is equivalent to the indented version of Stylus source, using the CSS syntax instead:
```
border-radius() {
-webkit-border-radius: arguments
-moz-border-radius: arguments
border-radius: arguments
}
body a {
font: 12px/1.4 "Lucida Grande", Arial, sans-serif;
background: black;
color: #ccc;
}
form input {
padding: 5px;
border: 1px solid;
border-radius: 5px;
}
```
### Features
Stylus has _many_ features. Detailed documentation links follow:
- [css syntax](docs/css-style.md) support
- [mixins](docs/mixins.md)
- [keyword arguments](docs/kwargs.md)
- [variables](docs/variables.md)
- [interpolation](docs/interpolation.md)
- arithmetic, logical, and equality [operators](docs/operators.md)
- [importing](docs/import.md) of other stylus sheets
- [introspection api](docs/introspection.md)
- type coercion
- [@extend](docs/extend.md)
- [conditionals](docs/conditionals.md)
- [iteration](docs/iteration.md)
- nested [selectors](docs/selectors.md)
- parent reference
- in-language [functions](docs/functions.md)
- [variable arguments](docs/vargs.md)
- built-in [functions](docs/bifs.md) (over 25)
- optional [image inlining](docs/functions.url.md)
- optional compression
- JavaScript [API](docs/js.md)
- extremely terse syntax
- stylus [executable](docs/executable.md)
- [error reporting](docs/error-reporting.md)
- single-line and multi-line [comments](docs/comments.md)
- css [literal](docs/literal.md)
- character [escaping](docs/escape.md)
- [@keyframes](docs/keyframes.md) support & expansion
- [@font-face](docs/font-face.md) support
- [@media](docs/media.md) support
- Connect [Middleware](docs/middleware.md)
- TextMate [bundle](docs/textmate.md)
- Coda/SubEtha Edit [Syntax mode](https://github.com/atljeremy/Stylus.mode)
- gedit [language-spec](docs/gedit.md)
- VIM [Syntax](https://github.com/wavded/vim-stylus)
- [Firebug extension](docs/firebug.md)
- heroku [web service](http://styl.heroku.com) for compiling stylus
- [style guide](https://github.com/lepture/ganam) parser and generator
- transparent vendor-specific function expansion
### Community modules
- https://github.com/LearnBoost/stylus/wiki
### Framework Support
- [Connect](docs/middleware.md)
- [Play! 2.0](https://github.com/patiencelabs/play-stylus)
- [Ruby On Rails](https://github.com/lucasmazza/ruby-stylus)
### CMS Support
- [DocPad](https://github.com/bevry/docpad)
- [Punch](https://github.com/laktek/punch-stylus-compiler)
### Screencasts
- [Stylus Intro](http://screenr.com/bNY)
- [CSS Syntax & Postfix Conditionals](http://screenr.com/A8v)
### Authors
- [TJ Holowaychuk (visionmedia)](http://github.com/visionmedia)
### More Information
- Language [comparisons](docs/compare.md)
## License
(The MIT License)
Copyright (c) 2010 LearnBoost &lt;dev@learnboost.com&gt;
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.

View File

@@ -0,0 +1,638 @@
#!/usr/bin/env node
/**
* Module dependencies.
*/
var fs = require('fs')
, stylus = require('../lib/stylus')
, basename = require('path').basename
, dirname = require('path').dirname
, resolve = require('path').resolve
, join = require('path').join
, isWindows = process.platform === 'win32';
/**
* Arguments.
*/
var args = process.argv.slice(2);
/**
* Compare flag.
*/
var compare = false;
/**
* Compress flag.
*/
var compress = false;
/**
* CSS conversion flag.
*/
var convertCSS = false;
/**
* Line numbers flag.
*/
var linenos = false;
/**
* Firebug flag
*/
var firebug = false;
/**
* Files to processes.
*/
var files = [];
/**
* Import paths.
*/
var paths = [];
/**
* Destination directory.
*/
var dest;
/**
* Watcher hash.
*/
var watchers;
/**
* Enable REPL.
*/
var interactive;
/**
* Plugins.
*/
var plugins = [];
/**
* Optional url() function.
*/
var urlFunction = false;
/**
* Include CSS on import.
*/
var includeCSS = false;
/**
* Set file imports.
*/
var imports = [];
/**
* Resolve relative urls
*/
var resolveURL = false;
/**
* Usage docs.
*/
var usage = [
''
, ' Usage: stylus [options] [command] [< in [> out]]'
, ' [file|dir ...]'
, ''
, ' Commands:'
, ''
, ' help [<type>:]<prop> Opens help info at MDC for <prop> in'
, ' your default browser. Optionally'
, ' searches other resources of <type>:'
, ' safari opera w3c ms caniuse quirksmode'
, ''
, ' Options:'
, ''
, ' -i, --interactive Start interactive REPL'
, ' -u, --use <path> Utilize the Stylus plugin at <path>'
, ' -U, --inline Utilize image inlining via data URI support'
, ' -w, --watch Watch file(s) for changes and re-compile'
, ' -o, --out <dir> Output to <dir> when passing files'
, ' -C, --css <src> [dest] Convert CSS input to Stylus'
, ' -I, --include <path> Add <path> to lookup paths'
, ' -c, --compress Compress CSS output'
, ' -d, --compare Display input along with output'
, ' -f, --firebug Emits debug infos in the generated CSS that'
, ' can be used by the FireStylus Firebug plugin'
, ' -l, --line-numbers Emits comments in the generated CSS'
, ' indicating the corresponding Stylus line'
, ' --import <file> Import stylus <file>'
, ' --include-css Include regular CSS on @import'
, ' -r, --resolve-url Resolve relative urls inside imports'
, ' -V, --version Display the version of Stylus'
, ' -h, --help Display help information'
, ''
].join('\n');
/**
* Handle arguments.
*/
var arg;
while (args.length) {
arg = args.shift();
switch (arg) {
case '-h':
case '--help':
console.error(usage);
process.exit(1);
case '-d':
case '--compare':
compare = true;
break;
case '-c':
case '--compress':
compress = true;
break;
case '-C':
case '--css':
convertCSS = true;
break;
case '-f':
case '--firebug':
firebug = true;
break;
case '-l':
case '--line-numbers':
linenos = true;
break;
case '-V':
case '--version':
console.log(stylus.version);
process.exit(0);
break;
case '-o':
case '--out':
dest = args.shift();
if (!dest) throw new Error('--out <dir> required');
break;
case 'help':
var name = args.shift()
, browser = name.split(':');
if (browser.length > 1) {
name = [].slice.call(browser, 1).join(':');
browser = browser[0];
} else {
name = browser[0];
browser = '';
}
if (!name) throw new Error('help <property> required');
help(name);
break;
case '--include-css':
includeCSS = true;
break;
case '-i':
case '--repl':
case '--interactive':
interactive = true;
break;
case '-I':
case '--include':
var path = args.shift();
if (!path) throw new Error('--include <path> required');
paths.push(path);
break;
case '-w':
case '--watch':
watchers = {};
break;
case '-U':
case '--inline':
args.unshift('--use', 'url');
break;
case '-u':
case '--use':
var options;
var path = args.shift();
if (!path) throw new Error('--use <path> required');
// options
if ('--with' == args[0]) {
args.shift();
options = args.shift();
if (!options) throw new Error('--with <options> required');
options = eval('(' + options + ')');
}
// url support
if ('url' == path) {
urlFunction = options || {};
} else {
paths.push(dirname(path));
plugins.push({ path: path, options: options });
}
break;
case '--import':
var file = args.shift();
if (!file) throw new Error('--import <file> required');
imports.push(file);
break;
case '-r':
case '--resolve-url':
resolveURL = true;
break;
default:
files.push(arg);
}
}
// if --watch is used, assume we are
// not working with stdio
if (watchers && !files.length) {
files = fs.readdirSync(process.cwd())
.filter(function(file){
return file.match(/\.styl$/);
});
}
/**
* Open the default browser to the CSS property `name`.
*
* @param {String} name
*/
function help(name) {
var url
, exec = require('child_process').exec
, command;
name = encodeURIComponent(name);
switch (browser) {
case 'safari':
case 'webkit':
url = 'https://developer.apple.com/library/safari/search/?q=' + name;
break;
case 'opera':
url = 'http://dev.opera.com/search/?term=' + name;
break;
case 'w3c':
url = 'http://www.google.com/search?q=site%3Awww.w3.org%2FTR+' + name;
break;
case 'ms':
url = 'http://social.msdn.microsoft.com/search/en-US/ie?query=' + name + '&refinement=59%2c61';
break;
case 'caniuse':
url = 'http://caniuse.com/#search=' + name;
break;
case 'quirksmode':
url = 'http://www.google.com/search?q=site%3Awww.quirksmode.org+' + name;
break;
default:
url = 'https://developer.mozilla.org/en/CSS/' + name;
}
switch (process.platform) {
case 'linux': command = 'x-www-browser'; break;
default: command = 'open';
}
exec(command + ' "' + url + '"', function(){
process.exit(0);
});
}
// Compilation options
var options = {
filename: 'stdin'
, compress: compress
, firebug: firebug
, linenos: linenos
, paths: [process.cwd()].concat(paths)
};
// Buffer stdin
var str = '';
// Convert CSS to Stylus
if (convertCSS) {
switch (files.length) {
case 2:
compileCSSFile(files[0], files[1]);
break;
case 1:
compileCSSFile(files[0], files[0].replace('.css', '.styl'));
break;
default:
var stdin = process.openStdin();
stdin.setEncoding('utf8');
stdin.on('data', function(chunk){ str += chunk; });
stdin.on('end', function(){
var out = stylus.convertCSS(str);
console.log(out);
});
}
} else if (interactive) {
repl();
} else {
if (files.length) {
compileFiles(files);
} else {
compileStdio();
}
}
/**
* Start Stylus REPL.
*/
function repl() {
var options = { filename: 'stdin', imports: [join(__dirname, '..', 'lib', 'functions')] }
, parser = new stylus.Parser('', options)
, evaluator = new stylus.Evaluator(parser.parse(), options)
, rl = require('readline')
, repl = rl.createInterface(process.stdin, process.stdout, autocomplete)
, global = evaluator.global.scope;
// expose BIFs
evaluator.evaluate();
// readline
repl.setPrompt('> ');
repl.prompt();
// HACK: flat-list auto-complete
function autocomplete(line){
var out = process.stdout
, keys = Object.keys(global.locals)
, len = keys.length
, words = line.split(/\s+/)
, word = words.pop()
, names = []
, name
, node
, key;
// find words that match
for (var i = 0; i < len; ++i) {
key = keys[i];
if (0 == key.indexOf(word)) {
node = global.lookup(key);
switch (node.nodeName) {
case 'function':
names.push(node.toString());
break;
default:
names.push(key);
}
}
}
return [names, line];
};
repl.on('line', function(line){
if (!line.trim().length) return repl.prompt();
parser = new stylus.Parser(line, options);
parser.state.push('expression');
evaluator.return = true;
try {
var expr = parser.parse();
var ret = evaluator.visit(expr);
ret = ret.nodes[ret.nodes.length - 1];
ret = ret.toString();
if ('(' == ret[0]) ret = ret.replace(/^\(|\)$/g, '');
console.log('\033[90m=> \033[0m' + highlight(ret));
repl.prompt();
} catch (err) {
console.error('\033[31merror: %s\033[0m', err.message || err.stack);
repl.prompt();
}
});
repl.on('SIGINT', function(){
console.log();
process.exit(0);
});
}
/**
* Highlight the given string of Stylus.
*/
function highlight(str) {
return str
.replace(/(#)?(\d+(\.\d+)?)/g, function($0, $1, $2){
return $1 ? $0 : '\033[36m' + $2 + '\033[0m';
})
.replace(/(#[\da-fA-F]+)/g, '\033[33m$1\033[0m')
.replace(/('.*?'|".*?")/g, '\033[32m$1\033[0m');
}
/**
* Convert a CSS file to a Styl file
*/
function compileCSSFile(file, fileOut) {
fs.lstat(file, function(err, stat){
if (err) throw err;
if (stat.isFile()) {
fs.readFile(file, 'utf8', function(err, str){
if (err) throw err;
var styl = stylus.convertCSS(str);
fs.writeFile(fileOut, styl, function(err){
if (err) throw err;
});
});
}
});
}
/**
* Compile with stdio.
*/
function compileStdio() {
process.stdin.setEncoding('utf8');
process.stdin.on('data', function(chunk){ str += chunk; });
process.stdin.on('end', function(){
// Compile to css
var style = stylus(str, options);
if (includeCSS) style.set('include css', true);
if (resolveURL) style.set('resolve url', true);
usePlugins(style);
importFiles(style);
style.render(function(err, css){
if (err) throw err;
if (compare) {
console.log('\n\x1b[1mInput:\x1b[0m');
console.log(str);
console.log('\n\x1b[1mOutput:\x1b[0m');
}
console.log(css);
if (compare) console.log();
});
}).resume();
}
/**
* Compile the given files.
*/
function compileFiles(files) {
files.forEach(compileFile);
}
/**
* Compile the given file.
*/
function compileFile(file) {
// ensure file exists
fs.lstat(file, function(err, stat){
if (err) throw err;
// file
if (stat.isFile()) {
fs.readFile(file, 'utf8', function(err, str){
if (err) throw err;
options.filename = file;
options._imports = [];
var style = stylus(str, options);
if (includeCSS) style.set('include css', true);
if (resolveURL) style.set('resolve url', true);
usePlugins(style);
importFiles(style);
style.render(function(err, css){
watchImports(file, options._imports);
if (err) {
if (watchers) {
console.error(err.stack || err.message);
} else {
throw err;
}
} else {
writeFile(file, css);
}
});
});
// directory
} else if (stat.isDirectory()) {
fs.readdir(file, function(err, files){
if (err) throw err;
files.filter(function(path){
return path.match(/\.styl$/);
}).map(function(path){
return join(file, path);
}).forEach(compileFile);
});
}
});
}
/**
* Write the given CSS output.
*/
function writeFile(file, css) {
// --out support
var path = dest
? join(dest, basename(file, '.styl') + '.css')
: file.replace('.styl', '.css');
fs.writeFile(path, css, function(err){
if (err) throw err;
console.log(' \033[90mcompiled\033[0m %s', path);
// --watch support
watch(file, compileFile);
});
}
/**
* Watch the given `file` and invoke `fn` when modified.
*/
function watch(file, fn) {
// not watching
if (!watchers) return;
// already watched
if (watchers[file]) return;
// watch the file itself
watchers[file] = true;
console.log(' \033[90mwatching\033[0m %s', file);
// if is windows use fs.watch api instead
// TODO: remove watchFile when fs.watch() works on osx etc
if (isWindows) {
fs.watch(file, function(event) {
if (event === 'change') fn(file);
});
} else {
fs.watchFile(file, { interval: 300 }, function(curr, prev) {
if (curr.mtime > prev.mtime) fn(file);
});
}
}
/**
* Watch `imports`, re-compiling `file` when they change.
*/
function watchImports(file, imports) {
imports.forEach(function(imported){
if (!imported.path) return;
watch(imported.path, function(){
compileFile(file);
});
});
}
/**
* Utilize plugins.
*/
function usePlugins(style) {
plugins.forEach(function(plugin){
var path = plugin.path;
var options = plugin.options;
fn = require(/^\.+\//.test(path) ? resolve(path) : path);
if ('function' != typeof fn) {
throw new Error('plugin ' + path + ' does not export a function');
}
style.use(fn(options));
});
if (urlFunction) {
style.define('url', stylus.url(urlFunction));
} else if (resolveURL) {
style.define('url', stylus.resolver());
}
}
/**
* Imports the indicated files.
*/
function importFiles(style) {
imports.forEach(function(file) {
style.import(file);
});
}

View File

@@ -0,0 +1,63 @@
/**
* Module dependencies.
*/
var stylus = require('./')
, fs = require('fs');
var times = ~~process.env.TIMES || 1
, avgs = [];
// test cases
var cases = fs.readdirSync('test/cases').filter(function(file){
return ~file.indexOf('.styl');
}).map(function(file){
return file.replace('.styl', '');
});
console.log();
cases.forEach(function(test){
var name = test.replace(/[-.]/g, ' ');
var path = 'test/cases/' + test + '.styl';
var styl = fs.readFileSync(path, 'utf8').replace(/\r/g, '');
var style = stylus(styl)
.set('filename', path)
.include(__dirname + '/test/images')
.include(__dirname + '/test/cases/import.basic')
.define('url', stylus.url());
if (~test.indexOf('compress')) style.set('compress', true);
var runs = []
, n = times
, start;
while (n--) {
start = new Date;
style.render(function(err){
if (err) throw err;
});
runs.push(new Date - start);
}
var avg = runs.reduce(function(sum, n){
return sum + n;
}) / times;
avgs.push(avg);
// im cool like that
var avgavg = avgs.reduce(function(sum, n){
return sum + n;
}) / avgs.length;
if (avg > avgavg) {
console.log(' \033[31m%s \033[31m%dms \033[90m+%dms\033[0m', name, avg | 0, avg - avgavg | 0);
} else {
console.log(' \033[36m%s \033[90m%dms\033[0m', name, avg | 0);
}
});
console.log();

View File

@@ -0,0 +1,4 @@
module.exports = process.env.STYLUS_COV
? require('./lib-cov/stylus')
: require('./lib/stylus');

View File

@@ -0,0 +1,2 @@
module.exports = require('./stylus');

View File

@@ -0,0 +1,156 @@
/*!
* Stylus - colors
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
module.exports = {
aliceblue: [240, 248, 255]
, antiquewhite: [250, 235, 215]
, aqua: [0, 255, 255]
, aquamarine: [127, 255, 212]
, azure: [240, 255, 255]
, beige: [245, 245, 220]
, bisque: [255, 228, 196]
, black: [0, 0, 0]
, blanchedalmond: [255, 235, 205]
, blue: [0, 0, 255]
, blueviolet: [138, 43, 226]
, brown: [165, 42, 42]
, burlywood: [222, 184, 135]
, cadetblue: [95, 158, 160]
, chartreuse: [127, 255, 0]
, chocolate: [210, 105, 30]
, coral: [255, 127, 80]
, cornflowerblue: [100, 149, 237]
, cornsilk: [255, 248, 220]
, crimson: [220, 20, 60]
, cyan: [0, 255, 255]
, darkblue: [0, 0, 139]
, darkcyan: [0, 139, 139]
, darkgoldenrod: [184, 132, 11]
, darkgray: [169, 169, 169]
, darkgreen: [0, 100, 0]
, darkgrey: [169, 169, 169]
, darkkhaki: [189, 183, 107]
, darkmagenta: [139, 0, 139]
, darkolivegreen: [85, 107, 47]
, darkorange: [255, 140, 0]
, darkorchid: [153, 50, 204]
, darkred: [139, 0, 0]
, darksalmon: [233, 150, 122]
, darkseagreen: [143, 188, 143]
, darkslateblue: [72, 61, 139]
, darkslategray: [47, 79, 79]
, darkslategrey: [47, 79, 79]
, darkturquoise: [0, 206, 209]
, darkviolet: [148, 0, 211]
, deeppink: [255, 20, 147]
, deepskyblue: [0, 191, 255]
, dimgray: [105, 105, 105]
, dimgrey: [105, 105, 105]
, dodgerblue: [30, 144, 255]
, firebrick: [178, 34, 34]
, floralwhite: [255, 255, 240]
, forestgreen: [34, 139, 34]
, fuchsia: [255, 0, 255]
, gainsboro: [220, 220, 220]
, ghostwhite: [248, 248, 255]
, gold: [255, 215, 0]
, goldenrod: [218, 165, 32]
, gray: [128, 128, 128]
, green: [0, 128, 0]
, greenyellow: [173, 255, 47]
, grey: [128, 128, 128]
, honeydew: [240, 255, 240]
, hotpink: [255, 105, 180]
, indianred: [205, 92, 92]
, indigo: [75, 0, 130]
, ivory: [255, 255, 240]
, khaki: [240, 230, 140]
, lavender: [230, 230, 250]
, lavenderblush: [255, 240, 245]
, lawngreen: [124, 252, 0]
, lemonchiffon: [255, 250, 205]
, lightblue: [173, 216, 230]
, lightcoral: [240, 128, 128]
, lightcyan: [224, 255, 255]
, lightgoldenrodyellow: [250, 250, 210]
, lightgray: [211, 211, 211]
, lightgreen: [144, 238, 144]
, lightgrey: [211, 211, 211]
, lightpink: [255, 182, 193]
, lightsalmon: [255, 160, 122]
, lightseagreen: [32, 178, 170]
, lightskyblue: [135, 206, 250]
, lightslategray: [119, 136, 153]
, lightslategrey: [119, 136, 153]
, lightsteelblue: [176, 196, 222]
, lightyellow: [255, 255, 224]
, lime: [0, 255, 0]
, limegreen: [50, 205, 50]
, linen: [250, 240, 230]
, magenta: [255, 0, 255]
, maroon: [128, 0, 0]
, mediumaquamarine: [102, 205, 170]
, mediumblue: [0, 0, 205]
, mediumorchid: [186, 85, 211]
, mediumpurple: [147, 112, 219]
, mediumseagreen: [60, 179, 113]
, mediumslateblue: [123, 104, 238]
, mediumspringgreen: [0, 250, 154]
, mediumturquoise: [72, 209, 204]
, mediumvioletred: [199, 21, 133]
, midnightblue: [25, 25, 112]
, mintcream: [245, 255, 250]
, mistyrose: [255, 228, 225]
, moccasin: [255, 228, 181]
, navajowhite: [255, 222, 173]
, navy: [0, 0, 128]
, oldlace: [253, 245, 230]
, olive: [128, 128, 0]
, olivedrab: [107, 142, 35]
, orange: [255, 165, 0]
, orangered: [255, 69, 0]
, orchid: [218, 112, 214]
, palegoldenrod: [238, 232, 170]
, palegreen: [152, 251, 152]
, paleturquoise: [175, 238, 238]
, palevioletred: [219, 112, 147]
, papayawhip: [255, 239, 213]
, peachpuff: [255, 218, 185]
, peru: [205, 133, 63]
, pink: [255, 192, 203]
, plum: [221, 160, 203]
, powderblue: [176, 224, 230]
, purple: [128, 0, 128]
, red: [255, 0, 0]
, rosybrown: [188, 143, 143]
, royalblue: [65, 105, 225]
, saddlebrown: [139, 69, 19]
, salmon: [250, 128, 114]
, sandybrown: [244, 164, 96]
, seagreen: [46, 139, 87]
, seashell: [255, 245, 238]
, sienna: [160, 82, 45]
, silver: [192, 192, 192]
, skyblue: [135, 206, 235]
, slateblue: [106, 90, 205]
, slategray: [119, 128, 144]
, slategrey: [119, 128, 144]
, snow: [255, 255, 250]
, springgreen: [0, 255, 127]
, steelblue: [70, 130, 180]
, tan: [210, 180, 140]
, teal: [0, 128, 128]
, thistle: [216, 191, 216]
, tomato: [255, 99, 71]
, turquoise: [64, 224, 208]
, violet: [238, 130, 238]
, wheat: [245, 222, 179]
, white: [255, 255, 255]
, whitesmoke: [245, 245, 245]
, yellow: [255, 255, 0]
, yellowgreen: [154, 205, 5]
};

View File

@@ -0,0 +1,130 @@
/*!
* Stylus - CSS to Stylus conversion
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Convert the given `css` to Stylus source.
*
* @param {String} css
* @return {String}
* @api public
*/
module.exports = function(css){
return new Converter(css).stylus();
};
/**
* Initialize a new `Converter` with the given `css`.
*
* @param {String} css
* @api private
*/
function Converter(css) {
var cssom = require('cssom');
this.css = css;
this.types = cssom.CSSRule;
this.root = cssom.parse(css);
this.indents = 0;
}
/**
* Convert to Stylus.
*
* @return {String}
* @api private
*/
Converter.prototype.stylus = function(){
return this.visitRules(this.root.cssRules);
};
/**
* Return indent string.
*
* @return {String}
* @api private
*/
Converter.prototype.__defineGetter__('indent', function(){
return Array(this.indents + 1).join(' ');
});
/**
* Visit `node`.
*
* @param {CSSRule} node
* @return {String}
* @api private
*/
Converter.prototype.visit = function(node){
switch (node.type) {
case this.types.STYLE_RULE:
return this.visitStyle(node);
case this.types.MEDIA_RULE:
return this.visitMedia(node);
}
};
/**
* Visit the rules on `node`.
*
* @param {CSSRule} node
* @return {String}
* @api private
*/
Converter.prototype.visitRules = function(node){
var buf = '';
for (var i = 0, len = node.length; i < len; ++i) {
buf += this.visit(node[i]);
}
return buf;
};
/**
* Visit CSSMediaRule `node`.
*
* @param {CSSMediaRule} node
* @return {String}
* @api private
*/
Converter.prototype.visitMedia = function(node){
var buf = this.indent + '@media ';
for (var i = 0, len = node.media.length; i < len; ++i) {
buf += node.media[i];
}
buf += '\n';
++this.indents;
buf += this.visitRules(node.cssRules);
--this.indents;
return buf;
};
/**
* Visit CSSStyleRule `node`.`
*
* @param {CSSStyleRule} node
* @return {String}
* @api private
*/
Converter.prototype.visitStyle = function(node){
var buf = this.indent + node.selectorText + '\n';
++this.indents;
for (var i = 0, len = node.style.length; i < len; ++i) {
var prop = node.style[i]
, val = node.style[prop]
, importance = node.style['_importants'][prop] ? ' !important' : '';
if (prop) {
buf += this.indent + prop + ': ' + val + importance + '\n';
}
}
--this.indents;
return buf + '\n';
};

View File

@@ -0,0 +1,58 @@
/*!
* Stylus - errors
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Expose constructors.
*/
exports.ParseError = ParseError;
exports.SyntaxError = SyntaxError;
/**
* Inherit from `Error.prototype`.
*/
SyntaxError.prototype.__proto__ = Error.prototype;
/**
* Initialize a new `ParseError` with the given `msg`.
*
* @param {String} msg
* @api private
*/
function ParseError(msg) {
this.name = 'ParseError';
this.message = msg;
Error.captureStackTrace(this, ParseError);
}
/**
* Inherit from `Error.prototype`.
*/
ParseError.prototype.__proto__ = Error.prototype;
/**
* Initialize a new `SyntaxError` with the given `msg`.
*
* @param {String} msg
* @api private
*/
function SyntaxError(msg) {
this.name = 'SyntaxError';
this.message = msg;
Error.captureStackTrace(this, ParseError);
}
/**
* Inherit from `Error.prototype`.
*/
SyntaxError.prototype.__proto__ = Error.prototype;

View File

@@ -0,0 +1,162 @@
/*!
* Stylus - plugin - url
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var utils = require('../utils')
, nodes = require('../nodes')
, fs = require('fs')
, path = require('path')
, sax = require('sax');
/**
* Initialize a new `Image` with the given `ctx` and `path.
*
* @param {Evaluator} ctx
* @param {String} path
* @api private
*/
var Image = module.exports = function Image(ctx, path) {
this.ctx = ctx;
this.path = utils.lookup(path, ctx.paths);
if (!this.path) throw new Error('failed to locate file ' + path);
};
/**
* Open the image for reading.
*
* @api private
*/
Image.prototype.open = function(){
this.fd = fs.openSync(this.path, 'r');
this.length = fs.fstatSync(this.fd).size;
this.extname = path.extname(this.path).slice(1);
};
/**
* Close the file.
*
* @api private
*/
Image.prototype.close = function(){
if (this.fd) fs.closeSync(this.fd);
};
/**
* Return the type of image, supports:
*
* - gif
* - png
* - jpeg
* - svg
*
* @return {String}
* @api private
*/
Image.prototype.type = function(){
var type
, buf = new Buffer(4);
fs.readSync(this.fd, buf, 0, 4, 0);
// GIF
if (0x47 == buf[0] && 0x49 == buf[1] && 0x46 == buf[2]) type = 'gif';
// PNG
else if (0x50 == buf[1] && 0x4E == buf[2] && 0x47 == buf[3]) type = 'png';
// JPEG
else if (0xff == buf[0] && 0xd8 == buf[1]) type = 'jpeg';
// SVG
else if ('svg' == this.extname) type = this.extname;
return type;
};
/**
* Return image dimensions `[width, height]`.
*
* @return {Array}
* @api private
*/
Image.prototype.size = function(){
var type = this.type()
, width
, height
, buf
, offset
, blockSize
, parser;
function uint16(b) { return b[1] << 8 | b[0]; }
function uint32(b) { return b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; }
// Determine dimensions
switch (type) {
case 'jpeg':
buf = new Buffer(this.length);
fs.readSync(this.fd, buf, 0, this.length);
offset = 4;
blockSize = buf[offset] << 8 | buf[offset + 1];
while (offset < this.length) {
offset += blockSize;
if (offset >= this.length || 0xff != buf[offset]) break;
// SOF0 or SOF2 (progressive)
if (0xc0 == buf[offset + 1] || 0xc2 == buf[offset + 1]) {
height = buf[offset + 5] << 8 | buf[offset + 6];
width = buf[offset + 7] << 8 | buf[offset + 8];
} else {
offset += 2;
blockSize = buf[offset] << 8 | buf[offset + 1];
}
}
break;
case 'png':
buf = new Buffer(8);
// IHDR chunk width / height uint32_t big-endian
fs.readSync(this.fd, buf, 0, 8, 16);
width = uint32(buf);
height = uint32(buf.slice(4, 8));
break;
case 'gif':
buf = new Buffer(4);
// width / height uint16_t little-endian
fs.readSync(this.fd, buf, 0, 4, 6);
width = uint16(buf);
height = uint16(buf.slice(2, 4));
break;
case 'svg':
offset = Math.min(this.length, 1024);
buf = new Buffer(offset);
fs.readSync(this.fd, buf, 0, offset);
buf = buf.toString('utf8');
parser = sax.parser(true);
parser.onopentag = function(node) {
if ('svg' == node.name && node.attributes.width && node.attributes.height) {
width = parseInt(node.attributes.width, 10);
height = parseInt(node.attributes.height, 10);
}
};
parser.write(buf).close();
break;
}
if ('number' != typeof width) throw new Error('failed to find width of "' + this.path + '"');
if ('number' != typeof height) throw new Error('failed to find height of "' + this.path + '"');
return [width, height];
};

View File

@@ -0,0 +1,953 @@
/*!
* Stylus - Evaluator - built-in functions
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Compiler = require('../visitor/compiler')
, nodes = require('../nodes')
, utils = require('../utils')
, Image = require('./image')
, units = require('../units')
, path = require('path')
, fs = require('fs');
/**
* Color component name map.
*/
var componentMap = {
red: 'r'
, green: 'g'
, blue: 'b'
, alpha: 'a'
, hue: 'h'
, saturation: 's'
, lightness: 'l'
};
/**
* Color component unit type map.
*/
var unitMap = {
hue: 'deg'
, saturation: '%'
, lightness: '%'
};
/**
* Color type map.
*/
var typeMap = {
red: 'rgba'
, blue: 'rgba'
, green: 'rgba'
, alpha: 'rgba'
, hue: 'hsla'
, saturation: 'hsla'
, lightness: 'hsla'
};
/**
* Convert the given `color` to an `HSLA` node,
* or h,s,l,a component values.
*
* Examples:
*
* hsla(10deg, 50%, 30%, 0.5)
* // => HSLA
*
* hsla(#ffcc00)
* // => HSLA
*
* @param {RGBA|HSLA|Unit} hue
* @param {Unit} saturation
* @param {Unit} lightness
* @param {Unit} alpha
* @return {HSLA}
* @api public
*/
exports.hsla = function hsla(hue, saturation, lightness, alpha){
switch (arguments.length) {
case 1:
utils.assertColor(hue);
return hue.hsla;
default:
utils.assertType(hue, 'unit', 'hue');
utils.assertType(saturation, 'unit', 'saturation');
utils.assertType(lightness, 'unit', 'lightness');
utils.assertType(alpha, 'unit', 'alpha');
if (alpha && '%' == alpha.type) alpha.val /= 100;
return new nodes.HSLA(
hue.val
, saturation.val
, lightness.val
, alpha.val);
}
};
/**
* Convert the given `color` to an `HSLA` node,
* or h,s,l component values.
*
* Examples:
*
* hsl(10, 50, 30)
* // => HSLA
*
* hsl(#ffcc00)
* // => HSLA
*
* @param {Unit|HSLA|RGBA} hue
* @param {Unit} saturation
* @param {Unit} lightness
* @return {HSLA}
* @api public
*/
exports.hsl = function hsl(hue, saturation, lightness){
if (1 == arguments.length) {
utils.assertColor(hue, 'color');
return hue.hsla;
} else {
return exports.hsla(
hue
, saturation
, lightness
, new nodes.Unit(1));
}
};
/**
* Return type of `node`.
*
* Examples:
*
* type(12)
* // => 'unit'
*
* type(#fff)
* // => 'color'
*
* type(type)
* // => 'function'
*
* type(unbound)
* typeof(unbound)
* type-of(unbound)
* // => 'ident'
*
* @param {Node} node
* @return {String}
* @api public
*/
exports.type =
exports.typeof =
exports['type-of'] = function type(node){
utils.assertPresent(node, 'expression');
return node.nodeName;
};
/**
* Return component `name` for the given `color`.
*
* @param {RGBA|HSLA} color
* @param {String} name
* @return {Unit}
* @api public
*/
exports.component = function component(color, name) {
utils.assertColor(color, 'color');
utils.assertString(name, 'name');
var name = name.string
, unit = unitMap[name]
, type = typeMap[name]
, name = componentMap[name];
if (!name) throw new Error('invalid color component "' + name + '"');
return new nodes.Unit(color[type][name], unit);
};
/**
* Return the basename of `path`.
*
* @param {String} path
* @return {String}
* @api public
*/
exports.basename = function basename(p, ext){
utils.assertString(p, 'path');
return path.basename(p.val, ext && ext.val);
};
/**
* Return the dirname of `path`.
*
* @param {String} path
* @return {String}
* @api public
*/
exports.dirname = function dirname(p){
utils.assertString(p, 'path');
return path.dirname(p.val);
};
/**
* Return the extname of `path`.
*
* @param {String} path
* @return {String}
* @api public
*/
exports.extname = function extname(p){
utils.assertString(p, 'path');
return path.extname(p.val);
};
/**
* Peform a path join.
*
* @param {String} path
* @return {String}
* @api public
*/
(exports.pathjoin = function pathjoin(){
var paths = [].slice.call(arguments).map(function(path){
return path.first.string;
});
return path.join.apply(null, paths);
}).raw = true;
/**
* Return the red component of the given `color`.
*
* Examples:
*
* red(#c00)
* // => 204
*
* @param {RGBA|HSLA} color
* @return {Unit}
* @api public
*/
exports.red = function red(color){
return exports.component(color, new nodes.String('red'));
};
/**
* Return the green component of the given `color`.
*
* Examples:
*
* green(#0c0)
* // => 204
*
* @param {RGBA|HSLA} color
* @return {Unit}
* @api public
*/
exports.green = function green(color){
return exports.component(color, new nodes.String('green'));
};
/**
* Return the blue component of the given `color`.
*
* Examples:
*
* blue(#00c)
* // => 204
*
* @param {RGBA|HSLA} color
* @return {Unit}
* @api public
*/
exports.blue = function blue(color){
return exports.component(color, new nodes.String('blue'));
};
/**
* Return a `RGBA` from the r,g,b,a channels.
*
* Examples:
*
* rgba(255,0,0,0.5)
* // => rgba(255,0,0,0.5)
*
* rgba(255,0,0,1)
* // => #ff0000
*
* rgba(#ffcc00, 50%)
* // rgba(255,204,0,0.5)
*
* @param {Unit|RGBA|HSLA} red
* @param {Unit} green
* @param {Unit} blue
* @param {Unit} alpha
* @return {RGBA}
* @api public
*/
exports.rgba = function rgba(red, green, blue, alpha){
switch (arguments.length) {
case 1:
utils.assertColor(red);
var color = red.rgba;
return new nodes.RGBA(
color.r
, color.g
, color.b
, color.a);
case 2:
utils.assertColor(red);
var color = red.rgba;
utils.assertType(green, 'unit', 'alpha');
if ('%' == green.type) green.val /= 100;
return new nodes.RGBA(
color.r
, color.g
, color.b
, green.val);
default:
utils.assertType(red, 'unit', 'red');
utils.assertType(green, 'unit', 'green');
utils.assertType(blue, 'unit', 'blue');
utils.assertType(alpha, 'unit', 'alpha');
var r = '%' == red.type ? Math.round(red.val * 2.55) : red.val;
var g = '%' == green.type ? Math.round(green.val * 2.55) : green.val;
var b = '%' == blue.type ? Math.round(blue.val * 2.55) : blue.val;
if (alpha && '%' == alpha.type) alpha.val /= 100;
return new nodes.RGBA(
r
, g
, b
, alpha.val);
}
};
/**
* Return a `RGBA` from the r,g,b channels.
*
* Examples:
*
* rgb(255,204,0)
* // => #ffcc00
*
* rgb(#fff)
* // => #fff
*
* @param {Unit|RGBA|HSLA} red
* @param {Unit} green
* @param {Unit} blue
* @return {RGBA}
* @api public
*/
exports.rgb = function rgb(red, green, blue){
switch (arguments.length) {
case 1:
utils.assertColor(red);
var color = red.rgba;
return new nodes.RGBA(
color.r
, color.g
, color.b
, 1);
default:
return exports.rgba(
red
, green
, blue
, new nodes.Unit(1));
}
};
/**
* Convert a .json file into stylus variables
* Nested variable object keys are joined with a dash (-)
*
* Given this sample media-queries.json file:
* {
* "small": "screen and (max-width:400px)",
* "tablet": {
* "landscape": "screen and (min-width:600px) and (orientation:landscape)",
* "portrait": "screen and (min-width:600px) and (orientation:portrait)"
* }
* }
*
* Examples:
*
* json('media-queries.json')
*
* @media small
* // => @media screen and (max-width:400px)
*
* @media tablet-landscape
* // => @media screen and (min-width:600px) and (orientation:landscape)
*
* @param {String} path
* @api public
*/
exports.json = function(path){
utils.assertString(path, 'path');
// lookup
path = path.string;
var found = utils.lookup(path, this.options.paths, this.options.filename);
if (!found) throw new Error('failed to locate .json file ' + path);
// read
var str = fs.readFileSync(found, 'utf8');
convert.call(this, JSON.parse(str));
return;
function convert(obj, prefix){
prefix = prefix ? prefix + '-' : '';
for (var key in obj){
var val = obj[key];
var name = prefix + key;
if ('object' == typeof val) {
convert.call(this, val, name);
} else {
val = utils.coerce(val);
if ('string' == val.nodeName) val = parseUnit(val.string) || new nodes.Literal(val.string);
this.global.scope.add({ name: name, val: val });
}
}
}
};
/**
* Use the given `plugin`
*
* Examples:
*
* use("plugins/add.js")
*
* width add(10, 100)
* // => width: 110
*/
exports.use = function(plugin){
utils.assertString(plugin, 'path');
// lookup
plugin = plugin.string;
var found = utils.lookup(plugin, this.options.paths, this.options.filename);
if (!found) throw new Error('failed to locate plugin file ' + plugin);
// use
var fn = require(path.resolve(found));
if ('function' != typeof fn) {
throw new Error('plugin ' + path + ' does not export a function');
}
this.renderer.use(fn(this.options));
}
/**
* Unquote the given `str`.
*
* Examples:
*
* unquote("sans-serif")
* // => sans-serif
*
* unquote(sans-serif)
* // => sans-serif
*
* @param {String|Ident} string
* @return {Literal}
* @api public
*/
exports.unquote = function unquote(string){
utils.assertString(string, 'string');
return new nodes.Literal(string.string);
};
/**
* Assign `type` to the given `unit` or return `unit`'s type.
*
* @param {Unit} unit
* @param {String|Ident} type
* @return {Unit}
* @api public
*/
exports.unit = function unit(unit, type){
utils.assertType(unit, 'unit', 'unit');
// Assign
if (type) {
utils.assertString(type, 'type');
return new nodes.Unit(unit.val, type.string);
} else {
return unit.type || '';
}
};
/**
* Lookup variable `name` or return Null.
*
* @param {String} name
* @return {Mixed}
* @api public
*/
exports.lookup = function lookup(name){
utils.assertType(name, 'string', 'name');
var node = this.lookup(name.val);
if (!node) return nodes.null;
return this.visit(node);
};
/**
* Perform `op` on the `left` and `right` operands.
*
* @param {String} op
* @param {Node} left
* @param {Node} right
* @return {Node}
* @api public
*/
exports.operate = function operate(op, left, right){
utils.assertType(op, 'string', 'op');
utils.assertPresent(left, 'left');
utils.assertPresent(right, 'right');
return left.operate(op.val, right);
};
/**
* Test if `val` matches the given `pattern`.
*
* Examples:
*
* match('^foo(bar)?', foo)
* match('^foo(bar)?', foobar)
* match('^foo(bar)?', 'foo')
* match('^foo(bar)?', 'foobar')
* // => true
*
* match('^foo(bar)?', 'bar')
* // => false
*
* @param {String} pattern
* @param {String|Ident} val
* @return {Boolean}
* @api public
*/
exports.match = function match(pattern, val){
utils.assertType(pattern, 'string', 'pattern');
utils.assertString(val, 'val');
var re = new RegExp(pattern.val);
return nodes.Boolean(re.test(val.string));
};
/**
* Return length of the given `expr`.
*
* @param {Expression} expr
* @return {Unit}
* @api public
*/
(exports.length = function length(expr){
if (expr) {
return expr.nodes
? utils.unwrap(expr).nodes.length
: 1;
}
return 0;
}).raw = true;
/**
* Inspect the given `expr`.
*
* @param {Expression} expr
* @api public
*/
(exports.p = function p(){
[].slice.call(arguments).forEach(function(expr){
expr = utils.unwrap(expr);
if (!expr.nodes.length) return;
console.log('\033[90minspect:\033[0m %s', expr.toString().replace(/^\(|\)$/g, ''));
})
return nodes.null;
}).raw = true;
/**
* Throw an error with the given `msg`.
*
* @param {String} msg
* @api public
*/
exports.error = function error(msg){
utils.assertType(msg, 'string', 'msg');
throw new Error(msg.val);
};
/**
* Warn with the given `msg` prefixed by "Warning: ".
*
* @param {String} msg
* @api public
*/
exports.warn = function warn(msg){
utils.assertType(msg, 'string', 'msg');
console.warn('Warning: %s', msg.val);
return nodes.null;
};
/**
* Output stack trace.
*
* @api public
*/
exports.trace = function trace(){
console.log(this.stack);
return nodes.null;
};
/**
* Push the given args to `expr`.
*
* @param {Expression} expr
* @param {Node} ...
* @return {Unit}
* @api public
*/
(exports.push = exports.append = function(expr){
expr = utils.unwrap(expr);
for (var i = 1, len = arguments.length; i < len; ++i) {
expr.nodes.push(utils.unwrap(arguments[i]));
}
return expr.nodes.length;
}).raw = true;
/**
* Pop a value from `expr`.
*
* @param {Expression} expr
* @return {Node}
* @api public
*/
(exports.pop = function pop(expr) {
expr = utils.unwrap(expr);
return expr.nodes.pop();
}).raw = true;
/**
* Unshift the given args to `expr`.
*
* @param {Expression} expr
* @param {Node} ...
* @return {Unit}
* @api public
*/
(exports.unshift = exports.prepend = function(expr){
expr = utils.unwrap(expr);
for (var i = 1, len = arguments.length; i < len; ++i) {
expr.nodes.unshift(utils.unwrap(arguments[i]));
}
return expr.nodes.length;
}).raw = true;
/**
* Shift an element from `expr`.
*
* @param {Expression} expr
* @return {Node}
* @api public
*/
(exports.shift = function(expr){
expr = utils.unwrap(expr);
return expr.nodes.shift();
}).raw = true;
/**
* Return a `Literal` with the given `fmt`, and
* variable number of arguments.
*
* @param {String} fmt
* @param {Node} ...
* @return {Literal}
* @api public
*/
(exports.s = function s(fmt){
fmt = utils.unwrap(fmt).nodes[0];
utils.assertString(fmt);
var self = this
, str = fmt.string
, args = arguments
, i = 1;
// format
str = str.replace(/%(s|d)/g, function(_, specifier){
var arg = args[i++] || nodes.null;
switch (specifier) {
case 's':
return new Compiler(arg, self.options).compile();
case 'd':
arg = utils.unwrap(arg).first;
if ('unit' != arg.nodeName) throw new Error('%d requires a unit');
return arg.val;
}
});
return new nodes.Literal(str);
}).raw = true;
/**
* Return a `Literal` `num` converted to the provided `base`, padded to `width`
* with zeroes (default width is 2)
*
* @param {Number} num
* @param {Number} base
* @param {Number} width
* @return {Literal}
* @api public
*/
(exports['base-convert'] = function(num, base, width) {
utils.assertPresent(num, 'number');
utils.assertPresent(base, 'base');
num = utils.unwrap(num).nodes[0].val;
base = utils.unwrap(base).nodes[0].val;
width = (width && utils.unwrap(width).nodes[0].val) || 2;
var result = Number(num).toString(base);
while (result.length < width) {
result = "0" + result;
}
return new nodes.Literal(result);
}).raw = true;
/**
* Return the opposites of the given `positions`.
*
* Examples:
*
* opposite-position(top left)
* // => bottom right
*
* @param {Expression} positions
* @return {Expression}
* @api public
*/
(exports['opposite-position'] = function oppositePosition(positions){
var expr = [];
utils.unwrap(positions).nodes.forEach(function(pos, i){
utils.assertString(pos, 'position ' + i);
pos = (function(){ switch (pos.string) {
case 'top': return 'bottom';
case 'bottom': return 'top';
case 'left': return 'right';
case 'right': return 'left';
case 'center': return 'center';
default: throw new Error('invalid position ' + pos);
}})();
expr.push(new nodes.Literal(pos));
});
return expr;
}).raw = true;
/**
* Return the width and height of the given `img` path.
*
* Examples:
*
* image-size('foo.png')
* // => 200px 100px
*
* image-size('foo.png')[0]
* // => 200px
*
* image-size('foo.png')[1]
* // => 100px
*
* Can be used to test if the image exists,
* using an optional argument set to `true`
* (without this argument this function throws error
* if there is no such image).
*
* Example:
*
* image-size('nosuchimage.png', true)[0]
* // => 0
*
* @param {String} img
* @param {Boolean} ignoreErr
* @return {Expression}
* @api public
*/
exports['image-size'] = function imageSize(img, ignoreErr) {
utils.assertType(img, 'string', 'img');
try {
var img = new Image(this, img.string);
} catch (err) {
if (ignoreErr) {
return [new nodes.Unit(0), new nodes.Unit(0)];
} else {
throw err;
}
}
// Read size
img.open();
var size = img.size();
img.close();
// Return (w h)
var expr = [];
expr.push(new nodes.Unit(size[0], 'px'));
expr.push(new nodes.Unit(size[1], 'px'));
return expr;
};
/**
* Apply Math `fn` to `n`.
*
* @param {Unit} n
* @param {String} fn
* @return {Unit}
* @api private
*/
exports['-math'] = function math(n, fn){
return new nodes.Unit(Math[fn.string](n.val), n.type);
};
/**
* Get Math `prop`.
*
* @param {String} prop
* @return {Unit}
* @api private
*/
exports['-math-prop'] = function math(prop){
return new nodes.Unit(Math[prop.string]);
};
/**
* Buffer the given js `str`.
*
* @param {String} str
* @return {JSLiteral}
* @api private
*/
exports.js = function js(str){
utils.assertString(str, 'str');
return new nodes.JSLiteral(str.val);
};
/**
* Adjust HSL `color` `prop` by `amount`.
*
* @param {RGBA|HSLA} color
* @param {String} prop
* @param {Unit} amount
* @return {RGBA}
* @api private
*/
exports['-adjust'] = function adjust(color, prop, amount){
var hsl = color.hsla.clone();
prop = { hue: 'h', saturation: 's', lightness: 'l' }[prop.string];
if (!prop) throw new Error('invalid adjustment property');
var val = amount.val;
if ('%' == amount.type){
val = 'l' == prop && val > 0
? (100 - hsl[prop]) * val / 100
: hsl[prop] * (val / 100);
}
hsl[prop] += val;
return hsl.rgba;
};
/**
* Return a clone of the given `expr`.
*
* @param {Expression} expr
* @return {Node}
* @api public
*/
(exports.clone = function clone(expr){
utils.assertPresent(expr, 'expr');
return expr.clone();
}).raw = true;
/**
* Add property `name` with the given `expr`
* to the mixin-able block.
*
* @param {String|Ident|Literal} name
* @param {Expression} expr
* @return {Property}
* @api public
*/
(exports['add-property'] = function addProperty(name, expr){
utils.assertType(name, 'expression', 'name');
name = utils.unwrap(name).first;
utils.assertString(name, 'name');
utils.assertType(expr, 'expression', 'expr');
var prop = new nodes.Property([name], expr);
var block = this.closestBlock;
var len = block.nodes.length
, head = block.nodes.slice(0, block.index)
, tail = block.nodes.slice(block.index++, len);
head.push(prop);
block.nodes = head.concat(tail);
return prop;
}).raw = true;
/**
* Attempt to parse unit `str`.
*
* @param {String} str
* @return {Unit}
* @api public
*/
function parseUnit(str){
var m = str.match(/^(\d+)(.*)/);
if (!m) return;
var n = parseInt(m[1], 10);
var type = m[2];
return new nodes.Unit(n, type);
}

View File

@@ -0,0 +1,255 @@
vendors = moz webkit o ms official
// stringify the given arg
-string(arg)
type(arg) + ' ' + arg
// require a color
require-color(color)
unless color is a 'color'
error('RGB or HSL value expected, got a ' + -string(color))
// require a unit
require-unit(n)
unless n is a 'unit'
error('unit expected, got a ' + -string(n))
// require a string
require-string(str)
unless str is a 'string' or str is a 'ident'
error('string expected, got a ' + -string(str))
// apply js Math function
math(n, fn)
require-unit(n)
require-string(fn)
-math(n, fn)
// adjust the given color's property by amount
adjust(color, prop, amount)
require-color(color)
require-string(prop)
require-unit(amount)
-adjust(color, prop, amount)
// Math functions
abs(n) { math(n, 'abs') }
min(a, b) { a < b ? a : b }
max(a, b) { a > b ? a : b }
// Trigonometrics
PI = -math-prop('PI')
radians-to-degrees(angle)
angle * (180 / PI)
degrees-to-radians(angle)
unit(angle * (PI / 180),'')
sin(n)
n = degrees-to-radians(n) if unit(n) == 'deg'
round(math(n, 'sin'), 9)
cos(n)
n = degrees-to-radians(n) if unit(n) == 'deg'
round(math(n, 'cos'), 9)
tan(n)
round(sin(n) / cos(n), 9)
// Rounding Math functions
ceil(n, precision = 0)
multiplier = 10 ** precision
math(n * multiplier, 'ceil') / multiplier
floor(n, precision = 0)
multiplier = 10 ** precision
math(n * multiplier, 'floor') / multiplier
round(n, precision = 0)
multiplier = 10 ** precision
math(n * multiplier, 'round') / multiplier
// return the sum of the given numbers
sum(nums)
sum = 0
sum += n for n in nums
// return the average of the given numbers
avg(nums)
sum(nums) / length(nums)
// return a unitless number, or pass through
remove-unit(n)
if typeof(n) is "unit"
unit(n, "")
else
n
// convert a percent to a decimal, or pass through
percent-to-decimal(n)
if unit(n) is "%"
remove-unit(n) / 100
else
n
// color components
alpha(color) { component(hsl(color), 'alpha') }
hue(color) { component(hsl(color), 'hue') }
saturation(color) { component(hsl(color), 'saturation') }
lightness(color) { component(hsl(color), 'lightness') }
// check if n is an odd number
odd(n)
1 == n % 2
// check if n is an even number
even(n)
0 == n % 2
// check if color is light
light(color)
lightness(color) >= 50%
// check if color is dark
dark(color)
lightness(color) < 50%
// desaturate color by amount
desaturate(color, amount)
adjust(color, 'saturation', - amount)
// saturate color by amount
saturate(color, amount)
adjust(color, 'saturation', amount)
// darken by the given amount
darken(color, amount)
adjust(color, 'lightness', - amount)
// lighten by the given amount
lighten(color, amount)
adjust(color, 'lightness', amount)
// decerase opacity by amount
fade-out(color, amount)
color - rgba(black, percent-to-decimal(amount))
// increase opacity by amount
fade-in(color, amount)
color + rgba(black, percent-to-decimal(amount))
// spin hue by a given amount
spin(color, amount)
color + unit(amount, deg)
// mix two colors by a given amount
mix(color1, color2, weight = 50%)
unless weight in 0..100
error("Weight must be between 0% and 100%")
if length(color1) == 2
weight = color1[0]
color1 = color1[1]
else if length(color2) == 2
weight = 100 - color2[0]
color2 = color2[1]
require-color(color1)
require-color(color2)
p = unit(weight / 100, '')
w = p * 2 - 1
a = alpha(color1) - alpha(color2)
w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2
w2 = 1 - w1
channels = (red(color1) red(color2)) (green(color1) green(color2)) (blue(color1) blue(color2))
rgb = ()
for pair in channels
push(rgb, floor(pair[0] * w1 + pair[1] * w2))
a1 = alpha(color1) * p
a2 = alpha(color1) * (1 - p)
alpha = a1 + a2
rgba(rgb[0], rgb[1], rgb[2], alpha)
// invert colors, leave alpha intact
invert(color)
r = 255 - red(color)
g = 255 - green(color)
b = 255 - blue(color)
rgba(r,g,b,alpha(color))
// return the last value in the given expr
last(expr)
expr[length(expr) - 1]
// return keys in the given pairs
keys(pairs)
ret = ()
for pair in pairs
push(ret, pair[0]);
ret
// return values in the given pairs
values(pairs)
ret = ()
for pair in pairs
push(ret, pair[1]);
ret
// join values with the given delimiter
join(delim, vals...)
buf = ''
vals = vals[0] if length(vals) == 1
for val, i in vals
buf += i ? delim + val : val
// add a CSS rule to the containing block
// - This definition allows add-property to be used as a mixin
// - It has the same effect as interpolation but allows users
// to opt for a functional style
add-property-function = add-property
add-property(name, expr)
if mixin
{name} expr
else
add-property-function(name, expr)

View File

@@ -0,0 +1,64 @@
/**
* Module dependencies.
*/
var Compiler = require('../visitor/compiler')
, nodes = require('../nodes')
, parse = require('url').parse
, relative = require('path').relative
, dirname = require('path').dirname
, utils = require('../utils');
/**
* Return a url() function with the given `options`.
*
* Options:
*
* - `paths` resolution path(s), merged with general lookup paths
*
* Examples:
*
* stylus(str)
* .set('filename', __dirname + '/css/test.styl')
* .define('url', stylus.resolver({ paths: [__dirname + '/public'] }))
* .render(function(err, css){ ... })
*
* @param {Object} options
* @return {Function}
* @api public
*/
module.exports = function(options) {
options = options || {};
var _paths = options.paths || [];
function url(url) {
// Compile the url
var compiler = new Compiler(url);
compiler.isURL = true;
var url = url.nodes.map(function(node){
return compiler.visit(node);
}).join('');
// Parse literal
var url = parse(url)
, literal = new nodes.Literal('url("' + url.href + '")')
, paths = _paths.concat(this.paths)
, found;
// Absolute
if (url.protocol) return literal;
// Lookup
var found = utils.lookup(url.pathname, paths);
// Failed to lookup
if (!found) return literal;
return new nodes.Literal('url("' + relative(dirname(this.filename), found) +'")');
};
url.raw = true;
return url;
};

View File

@@ -0,0 +1,105 @@
/*!
* Stylus - plugin - url
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Compiler = require('../visitor/compiler')
, nodes = require('../nodes')
, parse = require('url').parse
, extname = require('path').extname
, utils = require('../utils')
, fs = require('fs');
/**
* Mime table.
*/
var defaultMimes = {
'.gif': 'image/gif'
, '.png': 'image/png'
, '.jpg': 'image/jpeg'
, '.jpeg': 'image/jpeg'
, '.svg': 'image/svg+xml'
, '.ttf': 'application/x-font-ttf'
, '.eot': 'application/vnd.ms-fontobject'
, '.woff': 'application/x-font-woff'
};
/**
* Return a url() function with the given `options`.
*
* Options:
*
* - `limit` bytesize limit defaulting to 30Kb
* - `paths` image resolution path(s), merged with general lookup paths
*
* Examples:
*
* stylus(str)
* .set('filename', __dirname + '/css/test.styl')
* .define('url', stylus.url({ paths: [__dirname + '/public'] }))
* .render(function(err, css){ ... })
*
* @param {Object} options
* @return {Function}
* @api public
*/
module.exports = function(options) {
options = options || {};
var _paths = options.paths || [];
var sizeLimit = null != options.limit ? options.limit : 30000;
var mimes = options.mimes || defaultMimes;
function fn(url){
// Compile the url
var compiler = new Compiler(url);
compiler.isURL = true;
url = url.nodes.map(function(node){
return compiler.visit(node);
}).join('');
// Parse literal
url = parse(url);
var ext = extname(url.pathname)
, mime = mimes[ext]
, literal = new nodes.Literal('url("' + url.href + '")')
, paths = _paths.concat(this.paths)
, buf;
// Not supported
if (!mime) return literal;
// Absolute
if (url.protocol) return literal;
// Lookup
var found = utils.lookup(url.pathname, paths);
// Failed to lookup
if (!found) return literal;
// Read data
buf = fs.readFileSync(found);
// To large
if (false !== sizeLimit && buf.length > sizeLimit) return literal;
// Encode
return new nodes.Literal('url("data:' + mime + ';base64,' + buf.toString('base64') + '")');
};
fn.raw = true;
return fn;
};
// Exporting default mimes so we could easily access them
module.exports.mimes = defaultMimes;

View File

@@ -0,0 +1,807 @@
/*!
* Stylus - Lexer
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Token = require('./token')
, nodes = require('./nodes')
, errors = require('./errors')
, units = require('./units');
/**
* Expose `Lexer`.
*/
exports = module.exports = Lexer;
/**
* Operator aliases.
*/
var alias = {
'and': '&&'
, 'or': '||'
, 'is': '=='
, 'isnt': '!='
, 'is not': '!='
, ':=': '?='
};
/**
* Units.
*/
units = units.join('|');
/**
* Unit RegExp.
*/
var unit = new RegExp('^(-)?(\\d+\\.\\d+|\\d+|\\.\\d+)(' + units + ')?[ \\t]*');
/**
* Initialize a new `Lexer` with the given `str` and `options`.
*
* @param {String} str
* @param {Object} options
* @api private
*/
function Lexer(str, options) {
options = options || {};
this.stash = [];
this.indentStack = [];
this.indentRe = null;
this.lineno = 1;
function comment(str, val, offset, s) {
var inComment = s.lastIndexOf('/*', offset) > s.lastIndexOf('*/', offset)
|| s.lastIndexOf('//', offset) > s.lastIndexOf('\n', offset);
return inComment
? str
: val;
};
this.str = str
.replace(/\s+$/, '\n')
.replace(/\r\n?/g, '\n')
.replace(/\\ *\n/g, ' ')
.replace(/([,(]|:(?!\/\/[^ ])) *(?:\/\/[^\n]*)?\n\s*/g, comment)
.replace(/\s*\n *([,)])/g, comment);
};
/**
* Lexer prototype.
*/
Lexer.prototype = {
/**
* Custom inspect.
*/
inspect: function(){
var tok
, tmp = this.str
, buf = [];
while ('eos' != (tok = this.next()).type) {
buf.push(tok.inspect());
}
this.str = tmp;
this.prevIndents = 0;
return buf.concat(tok.inspect()).join('\n');
},
/**
* Lookahead `n` tokens.
*
* @param {Number} n
* @return {Object}
* @api private
*/
lookahead: function(n){
var fetch = n - this.stash.length;
while (fetch-- > 0) this.stash.push(this.advance());
return this.stash[--n];
},
/**
* Consume the given `len`.
*
* @param {Number|Array} len
* @api private
*/
skip: function(len){
this.str = this.str.substr(Array.isArray(len)
? len[0].length
: len);
},
/**
* Fetch next token including those stashed by peek.
*
* @return {Token}
* @api private
*/
next: function() {
var tok = this.stashed() || this.advance();
switch (tok.type) {
case 'newline':
case 'indent':
++this.lineno;
break;
case 'outdent':
if ('outdent' != this.prev.type) ++this.lineno;
}
this.prev = tok;
tok.lineno = this.lineno;
return tok;
},
/**
* Fetch next token.
*
* @return {Token}
* @api private
*/
advance: function() {
return this.eos()
|| this.null()
|| this.sep()
|| this.keyword()
|| this.urlchars()
|| this.atrule()
|| this.scope()
|| this.extends()
|| this.media()
|| this.mozdocument()
|| this.comment()
|| this.newline()
|| this.escaped()
|| this.important()
|| this.literal()
|| this.function()
|| this.brace()
|| this.paren()
|| this.color()
|| this.string()
|| this.unit()
|| this.namedop()
|| this.boolean()
|| this.ident()
|| this.op()
|| this.space()
|| this.selector();
},
/**
* Lookahead a single token.
*
* @return {Token}
* @api private
*/
peek: function() {
return this.lookahead(1);
},
/**
* Return the next possibly stashed token.
*
* @return {Token}
* @api private
*/
stashed: function() {
return this.stash.shift();
},
/**
* EOS | trailing outdents.
*/
eos: function() {
if (this.str.length) return;
if (this.indentStack.length) {
this.indentStack.shift();
return new Token('outdent');
} else {
return new Token('eos');
}
},
/**
* url char
*/
urlchars: function() {
var captures;
if (!this.isURL) return;
if (captures = /^[\/:@.;?&=*!,<>#%0-9]+/.exec(this.str)) {
this.skip(captures);
return new Token('literal', new nodes.Literal(captures[0]));
}
},
/**
* ';' [ \t]*
*/
sep: function() {
var captures;
if (captures = /^;[ \t]*/.exec(this.str)) {
this.skip(captures);
return new Token(';');
}
},
/**
* ' '+
*/
space: function() {
var captures;
if (captures = /^([ \t]+)/.exec(this.str)) {
this.skip(captures);
return new Token('space');
}
},
/**
* '\\' . ' '*
*/
escaped: function() {
var captures;
if (captures = /^\\(.)[ \t]*/.exec(this.str)) {
var c = captures[1];
this.skip(captures);
return new Token('ident', new nodes.Literal(c));
}
},
/**
* '@css' ' '* '{' .* '}' ' '*
*/
literal: function() {
// HACK attack !!!
var captures;
if (captures = /^@css[ \t]*\{/.exec(this.str)) {
this.skip(captures);
var c
, braces = 1
, css = '';
while (c = this.str[0]) {
this.str = this.str.substr(1);
switch (c) {
case '{': ++braces; break;
case '}': --braces; break;
}
css += c;
if (!braces) break;
}
css = css.replace(/\s*}$/, '');
return new Token('literal', new nodes.Literal(css));
}
},
/**
* '!important' ' '*
*/
important: function() {
var captures;
if (captures = /^!important[ \t]*/.exec(this.str)) {
this.skip(captures);
return new Token('ident', new nodes.Literal('!important'));
}
},
/**
* '{' | '}'
*/
brace: function() {
var captures;
if (captures = /^([{}])/.exec(this.str)) {
this.skip(1);
var brace = captures[1];
return new Token(brace, brace);
}
},
/**
* '(' | ')' ' '*
*/
paren: function() {
var captures;
if (captures = /^([()])([ \t]*)/.exec(this.str)) {
var paren = captures[1];
this.skip(captures);
if (')' == paren) this.isURL = false;
var tok = new Token(paren, paren);
tok.space = captures[2];
return tok;
}
},
/**
* 'null'
*/
null: function() {
var captures;
if (captures = /^(null)\b[ \t]*/.exec(this.str)) {
this.skip(captures);
return new Token('null', nodes.null);
}
},
/**
* 'if'
* | 'else'
* | 'unless'
* | 'return'
* | 'for'
* | 'in'
*/
keyword: function() {
var captures;
if (captures = /^(return|if|else|unless|for|in)\b[ \t]*/.exec(this.str)) {
var keyword = captures[1];
this.skip(captures);
return new Token(keyword, keyword);
}
},
/**
* 'not'
* | 'and'
* | 'or'
* | 'is'
* | 'is not'
* | 'isnt'
* | 'is a'
* | 'is defined'
*/
namedop: function() {
var captures;
if (captures = /^(not|and|or|is a|is defined|isnt|is not|is)(?!-)\b([ \t]*)/.exec(this.str)) {
var op = captures[1];
this.skip(captures);
op = alias[op] || op;
var tok = new Token(op, op);
tok.space = captures[2];
return tok;
}
},
/**
* ','
* | '+'
* | '+='
* | '-'
* | '-='
* | '*'
* | '*='
* | '/'
* | '/='
* | '%'
* | '%='
* | '**'
* | '!'
* | '&'
* | '&&'
* | '||'
* | '>'
* | '>='
* | '<'
* | '<='
* | '='
* | '=='
* | '!='
* | '!'
* | '~'
* | '?='
* | ':='
* | '?'
* | ':'
* | '['
* | ']'
* | '..'
* | '...'
*/
op: function() {
var captures;
if (captures = /^([.]{2,3}|&&|\|\||[!<>=?:]=|\*\*|[-+*\/%]=?|[,=?:!~<>&\[\]])([ \t]*)/.exec(this.str)) {
var op = captures[1];
this.skip(captures);
op = alias[op] || op;
var tok = new Token(op, op);
tok.space = captures[2];
this.isURL = false;
return tok;
}
},
/**
* '@extends' ([^{\n]+)
*/
extends: function() {
var captures;
if (captures = /^@extends?[ \t]*([^\/{\n;]+)/.exec(this.str)) {
this.skip(captures);
return new Token('extend', captures[1].trim());
}
},
/**
* '@media' ([^{\n]+)
*/
media: function() {
var captures;
if (captures = /^@media[ \t]*(.+?)(?=\/\/|[\n{])/.exec(this.str)) {
this.skip(captures);
return new Token('media', captures[1].trim());
}
},
/**
* '@-moz-document' ([^{\n]+)
*/
mozdocument: function() {
var captures;
if (captures = /^@-moz-document[ \t]*([^\/{\n]+)/.exec(this.str)) {
this.skip(captures);
return new Token('-moz-document', captures[1].trim());
}
},
/**
* '@scope' ([^{\n]+)
*/
scope: function() {
var captures;
if (captures = /^@scope[ \t]*([^\/{\n]+)/.exec(this.str)) {
this.skip(captures);
return new Token('scope', captures[1].trim());
}
},
/**
* '@' ('import' | 'keyframes' | 'charset' | 'page' | 'font-face')
*/
atrule: function() {
var captures;
if (captures = /^@(import|(?:-(\w+)-)?keyframes|charset|font-face|page)[ \t]*/.exec(this.str)) {
this.skip(captures);
var vendor = captures[2]
, type = captures[1];
if (vendor) type = 'keyframes';
return new Token(type, vendor);
}
},
/**
* '//' *
*/
comment: function() {
// Single line
if ('/' == this.str[0] && '/' == this.str[1]) {
var end = this.str.indexOf('\n');
if (-1 == end) end = this.str.length;
this.skip(end);
return this.advance();
}
// Multi-line
if ('/' == this.str[0] && '*' == this.str[1]) {
var end = this.str.indexOf('*/');
if (-1 == end) end = this.str.length;
var str = this.str.substr(0, end + 2)
, lines = str.split('\n').length - 1
, suppress = true;
this.lineno += lines;
this.skip(end + 2);
// output
if ('!' == str[2]) {
str = str.replace('*!', '*');
suppress = false;
}
return new Token('comment', new nodes.Comment(str, suppress));
}
},
/**
* 'true' | 'false'
*/
boolean: function() {
var captures;
if (captures = /^(true|false)\b([ \t]*)/.exec(this.str)) {
var val = nodes.Boolean('true' == captures[1]);
this.skip(captures);
var tok = new Token('boolean', val);
tok.space = captures[2];
return tok;
}
},
/**
* -*[_a-zA-Z$] [-\w\d$]* '('
*/
function: function() {
var captures;
if (captures = /^(-*[_a-zA-Z$][-\w\d$]*)\(([ \t]*)/.exec(this.str)) {
var name = captures[1];
this.skip(captures);
this.isURL = 'url' == name;
var tok = new Token('function', new nodes.Ident(name));
tok.space = captures[2];
return tok;
}
},
/**
* -*[_a-zA-Z$] [-\w\d$]*
*/
ident: function() {
var captures;
if (captures = /^(@)?(-*[_a-zA-Z$][-\w\d$]*)/.exec(this.str)) {
var at = captures[1]
, name = captures[2]
, id = new nodes.Ident(name);
this.skip(captures);
id.property = !! at;
return new Token('ident', id);
}
},
/**
* '\n' ' '+
*/
newline: function() {
var captures, re;
// we have established the indentation regexp
if (this.indentRe){
captures = this.indentRe.exec(this.str);
// figure out if we are using tabs or spaces
} else {
// try tabs
re = /^\n([\t]*)[ \t]*/;
captures = re.exec(this.str);
// nope, try spaces
if (captures && !captures[1].length) {
re = /^\n([ \t]*)/;
captures = re.exec(this.str);
}
// established
if (captures && captures[1].length) this.indentRe = re;
}
if (captures) {
var tok
, indents = captures[1].length;
this.skip(captures);
if (this.str[0] === ' ' || this.str[0] === '\t') {
throw new errors.SyntaxError('Invalid indentation. You can use tabs or spaces to indent, but not both.');
}
// Reset state
this.isVariable = false;
// Blank line
if ('\n' == this.str[0]) {
++this.lineno;
return this.advance();
}
// Outdent
if (this.indentStack.length && indents < this.indentStack[0]) {
while (this.indentStack.length && this.indentStack[0] > indents) {
this.stash.push(new Token('outdent'));
this.indentStack.shift();
}
tok = this.stash.pop();
// Indent
} else if (indents && indents != this.indentStack[0]) {
this.indentStack.unshift(indents);
tok = new Token('indent');
// Newline
} else {
tok = new Token('newline');
}
return tok;
}
},
/**
* '-'? (digit+ | digit* '.' digit+) unit
*/
unit: function() {
var captures;
if (captures = unit.exec(this.str)) {
this.skip(captures);
var n = parseFloat(captures[2]);
if ('-' == captures[1]) n = -n;
var node = new nodes.Unit(n, captures[3]);
return new Token('unit', node);
}
},
/**
* '"' [^"]+ '"' | "'"" [^']+ "'"
*/
string: function() {
var captures;
if (captures = /^("[^"]*"|'[^']*')[ \t]*/.exec(this.str)) {
var str = captures[1]
, quote = captures[0][0];
this.skip(captures);
str = str.slice(1,-1).replace(/\\n/g, '\n');
return new Token('string', new nodes.String(str, quote));
}
},
/**
* #rrggbbaa | #rrggbb | #rgba | #rgb | #nn | #n
*/
color: function() {
return this.rrggbbaa()
|| this.rrggbb()
|| this.rgba()
|| this.rgb()
|| this.nn()
|| this.n()
},
/**
* #n
*/
n: function() {
var captures;
if (captures = /^#([a-fA-F0-9]{1})[ \t]*/.exec(this.str)) {
this.skip(captures);
var n = parseInt(captures[1] + captures[1], 16)
, color = new nodes.RGBA(n, n, n, 1);
color.raw = captures[0];
return new Token('color', color);
}
},
/**
* #nn
*/
nn: function() {
var captures;
if (captures = /^#([a-fA-F0-9]{2})[ \t]*/.exec(this.str)) {
this.skip(captures);
var n = parseInt(captures[1], 16)
, color = new nodes.RGBA(n, n, n, 1);
color.raw = captures[0];
return new Token('color', color);
}
},
/**
* #rgb
*/
rgb: function() {
var captures;
if (captures = /^#([a-fA-F0-9]{3})[ \t]*/.exec(this.str)) {
this.skip(captures);
var rgb = captures[1]
, r = parseInt(rgb[0] + rgb[0], 16)
, g = parseInt(rgb[1] + rgb[1], 16)
, b = parseInt(rgb[2] + rgb[2], 16)
, color = new nodes.RGBA(r, g, b, 1);
color.raw = captures[0];
return new Token('color', color);
}
},
/**
* #rgba
*/
rgba: function() {
var captures;
if (captures = /^#([a-fA-F0-9]{4})[ \t]*/.exec(this.str)) {
this.skip(captures);
var rgb = captures[1]
, r = parseInt(rgb[0] + rgb[0], 16)
, g = parseInt(rgb[1] + rgb[1], 16)
, b = parseInt(rgb[2] + rgb[2], 16)
, a = parseInt(rgb[3] + rgb[3], 16)
, color = new nodes.RGBA(r, g, b, a/255);
color.raw = captures[0];
return new Token('color', color);
}
},
/**
* #rrggbb
*/
rrggbb: function() {
var captures;
if (captures = /^#([a-fA-F0-9]{6})[ \t]*/.exec(this.str)) {
this.skip(captures);
var rgb = captures[1]
, r = parseInt(rgb.substr(0, 2), 16)
, g = parseInt(rgb.substr(2, 2), 16)
, b = parseInt(rgb.substr(4, 2), 16)
, color = new nodes.RGBA(r, g, b, 1);
color.raw = captures[0];
return new Token('color', color);
}
},
/**
* #rrggbbaa
*/
rrggbbaa: function() {
var captures;
if (captures = /^#([a-fA-F0-9]{8})[ \t]*/.exec(this.str)) {
this.skip(captures);
var rgb = captures[1]
, r = parseInt(rgb.substr(0, 2), 16)
, g = parseInt(rgb.substr(2, 2), 16)
, b = parseInt(rgb.substr(4, 2), 16)
, a = parseInt(rgb.substr(6, 2), 16)
, color = new nodes.RGBA(r, g, b, a/255);
color.raw = captures[0];
return new Token('color', color);
}
},
/**
* [^\n,;]+
*/
selector: function() {
var captures;
if (captures = /^.*?(?=\/\/(?![^\[]*\])|[,\n{])/.exec(this.str)) {
var selector = captures[0];
this.skip(captures);
return new Token('selector', selector);
}
}
};

View File

@@ -0,0 +1,211 @@
/*!
* Stylus - middleware
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var stylus = require('./stylus')
, fs = require('fs')
, url = require('url')
, basename = require('path').basename
, dirname = require('path').dirname
, mkdirp = require('mkdirp')
, join = require('path').join
, debug = require('debug')('stylus:middleware');
/**
* Import map.
*/
var imports = {};
/**
* Return Connect middleware with the given `options`.
*
* Options:
*
* `force` Always re-compile
* `src` Source directory used to find .styl files
* `dest` Destination directory used to output .css files
* when undefined defaults to `src`.
* `compile` Custom compile function, accepting the arguments
* `(str, path)`.
* `compress` Whether the output .css files should be compressed
* `firebug` Emits debug infos in the generated CSS that can
* be used by the FireStylus Firebug plugin
* `linenos` Emits comments in the generated CSS indicating
* the corresponding Stylus line
*
* Examples:
*
* Here we set up the custom compile function so that we may
* set the `compress` option, or define additional functions.
*
* By default the compile function simply sets the `filename`
* and renders the CSS.
*
* function compile(str, path) {
* return stylus(str)
* .set('filename', path)
* .set('compress', true);
* }
*
* Pass the middleware to Connect, grabbing .styl files from this directory
* and saving .css files to _./public_. Also supplying our custom `compile` function.
*
* Following that we have a `static()` layer setup to serve the .css
* files generated by Stylus.
*
* var app = connect();
*
* app.middleware({
* src: __dirname
* , dest: __dirname + '/public'
* , compile: compile
* })
*
* app.use(connect.static(__dirname + '/public'));
*
* @param {Object} options
* @return {Function}
* @api public
*/
module.exports = function(options){
options = options || {};
// Accept src/dest dir
if ('string' == typeof options) {
options = { src: options };
}
// Force compilation
var force = options.force;
// Source dir required
var src = options.src;
if (!src) throw new Error('stylus.middleware() requires "src" directory');
// Default dest dir to source
var dest = options.dest
? options.dest
: src;
// Default compile callback
options.compile = options.compile || function(str, path){
return stylus(str)
.set('filename', path)
.set('compress', options.compress)
.set('firebug', options.firebug)
.set('linenos', options.linenos);
};
// Middleware
return function stylus(req, res, next){
if ('GET' != req.method && 'HEAD' != req.method) return next();
var path = url.parse(req.url).pathname;
if (/\.css$/.test(path)) {
var cssPath = join(dest, path)
, stylusPath = join(src, path.replace('.css', '.styl'));
// Ignore ENOENT to fall through as 404
function error(err) {
next('ENOENT' == err.code
? null
: err);
}
// Force
if (force) return compile();
// Compile to cssPath
function compile() {
debug('read %s', cssPath);
fs.readFile(stylusPath, 'utf8', function(err, str){
if (err) return error(err);
var style = options.compile(str, stylusPath);
var paths = style.options._imports = [];
delete imports[stylusPath];
style.render(function(err, css){
if (err) return next(err);
debug('render %s', stylusPath);
imports[stylusPath] = paths;
mkdirp(dirname(cssPath), 0700, function(err){
if (err) return error(err);
fs.writeFile(cssPath, css, 'utf8', next);
});
});
});
}
// Re-compile on server restart, disregarding
// mtimes since we need to map imports
if (!imports[stylusPath]) return compile();
// Compare mtimes
fs.stat(stylusPath, function(err, stylusStats){
if (err) return error(err);
fs.stat(cssPath, function(err, cssStats){
// CSS has not been compiled, compile it!
if (err) {
if ('ENOENT' == err.code) {
debug('not found %s', cssPath);
compile();
} else {
next(err);
}
} else {
// Source has changed, compile it
if (stylusStats.mtime > cssStats.mtime) {
debug('modified %s', cssPath);
compile();
// Already compiled, check imports
} else {
checkImports(stylusPath, function(changed){
if (debug && changed.length) {
changed.forEach(function(path) {
debug('modified import %s', path);
});
}
changed.length ? compile() : next();
});
}
}
});
});
} else {
next();
}
}
};
/**
* Check `path`'s imports to see if they have been altered.
*
* @param {String} path
* @param {Function} fn
* @api private
*/
function checkImports(path, fn) {
var nodes = imports[path];
if (!nodes) return fn();
if (!nodes.length) return fn();
var pending = nodes.length
, changed = [];
nodes.forEach(function(imported){
fs.stat(imported.path, function(err, stat){
// error or newer mtime
if (err || !imported.mtime || stat.mtime > imported.mtime) {
changed.push(imported.path);
}
--pending || fn(changed);
});
});
}

View File

@@ -0,0 +1,65 @@
/*!
* Stylus - Arguments
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('../nodes')
, utils = require('../utils');
/**
* Initialize a new `Arguments`.
*
* @api public
*/
var Arguments = module.exports = function Arguments(){
nodes.Expression.call(this);
this.map = {};
};
/**
* Inherit from `nodes.Expression.prototype`.
*/
Arguments.prototype.__proto__ = nodes.Expression.prototype;
/**
* Initialize an `Arguments` object with the nodes
* from the given `expr`.
*
* @param {Expression} expr
* @return {Arguments}
* @api public
*/
Arguments.fromExpression = function(expr){
var args = new Arguments
, len = expr.nodes.length;
args.lineno = expr.lineno;
args.isList = expr.isList;
for (var i = 0; i < len; ++i) {
args.push(expr.nodes[i]);
}
return args;
};
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Arguments.prototype.clone = function(){
var clone = nodes.Expression.prototype.clone.call(this);
clone.map = this.map;
return clone;
};

View File

@@ -0,0 +1,54 @@
/*!
* Stylus - BinOp
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `BinOp` with `op`, `left` and `right`.
*
* @param {String} op
* @param {Node} left
* @param {Node} right
* @api public
*/
var BinOp = module.exports = function BinOp(op, left, right){
Node.call(this);
this.op = op;
this.left = left;
this.right = right;
};
/**
* Inherit from `Node.prototype`.
*/
BinOp.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
BinOp.prototype.clone = function(){
var clone = new BinOp(
this.op
, this.left.clone()
, this.right ?
this.right.clone()
: null);
clone.lineno = this.lineno;
clone.filename = this.filename;
if (this.val) clone.val = this.val.clone();
return clone;
};

View File

@@ -0,0 +1,99 @@
/*!
* Stylus - Block
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Block` node with `parent` Block.
*
* @param {Block} parent
* @api public
*/
var Block = module.exports = function Block(parent, node){
Node.call(this);
this.nodes = [];
this.parent = parent;
this.node = node;
this.scope = true;
};
/**
* Inherit from `Node.prototype`.
*/
Block.prototype.__proto__ = Node.prototype;
/**
* Check if this block has properties..
*
* @return {Boolean}
* @api public
*/
Block.prototype.__defineGetter__('hasProperties', function(){
for (var i = 0, len = this.nodes.length; i < len; ++i) {
if ('property' == this.nodes[i].nodeName) {
return true;
}
}
});
/**
* Check if this block is empty.
*
* @return {Boolean}
* @api public
*/
Block.prototype.__defineGetter__('isEmpty', function(){
return !this.nodes.length;
});
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Block.prototype.clone = function(){
var clone = new Block(this.parent, this.node);
clone.lineno = this.lineno;
clone.filename = this.filename;
clone.scope = this.scope;
this.nodes.forEach(function(node){
node = node.clone();
switch (node.nodeName) {
case 'each':
case 'group':
node.block.parent = clone;
break;
case 'ident':
if ('function' == node.val.nodeName) {
node.val.block.parent = clone;
}
}
clone.push(node);
});
return clone;
};
/**
* Push a `node` to this block.
*
* @param {Node} node
* @api public
*/
Block.prototype.push = function(node){
this.nodes.push(node);
};

View File

@@ -0,0 +1,103 @@
/*!
* Stylus - Boolean
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `Boolean` node with the given `val`.
*
* @param {Boolean} val
* @api public
*/
var Boolean = module.exports = function Boolean(val){
Node.call(this);
if (this.nodeName) {
this.val = !!val;
} else {
return new Boolean(val);
}
};
/**
* Inherit from `Node.prototype`.
*/
Boolean.prototype.__proto__ = Node.prototype;
/**
* Return `this` node.
*
* @return {Boolean}
* @api public
*/
Boolean.prototype.toBoolean = function(){
return this;
};
/**
* Return `true` if this node represents `true`.
*
* @return {Boolean}
* @api public
*/
Boolean.prototype.__defineGetter__('isTrue', function(){
return this.val;
});
/**
* Return `true` if this node represents `false`.
*
* @return {Boolean}
* @api public
*/
Boolean.prototype.__defineGetter__('isFalse', function(){
return ! this.val;
});
/**
* Negate the value.
*
* @return {Boolean}
* @api public
*/
Boolean.prototype.negate = function(){
return new Boolean(!this.val);
};
/**
* Return 'Boolean'.
*
* @return {String}
* @api public
*/
Boolean.prototype.inspect = function(){
return '[Boolean ' + this.val + ']';
};
/**
* Return 'true' or 'false'.
*
* @return {String}
* @api public
*/
Boolean.prototype.toString = function(){
return this.val
? 'true'
: 'false';
};

View File

@@ -0,0 +1,57 @@
/*!
* Stylus - Call
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Call` with `name` and `args`.
*
* @param {String} name
* @param {Expression} args
* @api public
*/
var Call = module.exports = function Call(name, args){
Node.call(this);
this.name = name;
this.args = args;
};
/**
* Inherit from `Node.prototype`.
*/
Call.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Call.prototype.clone = function(){
var clone = new Call(this.name, this.args.clone());
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};
/**
* Return <name>().
*
* @return {String}
* @api public
*/
Call.prototype.toString = function(){
return this.name + '()';
};

View File

@@ -0,0 +1,42 @@
/*!
* Stylus - Charset
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `Charset` with the given `val`
*
* @param {String} val
* @api public
*/
var Charset = module.exports = function Charset(val){
Node.call(this);
this.val = val;
};
/**
* Inherit from `Node.prototype`.
*/
Charset.prototype.__proto__ = Node.prototype;
/**
* Return @charset "val".
*
* @return {String}
* @api public
*/
Charset.prototype.toString = function(){
return '@charset ' + this.val;
};

View File

@@ -0,0 +1,32 @@
/*!
* Stylus - Comment
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Comment` with the given `str`.
*
* @param {String} str
* @param {Boolean} suppress
* @api public
*/
var Comment = module.exports = function Comment(str, suppress){
Node.call(this);
this.str = str;
this.suppress = suppress;
};
/**
* Inherit from `Node.prototype`.
*/
Comment.prototype.__proto__ = Node.prototype;

View File

@@ -0,0 +1,56 @@
/*!
* Stylus - Each
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `Each` node with the given `val` name,
* `key` name, `expr`, and `block`.
*
* @param {String} val
* @param {String} key
* @param {Expression} expr
* @param {Block} block
* @api public
*/
var Each = module.exports = function Each(val, key, expr, block){
Node.call(this);
this.val = val;
this.key = key;
this.expr = expr;
this.block = block;
};
/**
* Inherit from `Node.prototype`.
*/
Each.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Each.prototype.clone = function(){
var clone = new Each(
this.val
, this.key
, this.expr.clone()
, this.block.clone());
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};

View File

@@ -0,0 +1,193 @@
/*!
* Stylus - Expression
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('../nodes')
, utils = require('../utils');
/**
* Initialize a new `Expression`.
*
* @param {Boolean} isList
* @api public
*/
var Expression = module.exports = function Expression(isList){
Node.call(this);
this.nodes = [];
this.isList = isList;
};
/**
* Check if the variable has a value.
*
* @return {Boolean}
* @api public
*/
Expression.prototype.__defineGetter__('isEmpty', function(){
return !this.nodes.length;
});
/**
* Return the first node in this expression.
*
* @return {Node}
* @api public
*/
Expression.prototype.__defineGetter__('first', function(){
return this.nodes[0]
? this.nodes[0].first
: nodes.null;
});
/**
* Hash all the nodes in order.
*
* @return {String}
* @api public
*/
Expression.prototype.__defineGetter__('hash', function(){
return this.nodes.map(function(node){
return node.hash;
}).join('::');
});
/**
* Inherit from `Node.prototype`.
*/
Expression.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Expression.prototype.clone = function(){
var clone = new this.constructor(this.isList);
clone.preserve = this.preserve;
clone.lineno = this.lineno;
clone.filename = this.filename;
for (var i = 0; i < this.nodes.length; ++i) {
clone.push(this.nodes[i].clone());
}
return clone;
};
/**
* Push the given `node`.
*
* @param {Node} node
* @api public
*/
Expression.prototype.push = function(node){
this.nodes.push(node);
};
/**
* Operate on `right` with the given `op`.
*
* @param {String} op
* @param {Node} right
* @return {Node}
* @api public
*/
Expression.prototype.operate = function(op, right, val){
switch (op) {
case '[]=':
var self = this
, range = utils.unwrap(right).nodes
, val = utils.unwrap(val)
, len;
range.forEach(function(unit){
len = self.nodes.length;
if ('unit' == unit.nodeName) {
var i = unit.val;
while (i-- > len) self.nodes[i] = nodes.null;
self.nodes[unit.val] = val;
}
});
return val;
case '[]':
var expr = new nodes.Expression
, vals = utils.unwrap(this).nodes
, range = utils.unwrap(right).nodes;
range.forEach(function(unit){
if ('unit' == unit.nodeName) {
var node = vals[unit.val];
if (node) expr.push(node);
}
});
return expr.isEmpty
? nodes.null
: utils.unwrap(expr);
case '||':
return this.toBoolean().isTrue
? this
: right;
case 'in':
return Node.prototype.operate.call(this, op, right);
case '!=':
return this.operate('==', right, val).negate();
case '==':
var len = this.nodes.length
, right = right.toExpression()
, a
, b;
if (len != right.nodes.length) return nodes.false;
for (var i = 0; i < len; ++i) {
a = this.nodes[i];
b = right.nodes[i];
if (a.operate(op, b).isTrue) continue;
return nodes.false;
}
return nodes.true;
break;
default:
return this.first.operate(op, right, val);
}
};
/**
* Expressions with length > 1 are truthy,
* otherwise the first value's toBoolean()
* method is invoked.
*
* @return {Boolean}
* @api public
*/
Expression.prototype.toBoolean = function(){
if (this.nodes.length > 1) return nodes.true;
return this.first.toBoolean();
};
/**
* Return "<a> <b> <c>" or "<a>, <b>, <c>" if
* the expression represents a list.
*
* @return {String}
* @api public
*/
Expression.prototype.toString = function(){
return '(' + this.nodes.map(function(node){
return node.toString();
}).join(this.isList ? ', ' : ' ') + ')';
};

View File

@@ -0,0 +1,52 @@
/*!
* Stylus - Extend
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Extend` with the given `selector`.
*
* @param {Selector} selector
* @api public
*/
var Extend = module.exports = function Extend(selector){
Node.call(this);
this.selector = selector;
};
/**
* Inherit from `Node.prototype`.
*/
Extend.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Extend.prototype.clone = function(){
return new Extend(this.selector);
};
/**
* Return `@extend selector`.
*
* @return {String}
* @api public
*/
Extend.prototype.toString = function(){
return '@extend ' + this.selector;
};

View File

@@ -0,0 +1,55 @@
/*!
* Stylus - FontFace
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `FontFace` with the given `block`.
*
* @param {Block} block
* @api public
*/
var FontFace = module.exports = function FontFace(block){
Node.call(this);
this.block = block;
};
/**
* Inherit from `Node.prototype`.
*/
FontFace.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
FontFace.prototype.clone = function(){
var clone = new FontFace(this.block.clone());
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};
/**
* Return `@oage name`.
*
* @return {String}
* @api public
*/
FontFace.prototype.toString = function(){
return '@font-face';
};

View File

@@ -0,0 +1,104 @@
/*!
* Stylus - Function
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Function` with `name`, `params`, and `body`.
*
* @param {String} name
* @param {Params|Function} params
* @param {Block} body
* @api public
*/
var Function = module.exports = function Function(name, params, body){
Node.call(this);
this.name = name;
this.params = params;
this.block = body;
if ('function' == typeof params) this.fn = params;
};
/**
* Check function arity.
*
* @return {Boolean}
* @api public
*/
Function.prototype.__defineGetter__('arity', function(){
return this.params.length;
});
/**
* Inherit from `Node.prototype`.
*/
Function.prototype.__proto__ = Node.prototype;
/**
* Return hash.
*
* @return {String}
* @api public
*/
Function.prototype.__defineGetter__('hash', function(){
return 'function ' + this.name;
});
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Function.prototype.clone = function(){
if (this.fn) {
var clone = new Function(
this.name
, this.fn);
} else {
var clone = new Function(
this.name
, this.params.clone()
, this.block.clone());
}
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};
/**
* Return <name>(param1, param2, ...).
*
* @return {String}
* @api public
*/
Function.prototype.toString = function(){
if (this.fn) {
return this.name
+ '('
+ this.fn.toString()
.match(/^function *\((.*?)\)/)
.slice(1)
.join(', ')
+ ')';
} else {
return this.name
+ '('
+ this.params.nodes.join(', ')
+ ')';
}
};

View File

@@ -0,0 +1,80 @@
/*!
* Stylus - Group
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Group`.
*
* @api public
*/
var Group = module.exports = function Group(){
Node.call(this);
this.nodes = [];
this.extends = [];
};
/**
* Inherit from `Node.prototype`.
*/
Group.prototype.__proto__ = Node.prototype;
/**
* Push the given `selector` node.
*
* @param {Selector} selector
* @api public
*/
Group.prototype.push = function(selector){
this.nodes.push(selector);
};
/**
* Return this set's `Block`.
*/
Group.prototype.__defineGetter__('block', function(){
return this.nodes[0].block;
});
/**
* Assign `block` to each selector in this set.
*
* @param {Block} block
* @api public
*/
Group.prototype.__defineSetter__('block', function(block){
for (var i = 0, len = this.nodes.length; i < len; ++i) {
this.nodes[i].block = block;
}
});
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Group.prototype.clone = function(){
var clone = new Group;
clone.lineno = this.lineno;
this.nodes.forEach(function(node){
clone.push(node.clone());
});
clone.filename = this.filename;
clone.block = this.block.clone();
return clone;
};

View File

@@ -0,0 +1,256 @@
/*!
* Stylus - HSLA
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `HSLA` with the given h,s,l,a component values.
*
* @param {Number} h
* @param {Number} s
* @param {Number} l
* @param {Number} a
* @api public
*/
var HSLA = exports = module.exports = function HSLA(h,s,l,a){
Node.call(this);
this.h = clampDegrees(h);
this.s = clampPercentage(s);
this.l = clampPercentage(l);
this.a = clampAlpha(a);
this.hsla = this;
};
/**
* Inherit from `Node.prototype`.
*/
HSLA.prototype.__proto__ = Node.prototype;
/**
* Return hsla(n,n,n,n).
*
* @return {String}
* @api public
*/
HSLA.prototype.toString = function(){
return 'hsla('
+ this.h + ','
+ this.s.toFixed(0) + ','
+ this.l.toFixed(0) + ','
+ this.a + ')';
};
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
HSLA.prototype.clone = function(){
var clone = new HSLA(
this.h
, this.s
, this.l
, this.a);
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};
/**
* Return rgba `RGBA` representation.
*
* @return {RGBA}
* @api public
*/
HSLA.prototype.__defineGetter__('rgba', function(){
return nodes.RGBA.fromHSLA(this);
});
/**
* Return hash.
*
* @return {String}
* @api public
*/
HSLA.prototype.__defineGetter__('hash', function(){
return this.rgba.toString();
});
/**
* Add h,s,l to the current component values.
*
* @param {Number} h
* @param {Number} s
* @param {Number} l
* @return {HSLA} new node
* @api public
*/
HSLA.prototype.add = function(h,s,l){
return new HSLA(
this.h + h
, this.s + s
, this.l + l
, this.a);
};
/**
* Subtract h,s,l from the current component values.
*
* @param {Number} h
* @param {Number} s
* @param {Number} l
* @return {HSLA} new node
* @api public
*/
HSLA.prototype.sub = function(h,s,l){
return this.add(-h, -s, -l);
};
/**
* Operate on `right` with the given `op`.
*
* @param {String} op
* @param {Node} right
* @return {Node}
* @api public
*/
HSLA.prototype.operate = function(op, right){
switch (op) {
case '==':
case '!=':
case '<=':
case '>=':
case '<':
case '>':
case 'is a':
case '||':
case '&&':
return this.rgba.operate(op, right);
default:
return this.rgba.operate(op, right).hsla;
}
};
/**
* Return `HSLA` representation of the given `color`.
*
* @param {RGBA} color
* @return {HSLA}
* @api public
*/
exports.fromRGBA = function(rgba){
var r = rgba.r / 255
, g = rgba.g / 255
, b = rgba.b / 255
, a = rgba.a;
var min = Math.min(r,g,b)
, max = Math.max(r,g,b)
, l = (max + min) / 2
, d = max - min
, h, s;
switch (max) {
case min: h = 0; break;
case r: h = 60 * (g-b) / d; break;
case g: h = 60 * (b-r) / d + 120; break;
case b: h = 60 * (r-g) / d + 240; break;
}
if (max == min) {
s = 0;
} else if (l < .5) {
s = d / (2 * l);
} else {
s = d / (2 - 2 * l);
}
h %= 360;
s *= 100;
l *= 100;
return new HSLA(h,s,l,a);
};
/**
* Adjust lightness by `percent`.
*
* @param {Number} percent
* @return {HSLA} for chaining
* @api public
*/
HSLA.prototype.adjustLightness = function(percent){
this.l = clampPercentage(this.l + this.l * (percent / 100));
return this;
};
/**
* Adjust hue by `deg`.
*
* @param {Number} deg
* @return {HSLA} for chaining
* @api public
*/
HSLA.prototype.adjustHue = function(deg){
this.h = clampDegrees(this.h + deg);
return this;
};
/**
* Clamp degree `n` >= 0 and <= 360.
*
* @param {Number} n
* @return {Number}
* @api private
*/
function clampDegrees(n) {
n = n % 360;
return n >= 0 ? n : 360 + n;
}
/**
* Clamp percentage `n` >= 0 and <= 100.
*
* @param {Number} n
* @return {Number}
* @api private
*/
function clampPercentage(n) {
return Math.max(0, Math.min(n, 100));
}
/**
* Clamp alpha `n` >= 0 and <= 1.
*
* @param {Number} n
* @return {Number}
* @api private
*/
function clampAlpha(n) {
return Math.max(0, Math.min(n, 1));
}

View File

@@ -0,0 +1,127 @@
/*!
* Stylus - Ident
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `Ident` by `name` with the given `val` node.
*
* @param {String} name
* @param {Node} val
* @api public
*/
var Ident = module.exports = function Ident(name, val){
Node.call(this);
this.name = name;
this.string = name;
this.val = val || nodes.null;
};
/**
* Check if the variable has a value.
*
* @return {Boolean}
* @api public
*/
Ident.prototype.__defineGetter__('isEmpty', function(){
return undefined == this.val;
});
/**
* Return hash.
*
* @return {String}
* @api public
*/
Ident.prototype.__defineGetter__('hash', function(){
return this.name;
});
/**
* Inherit from `Node.prototype`.
*/
Ident.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Ident.prototype.clone = function(){
var clone = new Ident(this.name, this.val.clone());
clone.lineno = this.lineno;
clone.filename = this.filename;
clone.property = this.property;
return clone;
};
/**
* Return <name>.
*
* @return {String}
* @api public
*/
Ident.prototype.toString = function(){
return this.name;
};
/**
* Coerce `other` to an ident.
*
* @param {Node} other
* @return {String}
* @api public
*/
Ident.prototype.coerce = function(other){
switch (other.nodeName) {
case 'ident':
case 'string':
case 'literal':
return new Ident(other.string);
default:
return Node.prototype.coerce.call(this, other);
}
};
/**
* Operate on `right` with the given `op`.
*
* @param {String} op
* @param {Node} right
* @return {Node}
* @api public
*/
Ident.prototype.operate = function(op, right){
var val = right.first;
switch (op) {
case '-':
if ('unit' == val.nodeName) {
var expr = new nodes.Expression;
val.val = -val.val;
expr.push(this);
expr.push(val);
return expr;
}
case '+':
return new nodes.Ident(this.string + this.coerce(val).string);
}
return Node.prototype.operate.call(this, op, right);
};

View File

@@ -0,0 +1,56 @@
/*!
* Stylus - If
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `If` with the given `cond`.
*
* @param {Expression} cond
* @param {Boolean|Block} negate, block
* @api public
*/
var If = module.exports = function If(cond, negate){
Node.call(this);
this.cond = cond;
this.elses = [];
if (negate && negate.nodeName) {
this.block = negate;
} else {
this.negate = negate;
}
};
/**
* Inherit from `Node.prototype`.
*/
If.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
If.prototype.clone = function(){
var cond = this.cond.clone()
, block = this.block.clone();
var clone = new If(cond, block);
clone.elses = this.elses.map(function(node){ return node.clone(); });
clone.negate = this.negate;
clone.postfix = this.postfix;
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};

View File

@@ -0,0 +1,30 @@
/*!
* Stylus - Import
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Import` with the given `expr`.
*
* @param {Expression} expr
* @api public
*/
var Import = module.exports = function Import(expr){
Node.call(this);
this.path = expr;
};
/**
* Inherit from `Node.prototype`.
*/
Import.prototype.__proto__ = Node.prototype;

View File

@@ -0,0 +1,54 @@
/*!
* Stylus - nodes
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Constructors
*/
exports.Node = require('./node');
exports.Root = require('./root');
exports.Null = require('./null');
exports.Each = require('./each');
exports.If = require('./if');
exports.Call = require('./call');
exports.Page = require('./page');
exports.FontFace = require('./fontface');
exports.UnaryOp = require('./unaryop');
exports.BinOp = require('./binop');
exports.Ternary = require('./ternary');
exports.Block = require('./block');
exports.Unit = require('./unit');
exports.String = require('./string');
exports.HSLA = require('./hsla');
exports.RGBA = require('./rgba');
exports.Ident = require('./ident');
exports.Group = require('./group');
exports.Literal = require('./literal');
exports.JSLiteral = require('./jsliteral');
exports.Boolean = require('./boolean');
exports.Return = require('./return');
exports.Media = require('./media');
exports.Params = require('./params');
exports.Comment = require('./comment');
exports.Keyframes = require('./keyframes');
exports.Charset = require('./charset');
exports.Import = require('./import');
exports.Extend = require('./extend');
exports.Function = require('./function');
exports.Property = require('./property');
exports.Selector = require('./selector');
exports.Expression = require('./expression');
exports.Arguments = require('./arguments');
exports.MozDocument = require('./mozdocument');
/**
* Singletons.
*/
exports.true = new exports.Boolean(true);
exports.false = new exports.Boolean(false);
exports.null = new exports.Null;

View File

@@ -0,0 +1,32 @@
/*!
* Stylus - JSLiteral
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `JSLiteral` with the given `str`.
*
* @param {String} str
* @api public
*/
var JSLiteral = module.exports = function JSLiteral(str){
Node.call(this);
this.val = str;
this.string = str;
};
/**
* Inherit from `Node.prototype`.
*/
JSLiteral.prototype.__proto__ = Node.prototype;

View File

@@ -0,0 +1,78 @@
/*!
* Stylus - Keyframes
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Keyframes` with the given `name`,
* and optional vendor `prefix`.
*
* @param {String} name
* @param {String} prefix
* @api public
*/
var Keyframes = module.exports = function Keyframes(name, prefix){
Node.call(this);
this.name = name;
this.frames = [];
this.prefix = prefix || 'official';
};
/**
* Inherit from `Node.prototype`.
*/
Keyframes.prototype.__proto__ = Node.prototype;
/**
* Push the given `block` at `pos`.
*
* @param {Array} pos
* @param {Block} block
* @api public
*/
Keyframes.prototype.push = function(pos, block){
this.frames.push({
pos: pos
, block: block
});
};
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Keyframes.prototype.clone = function(){
var clone = new Keyframes(this.name);
clone.lineno = this.lineno;
clone.prefix = this.prefix;
clone.frames = this.frames.map(function(node){
node.block = node.block.clone();
return node;
});
return clone;
};
/**
* Return `@keyframes name`.
*
* @return {String}
* @api public
*/
Keyframes.prototype.toString = function(){
return '@keyframes ' + this.name;
};

View File

@@ -0,0 +1,92 @@
/*!
* Stylus - Literal
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `Literal` with the given `str`.
*
* @param {String} str
* @api public
*/
var Literal = module.exports = function Literal(str){
Node.call(this);
this.val = str;
this.string = str;
};
/**
* Inherit from `Node.prototype`.
*/
Literal.prototype.__proto__ = Node.prototype;
/**
* Return hash.
*
* @return {String}
* @api public
*/
Literal.prototype.__defineGetter__('hash', function(){
return this.val;
});
/**
* Return literal value.
*
* @return {String}
* @api public
*/
Literal.prototype.toString = function(){
return this.val;
};
/**
* Coerce `other` to a literal.
*
* @param {Node} other
* @return {String}
* @api public
*/
Literal.prototype.coerce = function(other){
switch (other.nodeName) {
case 'ident':
case 'string':
case 'literal':
return new Literal(other.string);
default:
return Node.prototype.coerce.call(this, other);
}
};
/**
* Operate on `right` with the given `op`.
*
* @param {String} op
* @param {Node} right
* @return {Node}
* @api public
*/
Literal.prototype.operate = function(op, right){
var val = right.first;
switch (op) {
case '+':
return new nodes.Literal(this.string + this.coerce(val).string);
default:
return Node.prototype.operate.call(this, op, right);
}
};

View File

@@ -0,0 +1,55 @@
/*!
* Stylus - Media
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `Media` with the given `val`
*
* @param {String} val
* @api public
*/
var Media = module.exports = function Media(val){
Node.call(this);
this.val = val;
};
/**
* Inherit from `Node.prototype`.
*/
Media.prototype.__proto__ = Node.prototype;
/**
* Clone this node.
*
* @return {Media}
* @api public
*/
Media.prototype.clone = function(){
var clone = new Media(this.val);
clone.block = this.block.clone();
return clone;
};
/**
* Return @media "val".
*
* @return {String}
* @api public
*/
Media.prototype.toString = function(){
return '@media ' + this.val;
};

View File

@@ -0,0 +1,19 @@
var Node = require('./node')
, nodes = require('./');
var MozDocument = module.exports = function MozDocument(val){
Node.call(this);
this.val = val;
};
MozDocument.prototype.__proto__ = Node.prototype;
MozDocument.prototype.clone = function(){
var clone = new MozDocument(this.val);
clone.block = this.block.clone();
return clone;
};
MozDocument.prototype.toString = function(){
return '@-moz-document ' + this.val;
}

View File

@@ -0,0 +1,223 @@
/*!
* Stylus - Node
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Evaluator = require('../visitor/evaluator')
, utils = require('../utils')
, nodes = require('./');
/**
* Node constructor.
*
* @api public
*/
var Node = module.exports = function Node(){
this.lineno = nodes.lineno;
Object.defineProperty(this, 'filename', { writable: true, value: nodes.filename });
};
/**
* Return this node.
*
* @return {Node}
* @api public
*/
Node.prototype.__defineGetter__('first', function(){
return this;
});
/**
* Return hash.
*
* @return {String}
* @api public
*/
Node.prototype.__defineGetter__('hash', function(){
return this.val;
});
/**
* Return node name.
*
* @return {String}
* @api public
*/
Node.prototype.__defineGetter__('nodeName', function(){
return this.constructor.name.toLowerCase();
});
/**
* Return this node.
*
* @return {Node}
* @api public
*/
Node.prototype.clone = function(){
return this;
};
/**
* Nodes by default evaluate to themselves.
*
* @return {Node}
* @api public
*/
Node.prototype.eval = function(){
return new Evaluator(this).evaluate();
};
/**
* Return true.
*
* @return {Boolean}
* @api public
*/
Node.prototype.toBoolean = function(){
return nodes.true;
};
/**
* Return the expression, or wrap this node in an expression.
*
* @return {Expression}
* @api public
*/
Node.prototype.toExpression = function(){
if ('expression' == this.nodeName) return this;
var expr = new nodes.Expression;
expr.push(this);
return expr;
};
/**
* Return false if `op` is generally not coerced.
*
* @param {String} op
* @return {Boolean}
* @api private
*/
Node.prototype.shouldCoerce = function(op){
switch (op) {
case 'is a':
case 'in':
case '||':
case '&&':
return false;
default:
return true;
}
};
/**
* Operate on `right` with the given `op`.
*
* @param {String} op
* @param {Node} right
* @return {Node}
* @api public
*/
Node.prototype.operate = function(op, right){
switch (op) {
case 'is a':
if ('string' == right.nodeName) {
return nodes.Boolean(this.nodeName == right.val);
} else {
throw new Error('"is a" expects a string, got ' + right.toString());
}
case '==':
return nodes.Boolean(this.hash == right.hash);
case '!=':
return nodes.Boolean(this.hash != right.hash);
case '>=':
return nodes.Boolean(this.hash >= right.hash);
case '<=':
return nodes.Boolean(this.hash <= right.hash);
case '>':
return nodes.Boolean(this.hash > right.hash);
case '<':
return nodes.Boolean(this.hash < right.hash);
case '||':
return this.toBoolean().isTrue
? this
: right;
case 'in':
var vals = utils.unwrap(right).nodes
, hash = this.hash;
if (!vals) throw new Error('"in" given invalid right-hand operand, expecting an expression');
for (var i = 0, len = vals.length; i < len; ++i) {
if (hash == vals[i].hash) {
return nodes.true;
}
}
return nodes.false;
case '&&':
var a = this.toBoolean()
, b = right.toBoolean();
return a.isTrue && b.isTrue
? right
: a.isFalse
? this
: right;
default:
if ('[]' == op) {
var msg = 'cannot perform '
+ this
+ '[' + right + ']';
} else {
var msg = 'cannot perform'
+ ' ' + this
+ ' ' + op
+ ' ' + right;
}
throw new Error(msg);
}
};
/**
* Initialize a new `CoercionError` with the given `msg`.
*
* @param {String} msg
* @api private
*/
function CoercionError(msg) {
this.name = 'CoercionError'
this.message = msg
Error.captureStackTrace(this, CoercionError);
}
/**
* Inherit from `Error.prototype`.
*/
CoercionError.prototype.__proto__ = Error.prototype;
/**
* Default coercion throws.
*
* @param {Node} other
* @return {Node}
* @api public
*/
Node.prototype.coerce = function(other){
if (other.nodeName == this.nodeName) return other;
throw new CoercionError('cannot coerce ' + other + ' to ' + this.nodeName);
};

View File

@@ -0,0 +1,72 @@
/*!
* Stylus - Null
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `Null` node.
*
* @api public
*/
var Null = module.exports = function Null(){};
/**
* Inherit from `Node.prototype`.
*/
Null.prototype.__proto__ = Node.prototype;
/**
* Return 'Null'.
*
* @return {String}
* @api public
*/
Null.prototype.inspect =
Null.prototype.toString = function(){
return 'null';
};
/**
* Return false.
*
* @return {Boolean}
* @api public
*/
Null.prototype.toBoolean = function(){
return nodes.false;
};
/**
* Check if the node is a null node.
*
* @return {Boolean}
* @api public
*/
Null.prototype.__defineGetter__('isNull', function(){
return true;
});
/**
* Return hash.
*
* @return {String}
* @api public
*/
Null.prototype.__defineGetter__('hash', function(){
return null;
});

View File

@@ -0,0 +1,43 @@
/*!
* Stylus - Page
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Page` with the given `selector` and `block`.
*
* @param {Selector} selector
* @param {Block} block
* @api public
*/
var Page = module.exports = function Page(selector, block){
Node.call(this);
this.selector = selector;
this.block = block;
};
/**
* Inherit from `Node.prototype`.
*/
Page.prototype.__proto__ = Node.prototype;
/**
* Return `@page name`.
*
* @return {String}
* @api public
*/
Page.prototype.toString = function(){
return '@page ' + this.selector;
};

View File

@@ -0,0 +1,72 @@
/*!
* Stylus - Params
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Params` with `name`, `params`, and `body`.
*
* @param {String} name
* @param {Params} params
* @param {Expression} body
* @api public
*/
var Params = module.exports = function Params(){
Node.call(this);
this.nodes = [];
};
/**
* Check function arity.
*
* @return {Boolean}
* @api public
*/
Params.prototype.__defineGetter__('length', function(){
return this.nodes.length;
});
/**
* Inherit from `Node.prototype`.
*/
Params.prototype.__proto__ = Node.prototype;
/**
* Push the given `node`.
*
* @param {Node} node
* @api public
*/
Params.prototype.push = function(node){
this.nodes.push(node);
};
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Params.prototype.clone = function(){
var clone = new Params;
clone.lineno = this.lineno;
clone.filename = this.filename;
this.nodes.forEach(function(node){
clone.push(node.clone());
});
return clone;
};

View File

@@ -0,0 +1,73 @@
/*!
* Stylus - Property
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Property` with the given `segs` and optional `expr`.
*
* @param {Array} segs
* @param {Expression} expr
* @api public
*/
var Property = module.exports = function Property(segs, expr){
Node.call(this);
this.segments = segs;
this.expr = expr;
};
/**
* Inherit from `Node.prototype`.
*/
Property.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Property.prototype.clone = function(){
var clone = new Property(this.segments);
clone.name = this.name;
clone.lineno = this.lineno;
clone.filename = this.filename;
clone.segments = this.segments.map(function(node){ return node.clone(); });
if (this.expr) clone.expr = this.expr.clone();
return clone;
};
/**
* Return string representation of this node.
*
* @return {String}
* @api public
*/
Property.prototype.toString = function(){
return 'property(' + this.segments.join('') + ', ' + this.expr + ')';
};
/**
* Operate on the property expression.
*
* @param {String} op
* @param {Node} right
* @return {Node}
* @api public
*/
Property.prototype.operate = function(op, right, val){
return this.expr.operate(op, right, val);
};

View File

@@ -0,0 +1,44 @@
/*!
* Stylus - Return
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `Return` node with the given `expr`.
*
* @param {Expression} expr
* @api public
*/
var Return = module.exports = function Return(expr){
this.expr = expr || nodes.null;
};
/**
* Inherit from `Node.prototype`.
*/
Return.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Return.prototype.clone = function(){
var clone = new Return(this.expr.clone());
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};

View File

@@ -0,0 +1,337 @@
/*!
* Stylus - RGBA
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, HSLA = require('./hsla')
, functions = require('../functions')
, adjust = functions['-adjust']
, nodes = require('./');
/**
* Initialize a new `RGBA` with the given r,g,b,a component values.
*
* @param {Number} r
* @param {Number} g
* @param {Number} b
* @param {Number} a
* @api public
*/
var RGBA = exports = module.exports = function RGBA(r,g,b,a){
Node.call(this);
this.r = clamp(r);
this.g = clamp(g);
this.b = clamp(b);
this.a = clampAlpha(a);
this.rgba = this;
};
/**
* Inherit from `Node.prototype`.
*/
RGBA.prototype.__proto__ = Node.prototype;
/**
* Return an `RGBA` without clamping values.
*
* @param {Number} r
* @param {Number} g
* @param {Number} b
* @param {Number} a
* @return {RGBA}
* @api public
*/
RGBA.withoutClamping = function(r,g,b,a){
var rgba = new RGBA(0,0,0,0);
rgba.r = r;
rgba.g = g;
rgba.b = b;
rgba.a = a;
return rgba;
};
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
RGBA.prototype.clone = function(){
var clone = new RGBA(
this.r
, this.g
, this.b
, this.a);
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};
/**
* Return true.
*
* @return {Boolean}
* @api public
*/
RGBA.prototype.toBoolean = function(){
return nodes.true;
};
/**
* Return `HSLA` representation.
*
* @return {HSLA}
* @api public
*/
RGBA.prototype.__defineGetter__('hsla', function(){
return HSLA.fromRGBA(this);
});
/**
* Return hash.
*
* @return {String}
* @api public
*/
RGBA.prototype.__defineGetter__('hash', function(){
return this.toString();
});
/**
* Add r,g,b,a to the current component values.
*
* @param {Number} r
* @param {Number} g
* @param {Number} b
* @param {Number} a
* @return {RGBA} new node
* @api public
*/
RGBA.prototype.add = function(r,g,b,a){
return new RGBA(
this.r + r
, this.g + g
, this.b + b
, this.a + a);
};
/**
* Subtract r,g,b,a from the current component values.
*
* @param {Number} r
* @param {Number} g
* @param {Number} b
* @param {Number} a
* @return {RGBA} new node
* @api public
*/
RGBA.prototype.sub = function(r,g,b,a){
return new RGBA(
this.r - r
, this.g - g
, this.b - b
, a == 1 ? this.a : this.a - a);
};
/**
* Multiply rgb components by `n`.
*
* @param {String} n
* @return {RGBA} new node
* @api public
*/
RGBA.prototype.multiply = function(n){
return new RGBA(
this.r * n
, this.g * n
, this.b * n
, this.a);
};
/**
* Divide rgb components by `n`.
*
* @param {String} n
* @return {RGBA} new node
* @api public
*/
RGBA.prototype.divide = function(n){
return new RGBA(
this.r / n
, this.g / n
, this.b / n
, this.a);
};
/**
* Operate on `right` with the given `op`.
*
* @param {String} op
* @param {Node} right
* @return {Node}
* @api public
*/
RGBA.prototype.operate = function(op, right){
right = right.first;
switch (op) {
case 'is a':
if ('string' == right.nodeName && 'color' == right.string) {
return nodes.true;
}
break;
case '+':
switch (right.nodeName) {
case 'unit':
var n = right.val;
switch (right.type) {
case '%': return adjust(this, new nodes.String('lightness'), right);
case 'deg': return this.hsla.adjustHue(n).rgba;
default: return this.add(n,n,n,0);
}
case 'rgba':
return this.add(right.r, right.g, right.b, right.a);
case 'hsla':
return this.hsla.add(right.h, right.s, right.l);
}
break;
case '-':
switch (right.nodeName) {
case 'unit':
var n = right.val;
switch (right.type) {
case '%': return adjust(this, new nodes.String('lightness'), new nodes.Unit(-n, '%'));
case 'deg': return this.hsla.adjustHue(-n).rgba;
default: return this.sub(n,n,n,0);
}
case 'rgba':
return this.sub(right.r, right.g, right.b, right.a);
case 'hsla':
return this.hsla.sub(right.h, right.s, right.l);
}
break;
case '*':
switch (right.nodeName) {
case 'unit':
return this.multiply(right.val);
}
break;
case '/':
switch (right.nodeName) {
case 'unit':
return this.divide(right.val);
}
break;
}
return Node.prototype.operate.call(this, op, right);
};
/**
* Return #nnnnnn, #nnn, or rgba(n,n,n,n) string representation of the color.
*
* @return {String}
* @api public
*/
RGBA.prototype.toString = function(){
function pad(n) {
return n < 16
? '0' + n.toString(16)
: n.toString(16);
}
if (1 == this.a) {
var r = pad(this.r)
, g = pad(this.g)
, b = pad(this.b);
// Compress
if (r[0] == r[1] && g[0] == g[1] && b[0] == b[1]) {
return '#' + r[0] + g[0] + b[0];
} else {
return '#' + r + g + b;
}
} else {
return 'rgba('
+ this.r + ','
+ this.g + ','
+ this.b + ','
+ (+this.a.toFixed(3)) + ')';
}
};
/**
* Return a `RGBA` from the given `hsla`.
*
* @param {HSLA} hsla
* @return {RGBA}
* @api public
*/
exports.fromHSLA = function(hsla){
var h = hsla.h / 360
, s = hsla.s / 100
, l = hsla.l / 100
, a = hsla.a;
var m2 = l <= .5 ? l * (s + 1) : l + s - l * s
, m1 = l * 2 - m2;
var r = hue(h + 1/3) * 0xff
, g = hue(h) * 0xff
, b = hue(h - 1/3) * 0xff;
function hue(h) {
if (h < 0) ++h;
if (h > 1) --h;
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
if (h * 2 < 1) return m2;
if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;
return m1;
}
return new RGBA(r,g,b,a);
};
/**
* Clamp `n` >= 0 and <= 255.
*
* @param {Number} n
* @return {Number}
* @api private
*/
function clamp(n) {
return Math.max(0, Math.min(n.toFixed(0), 255));
}
/**
* Clamp alpha `n` >= 0 and <= 1.
*
* @param {Number} n
* @return {Number}
* @api private
*/
function clampAlpha(n) {
return Math.max(0, Math.min(n, 1));
}

View File

@@ -0,0 +1,61 @@
/*!
* Stylus - Root
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Root` node.
*
* @api public
*/
var Root = module.exports = function Root(){
this.nodes = [];
};
/**
* Inherit from `Node.prototype`.
*/
Root.prototype.__proto__ = Node.prototype;
/**
* Push a `node` to this block.
*
* @param {Node} node
* @api public
*/
Root.prototype.push = function(node){
this.nodes.push(node);
};
/**
* Unshift a `node` to this block.
*
* @param {Node} node
* @api public
*/
Root.prototype.unshift = function(node){
this.nodes.unshift(node);
};
/**
* Return "root".
*
* @return {String}
* @api public
*/
Root.prototype.toString = function(){
return '[Root]';
};

View File

@@ -0,0 +1,58 @@
/*!
* Stylus - Selector
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Block = require('./block')
, Node = require('./node');
/**
* Initialize a new `Selector` with the given `segs`.
*
* @param {Array} segs
* @api public
*/
var Selector = module.exports = function Selector(segs){
Node.call(this);
this.inherits = true;
this.segments = segs;
};
/**
* Inherit from `Node.prototype`.
*/
Selector.prototype.__proto__ = Node.prototype;
/**
* Return the selector string.
*
* @return {String}
* @api public
*/
Selector.prototype.toString = function(){
return this.segments.join('');
};
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Selector.prototype.clone = function(){
var clone = new Selector;
clone.lineno = this.lineno;
clone.filename = this.filename;
clone.segments = this.segments.map(function(node){ return node.clone(); });
return clone;
};

View File

@@ -0,0 +1,122 @@
/*!
* Stylus - String
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, sprintf = require('../functions').s
, utils = require('../utils')
, nodes = require('./');
/**
* Initialize a new `String` with the given `val`.
*
* @param {String} val
* @param {String} quote
* @api public
*/
var String = module.exports = function String(val, quote){
Node.call(this);
this.val = val;
this.string = val;
this.quote = quote || "'";
};
/**
* Inherit from `Node.prototype`.
*/
String.prototype.__proto__ = Node.prototype;
/**
* Return quoted string.
*
* @return {String}
* @api public
*/
String.prototype.toString = function(){
return this.quote + this.val + this.quote;
};
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
String.prototype.clone = function(){
var clone = new String(this.val, this.quote);
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};
/**
* Return Boolean based on the length of this string.
*
* @return {Boolean}
* @api public
*/
String.prototype.toBoolean = function(){
return nodes.Boolean(this.val.length);
};
/**
* Coerce `other` to a string.
*
* @param {Node} other
* @return {String}
* @api public
*/
String.prototype.coerce = function(other){
switch (other.nodeName) {
case 'string':
return other;
case 'expression':
return new String(other.nodes.map(function(node){
return this.coerce(node).val;
}, this).join(' '));
default:
return new String(other.toString());
}
};
/**
* Operate on `right` with the given `op`.
*
* @param {String} op
* @param {Node} right
* @return {Node}
* @api public
*/
String.prototype.operate = function(op, right){
switch (op) {
case '%':
var expr = new nodes.Expression;
expr.push(this);
// constructargs
var args = 'expression' == right.nodeName
? utils.unwrap(right).nodes
: [right];
// apply
return sprintf.apply(null, [expr].concat(args));
case '+':
return new String(this.val + this.coerce(right).val);
default:
return Node.prototype.operate.call(this, op, right);
}
};

View File

@@ -0,0 +1,51 @@
/*!
* Stylus - Ternary
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `Ternary` with `cond`, `trueExpr` and `falseExpr`.
*
* @param {Expression} cond
* @param {Expression} trueExpr
* @param {Expression} falseExpr
* @api public
*/
var Ternary = module.exports = function Ternary(cond, trueExpr, falseExpr){
Node.call(this);
this.cond = cond;
this.trueExpr = trueExpr;
this.falseExpr = falseExpr;
};
/**
* Inherit from `Node.prototype`.
*/
Ternary.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Ternary.prototype.clone = function(){
var clone = new Ternary(
this.cond.clone()
, this.trueExpr.clone()
, this.falseExpr.clone());
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};

View File

@@ -0,0 +1,46 @@
/*!
* Stylus - UnaryOp
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node');
/**
* Initialize a new `UnaryOp` with `op`, and `expr`.
*
* @param {String} op
* @param {Node} expr
* @api public
*/
var UnaryOp = module.exports = function UnaryOp(op, expr){
Node.call(this);
this.op = op;
this.expr = expr;
};
/**
* Inherit from `Node.prototype`.
*/
UnaryOp.prototype.__proto__ = Node.prototype;
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
UnaryOp.prototype.clone = function(){
var clone = new UnaryOp(this.op, this.expr.clone());
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};

View File

@@ -0,0 +1,191 @@
/*!
* Stylus - Unit
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./');
/**
* Initialize a new `Unit` with the given `val` and unit `type`
* such as "px", "pt", "in", etc.
*
* @param {String} val
* @param {String} type
* @api public
*/
var Unit = module.exports = function Unit(val, type){
Node.call(this);
this.val = val;
this.type = type;
};
/**
* Inherit from `Node.prototype`.
*/
Unit.prototype.__proto__ = Node.prototype;
/**
* Return Boolean based on the unit value.
*
* @return {Boolean}
* @api public
*/
Unit.prototype.toBoolean = function(){
return nodes.Boolean(this.type
? true
: this.val);
};
/**
* Return unit string.
*
* @return {String}
* @api public
*/
Unit.prototype.toString = function(){
var n = this.val;
if ('px' == this.type) n = n.toFixed(0);
return n + (this.type || '');
};
/**
* Return a clone of this node.
*
* @return {Node}
* @api public
*/
Unit.prototype.clone = function(){
var clone = new Unit(this.val, this.type);
clone.lineno = this.lineno;
clone.filename = this.filename;
return clone;
};
/**
* Operate on `right` with the given `op`.
*
* @param {String} op
* @param {Node} right
* @return {Node}
* @api public
*/
Unit.prototype.operate = function(op, right){
var type = this.type || right.first.type;
// swap color
if ('rgba' == right.nodeName || 'hsla' == right.nodeName) {
return right.operate(op, this);
}
// operate
if (this.shouldCoerce(op)) {
right = right.first;
// percentages
if (('-' == op || '+' == op) && '%' == right.type) {
right = new Unit(this.val * (right.val / 100), '%');
} else {
right = this.coerce(right);
}
switch (op) {
case '-':
return new Unit(this.val - right.val, type);
case '+':
return new Unit(this.val + right.val, type);
case '/':
return new Unit(this.val / right.val, type);
case '*':
return new Unit(this.val * right.val, type);
case '%':
return new Unit(this.val % right.val, type);
case '**':
return new Unit(Math.pow(this.val, right.val), type);
case '..':
case '...':
var start = this.val
, end = right.val
, expr = new nodes.Expression
, inclusive = '..' == op;
do {
expr.push(new nodes.Unit(start));
} while (inclusive ? ++start <= end : ++start < end);
return expr;
}
}
return Node.prototype.operate.call(this, op, right);
};
/**
* Coerce `other` unit to the same type as `this` unit.
*
* Supports:
*
* mm -> cm | in
* cm -> mm | in
* in -> mm | cm
*
* ms -> s
* s -> ms
*
* Hz -> kHz
* kHz -> Hz
*
* @param {Unit} other
* @return {Unit}
* @api public
*/
Unit.prototype.coerce = function(other){
if ('unit' == other.nodeName) {
var a = this
, b = other
, factorA = factor(a)
, factorB = factor(b);
if (factorA && factorB && (factorA.label == factorB.label)) {
var bVal = b.val * (factorB.val / factorA.val);
return new nodes.Unit(bVal, a.type);
} else {
return new nodes.Unit(b.val, a.type);
}
} else if ('string' == other.nodeName) {
var val = parseInt(other.val, 10);
if (isNaN(val)) Node.prototype.coerce.call(this, other);
return new nodes.Unit(val);
} else {
return Node.prototype.coerce.call(this, other);
}
};
/**
* Convert a unit to base unit
*/
function factor(unit) {
var factorTable = {
'mm': {val: 1, label: 'mm'},
'cm': {val: 10, label: 'mm'},
'in': {val: 25.4, label: 'mm'},
'ms': {val: 1, label: 'ms'},
's': {val: 1000, label: 'ms'},
'Hz': {val: 1, label: 'Hz'},
'kHz': {val: 1000, label: 'Hz'}
};
return factorTable[unit.type];
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,187 @@
/*!
* Stylus - Renderer
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Parser = require('./parser')
, EventEmitter = require('events').EventEmitter
, Compiler = require('./visitor/compiler')
, Evaluator = require('./visitor/evaluator')
, Normalizer = require('./visitor/normalizer')
, utils = require('./utils')
, nodes = require('./nodes')
, path = require('path')
, join = path.join;
/**
* Expose `Renderer`.
*/
module.exports = Renderer;
/**
* Initialize a new `Renderer` with the given `str` and `options`.
*
* @param {String} str
* @param {Object} options
* @api public
*/
function Renderer(str, options) {
options = options || {};
options.globals = {};
options.functions = {};
options.imports = [join(__dirname, 'functions')];
options.paths = options.paths || [];
options.filename = options.filename || 'stylus';
this.options = options;
this.str = str;
};
/**
* Inherit from `EventEmitter.prototype`.
*/
Renderer.prototype.__proto__ = EventEmitter.prototype;
/**
* Parse and evaluate AST, then callback `fn(err, css, js)`.
*
* @param {Function} fn
* @api public
*/
Renderer.prototype.render = function(fn){
var parser = this.parser = new Parser(this.str, this.options);
try {
nodes.filename = this.options.filename;
// parse
var ast = parser.parse();
// evaluate
this.evaluator = new Evaluator(ast, this.options);
this.nodes = nodes;
this.evaluator.renderer = this;
ast = this.evaluator.evaluate();
// normalize
var normalizer = new Normalizer(ast, this.options);
ast = normalizer.normalize();
// compile
var compiler = new Compiler(ast, this.options)
, css = compiler.compile();
this.emit('end', css);
if (!fn) return css;
fn(null, css);
} catch (err) {
var options = {};
options.input = err.input || this.str;
options.filename = err.filename || this.options.filename;
options.lineno = err.lineno || parser.lexer.lineno;
if (!fn) throw utils.formatException(err, options);
fn(utils.formatException(err, options));
}
};
/**
* Set option `key` to `val`.
*
* @param {String} key
* @param {Mixed} val
* @return {Renderer} for chaining
* @api public
*/
Renderer.prototype.set = function(key, val){
this.options[key] = val;
return this;
};
/**
* Get option `key`.
*
* @param {String} key
* @return {Mixed} val
* @api public
*/
Renderer.prototype.get = function(key){
return this.options[key];
};
/**
* Include the given `path` to the lookup paths array.
*
* @param {String} path
* @return {Renderer} for chaining
* @api public
*/
Renderer.prototype.include = function(path){
this.options.paths.push(path);
return this;
};
/**
* Use the given `fn`.
*
* This allows for plugins to alter the renderer in
* any way they wish, exposing paths etc.
*
* @param {Function}
* @return {Renderer} for chaining
* @api public
*/
Renderer.prototype.use = function(fn){
fn.call(this, this);
return this;
};
/**
* Define function or global var with the given `name`. Optionally
* the function may accept full expressions, by setting `raw`
* to `true`.
*
* @param {String} name
* @param {Function|Node} fn
* @return {Renderer} for chaining
* @api public
*/
Renderer.prototype.define = function(name, fn, raw){
fn = utils.coerce(fn);
if (fn.nodeName) {
this.options.globals[name] = fn;
return this;
}
// function
this.options.functions[name] = fn;
if (undefined != raw) fn.raw = raw;
return this;
};
/**
* Import the given `file`.
*
* @param {String} file
* @return {Renderer} for chaining
* @api public
*/
Renderer.prototype.import = function(file){
this.options.imports.push(file);
return this;
};

View File

@@ -0,0 +1,66 @@
/*!
* Stylus - stack - Frame
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Scope = require('./scope')
, blocks = require('../nodes');
/**
* Initialize a new `Frame` with the given `block`.
*
* @param {Block} block
* @api private
*/
var Frame = module.exports = function Frame(block) {
this._scope = false === block.scope
? null
: new Scope;
this.block = block;
};
/**
* Return this frame's scope or the parent scope
* for scope-less blocks.
*
* @return {Scope}
* @api public
*/
Frame.prototype.__defineGetter__('scope', function(){
return this._scope || this.parent.scope;
});
/**
* Lookup the given local variable `name`.
*
* @param {String} name
* @return {Node}
* @api private
*/
Frame.prototype.lookup = function(name){
return this.scope.lookup(name)
};
/**
* Custom inspect.
*
* @return {String}
* @api public
*/
Frame.prototype.inspect = function(){
return '[Frame '
+ (false === this.block.scope
? 'scope-less'
: this.scope.inspect())
+ ']';
};

View File

@@ -0,0 +1,146 @@
/*!
* Stylus - Stack
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Frame = require('./frame');
/**
* Initialize a new `Stack`.
*
* @api private
*/
var Stack = module.exports = function Stack() {
Array.apply(this, arguments);
};
/**
* Inherit from `Array.prototype`.
*/
Stack.prototype.__proto__ = Array.prototype;
/**
* Push the given `frame`.
*
* @param {Frame} frame
* @api public
*/
Stack.prototype.push = function(frame){
frame.stack = this;
frame.parent = this.currentFrame;
return [].push.apply(this, arguments);
};
/**
* Return the current stack `Frame`.
*
* @return {Frame}
* @api private
*/
Stack.prototype.__defineGetter__('currentFrame', function(){
return this[this.length - 1];
});
/**
* Lookup stack frame for the given `block`.
*
* @param {Block} block
* @return {Frame}
* @api private
*/
Stack.prototype.getBlockFrame = function(block){
for (var i = 0; i < this.length; ++i) {
if (block == this[i].block) {
return this[i];
}
}
};
/**
* Lookup the given local variable `name`, relative
* to the lexical scope of the current frame's `Block`.
*
* When the result of a lookup is an identifier
* a recursive lookup is performed, defaulting to
* returning the identifier itself.
*
* @param {String} name
* @return {Node}
* @api private
*/
Stack.prototype.lookup = function(name){
var block = this.currentFrame.block
, val
, ret;
do {
var frame = this.getBlockFrame(block);
if (frame && (val = frame.lookup(name))) {
switch (val.first.nodeName) {
case 'ident':
return this.lookup(val.first.name) || val;
default:
return val;
}
}
} while (block = block.parent);
};
/**
* Custom inspect.
*
* @return {String}
* @api private
*/
Stack.prototype.inspect = function(){
return this.reverse().map(function(frame){
return frame.inspect();
}).join('\n');
};
/**
* Return stack string formatted as:
*
* at <context> (<filename>:<lineno>)
*
* @return {String}
* @api private
*/
Stack.prototype.toString = function(){
var block
, node
, buf = []
, location
, len = this.length;
while (len--) {
block = this[len].block;
if (node = block.node) {
location = '(' + node.filename + ':' + (node.lineno + 1) + ')';
switch (node.nodeName) {
case 'function':
buf.push(' at ' + node.name + '() ' + location);
break;
case 'group':
buf.push(' at "' + node.nodes[0].val + '" ' + location);
break;
}
}
}
return buf.join('\n');
};

View File

@@ -0,0 +1,53 @@
/*!
* Stylus - stack - Scope
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Initialize a new `Scope`.
*
* @api private
*/
var Scope = module.exports = function Scope() {
this.locals = {};
};
/**
* Add `ident` node to the current scope.
*
* @param {Ident} ident
* @api private
*/
Scope.prototype.add = function(ident){
this.locals[ident.name] = ident.val;
};
/**
* Lookup the given local variable `name`.
*
* @param {String} name
* @return {Node}
* @api private
*/
Scope.prototype.lookup = function(name){
return this.locals[name];
};
/**
* Custom inspect.
*
* @return {String}
* @api public
*/
Scope.prototype.inspect = function(){
var keys = Object.keys(this.locals).map(function(key){ return '@' + key; });
return '[Scope'
+ (keys.length ? ' ' + keys.join(', ') : '')
+ ']';
};

View File

@@ -0,0 +1,104 @@
/*!
* Stylus
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Renderer = require('./renderer')
, Parser = require('./parser')
, nodes = require('./nodes')
, utils = require('./utils');
/**
* Export render as the module.
*/
exports = module.exports = render;
/**
* Library version.
*/
exports.version = require('../package').version;
/**
* Expose nodes.
*/
exports.nodes = nodes;
/**
* Expose BIFs.
*/
exports.functions = require('./functions');
/**
* Expose utils.
*/
exports.utils = require('./utils');
/**
* Expose middleware.
*/
exports.middleware = require('./middleware');
/**
* Expose constructors.
*/
exports.Visitor = require('./visitor');
exports.Parser = require('./parser');
exports.Evaluator = require('./visitor/evaluator');
exports.Compiler = require('./visitor/compiler');
/**
* Convert the given `css` to `stylus` source.
*
* @param {String} css
* @return {String}
* @api public
*/
exports.convertCSS = require('./convert/css');
/**
* Render the given `str` with `options` and callback `fn(err, css)`.
*
* @param {String} str
* @param {Object|Function} options
* @param {Function} fn
* @api public
*/
exports.render = function(str, options, fn){
if ('function' == typeof options) fn = options, options = {};
new Renderer(str, options).render(fn);
};
/**
* Return a new `Renderer` for the given `str` and `options`.
*
* @param {String} str
* @param {Object} options
* @return {Renderer}
* @api public
*/
function render(str, options) {
return new Renderer(str, options);
}
/**
* Expose optional functions.
*/
exports.url = require('./functions/url');
exports.resolver = require('./functions/resolver');

View File

@@ -0,0 +1,53 @@
/*!
* Stylus - Token
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var inspect = require('util').inspect;
/**
* Initialize a new `Token` with the given `type` and `val`.
*
* @param {String} type
* @param {Mixed} val
* @api private
*/
var Token = exports = module.exports = function Token(type, val) {
this.type = type;
this.val = val;
};
/**
* Custom inspect.
*
* @return {String}
* @api public
*/
Token.prototype.inspect = function(){
var val = ' ' + inspect(this.val);
return '[Token:' + this.lineno + ' '
+ '\x1b[32m' + this.type + '\x1b[0m'
+ '\x1b[33m' + (this.val ? val : '') + '\x1b[0m'
+ ']';
};
/**
* Return type or val.
*
* @return {String}
* @api public
*/
Token.prototype.toString = function(){
return (undefined === this.val
? this.type
: this.val).toString();
};

View File

@@ -0,0 +1,20 @@
/*!
* Stylus - units
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
// units found in http://www.w3.org/TR/css3-values
module.exports = [
'em', 'ex', 'ch', 'rem' // relative lengths
, 'vw', 'vh', 'vmin' // relative viewport-percentage lengths
, 'cm', 'mm', 'in', 'pt', 'pc', 'px' // absolute lengths
, 'deg', 'grad', 'rad', 'turn' // angles
, 's', 'ms' // times
, 'Hz', 'kHz' // frequencies
, 'dpi', 'dpcm', 'dppx', 'x' // resolutions
, '%' // percentage type
, 'fr' // grid-layout (http://www.w3.org/TR/css3-grid-layout/)
];

View File

@@ -0,0 +1,304 @@
/*!
* Stylus - utils
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var nodes = require('./nodes')
, resolve = require('path').resolve
, fs = require('fs');
/**
* Check if `path` looks absolute.
*
* @param {String} path
* @return {Boolean}
* @api private
*/
exports.absolute = function(path){
// On Windows the path could start with a drive letter, i.e. a:\\ or two leading backslashes
return path.substr(0, 2) == '\\\\' || path[0] == '/' || /^[a-z]:\\/i.test(path);
};
/**
* Attempt to lookup `path` within `paths` from tail to head.
* Optionally a path to `ignore` may be passed.
*
* @param {String} path
* @param {String} paths
* @param {String} ignore
* @return {String}
* @api private
*/
exports.lookup = function(path, paths, ignore){
var lookup
, i = paths.length;
// Absolute
if (exports.absolute(path)) {
try {
fs.statSync(path);
return path;
} catch (err) {
// Ignore, continue on
// to trying relative lookup.
// Needed for url(/images/foo.png)
// for example
}
}
// Relative
while (i--) {
try {
lookup = resolve(paths[i], path);
if (ignore == lookup) continue;
fs.statSync(lookup);
return lookup;
} catch (err) {
// Ignore
}
}
};
/**
* Format the given `err` with the given `options`.
*
* Options:
*
* - `filename` context filename
* - `context` context line count [8]
* - `lineno` context line number
* - `input` input string
*
* @param {Error} err
* @param {Object} options
* @return {Error}
* @api private
*/
exports.formatException = function(err, options){
var lineno = options.lineno
, filename = options.filename
, str = options.input
, context = options.context || 8
, context = context / 2
, lines = ('\n' + str).split('\n')
, start = Math.max(lineno - context, 1)
, end = Math.min(lines.length, lineno + context)
, pad = end.toString().length;
var context = lines.slice(start, end).map(function(line, i){
var curr = i + start;
return (curr == lineno ? ' > ' : ' ')
+ Array(pad - curr.toString().length + 1).join(' ')
+ curr
+ '| '
+ line;
}).join('\n');
err.message = filename
+ ':' + lineno
+ '\n' + context
+ '\n\n' + err.message + '\n'
+ (err.stylusStack ? err.stylusStack + '\n' : '');
return err;
};
/**
* Assert that `node` is of the given `type`, or throw.
*
* @param {Node} node
* @param {Function} type
* @param {String} param
* @api public
*/
exports.assertType = function(node, type, param){
exports.assertPresent(node, param);
if (node.nodeName == type) return;
var actual = node.nodeName
, msg = 'expected "'
+ param + '" to be a '
+ type + ', but got '
+ actual + ':' + node;
throw new Error('TypeError: ' + msg);
};
/**
* Assert that `node` is a `String` or `Ident`.
*
* @param {Node} node
* @param {String} param
* @api public
*/
exports.assertString = function(node, param){
exports.assertPresent(node, param);
switch (node.nodeName) {
case 'string':
case 'ident':
case 'literal':
return;
default:
var actual = node.nodeName
, msg = 'expected string, ident or literal, but got ' + actual + ':' + node;
throw new Error('TypeError: ' + msg);
}
};
/**
* Assert that `node` is a `RGBA` or `HSLA`.
*
* @param {Node} node
* @param {String} param
* @api public
*/
exports.assertColor = function(node, param){
exports.assertPresent(node, param);
switch (node.nodeName) {
case 'rgba':
case 'hsla':
return;
default:
var actual = node.nodeName
, msg = 'expected rgba or hsla, but got ' + actual + ':' + node;
throw new Error('TypeError: ' + msg);
}
};
/**
* Assert that param `name` is given, aka the `node` is passed.
*
* @param {Node} node
* @param {String} name
* @api public
*/
exports.assertPresent = function(node, name){
if (node) return;
if (name) throw new Error('"' + name + '" argument required');
throw new Error('argument missing');
};
/**
* Unwrap `expr`.
*
* Takes an expressions with length of 1
* such as `((1 2 3))` and unwraps it to `(1 2 3)`.
*
* @param {Expression} expr
* @return {Node}
* @api public
*/
exports.unwrap = function(expr){
// explicitly preserve the expression
if (expr.preserve) return expr;
if ('arguments' != expr.nodeName && 'expression' != expr.nodeName) return expr;
if (1 != expr.nodes.length) return expr;
if ('arguments' != expr.nodes[0].nodeName && 'expression' != expr.nodes[0].nodeName) return expr;
return exports.unwrap(expr.nodes[0]);
};
/**
* Coerce JavaScript values to their Stylus equivalents.
*
* @param {Mixed} val
* @return {Node}
* @api public
*/
exports.coerce = function(val){
switch (typeof val) {
case 'function':
return val;
case 'string':
return new nodes.String(val);
case 'boolean':
return new nodes.Boolean(val);
case 'number':
return new nodes.Unit(val);
default:
if (null == val) return nodes.null;
if (Array.isArray(val)) return exports.coerceArray(val);
if (val.nodeName) return val;
return exports.coerceObject(val);
}
};
/**
* Coerce a javascript `Array` to a Stylus `Expression`.
*
* @param {Array} val
* @return {Expression}
* @api private
*/
exports.coerceArray = function(val){
var expr = new nodes.Expression;
val.forEach(function(val){
expr.push(exports.coerce(val));
});
return expr;
};
/**
* Coerce a javascript object to a Stylus `Expression`.
*
* For example `{ foo: 'bar', bar: 'baz' }` would become
* the expression `(foo 'bar') (bar 'baz')`.
*
* @param {Object} obj
* @return {Expression}
* @api public
*/
exports.coerceObject = function(obj){
var expr = new nodes.Expression
, val;
for (var key in obj) {
val = exports.coerce(obj[key]);
key = new nodes.Ident(key);
expr.push(exports.coerceArray([key, val]));
}
return expr;
};
/**
* Return param names for `fn`.
*
* @param {Function} fn
* @return {Array}
* @api private
*/
exports.params = function(fn){
return fn
.toString()
.match(/\(([^)]*)\)/)[1].split(/ *, */);
};
/**
* Merge object `b` with `a`.
*
* @param {Object} a
* @param {Object} b
* @return {Object} a
* @api private
*/
exports.merge = function(a, b){
for (var k in b) a[k] = b[k];
return a;
}

View File

@@ -0,0 +1,528 @@
/*!
* Stylus - Compiler
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Visitor = require('./')
, nodes = require('../nodes')
, utils = require('../utils')
, fs = require('fs');
/**
* Initialize a new `Compiler` with the given `root` Node
* and the following `options`.
*
* Options:
*
* - `compress` Compress the CSS output (default: false)
*
* @param {Node} root
* @api public
*/
var Compiler = module.exports = function Compiler(root, options) {
options = options || {};
this.compress = options.compress;
this.firebug = options.firebug;
this.linenos = options.linenos;
this.spaces = options['indent spaces'] || 2;
this.includeCSS = options['include css'];
this.indents = 1;
Visitor.call(this, root);
this.stack = [];
this.js = '';
};
/**
* Inherit from `Visitor.prototype`.
*/
Compiler.prototype.__proto__ = Visitor.prototype;
/**
* Compile to css, and return a string of CSS.
*
* @return {String}
* @api private
*/
Compiler.prototype.compile = function(){
return this.visit(this.root);
};
/**
* Return indentation string.
*
* @return {String}
* @api private
*/
Compiler.prototype.__defineGetter__('indent', function(){
if (this.compress) return '';
return new Array(this.indents).join(Array(this.spaces + 1).join(' '));
});
/**
* Visit Root.
*/
Compiler.prototype.visitRoot = function(block){
this.buf = '';
for (var i = 0, len = block.nodes.length; i < len; ++i) {
var node = block.nodes[i];
if (this.linenos || this.firebug) this.debugInfo(node);
var ret = this.visit(node);
if (ret) this.buf += ret + '\n';
}
return this.buf;
};
/**
* Visit Block.
*/
Compiler.prototype.visitBlock = function(block){
var node;
if (block.hasProperties && !block.lacksRenderedSelectors) {
var arr = [this.compress ? '{' : ' {'];
++this.indents;
for (var i = 0, len = block.nodes.length; i < len; ++i) {
this.last = len - 1 == i;
node = block.nodes[i];
switch (node.nodeName) {
case 'null':
case 'expression':
case 'function':
case 'jsliteral':
case 'group':
case 'unit':
continue;
case 'media':
// Prevent double-writing the @media declaration when
// nested inside of a function/mixin
if (node.block.parent.scope) {
continue;
}
default:
arr.push(this.visit(node));
}
}
--this.indents;
arr.push(this.indent + '}');
this.buf += arr.join(this.compress ? '' : '\n');
this.buf += '\n';
}
// Nesting
for (var i = 0, len = block.nodes.length; i < len; ++i) {
node = block.nodes[i];
switch (node.nodeName) {
case 'group':
case 'print':
case 'page':
case 'block':
case 'keyframes':
if (this.linenos || this.firebug) this.debugInfo(node);
this.visit(node);
break;
case 'media':
case 'mozdocument':
case 'import':
case 'fontface':
this.visit(node);
break;
case 'comment':
// only show comments inside when outside of scope and unsuppressed
if (!block.scope && !node.suppress) {
this.buf += this.visit(node) + '\n';
}
break;
case 'literal':
this.buf += this.visit(node) + '\n';
break;
}
}
};
/**
* Visit Keyframes.
*/
Compiler.prototype.visitKeyframes = function(node){
var comma = this.compress ? ',' : ', ';
var prefix = 'official' == node.prefix
? ''
: '-' + node.prefix + '-';
this.buf += '@' + prefix + 'keyframes '
+ this.visit(node.name)
+ (this.compress ? '{' : ' {');
++this.indents;
node.frames.forEach(function(frame){
if (!this.compress) this.buf += '\n ';
this.buf += this.visit(frame.pos.join(comma));
this.visit(frame.block);
}, this);
--this.indents;
this.buf += '}' + (this.compress ? '' : '\n');
};
/**
* Visit Media.
*/
Compiler.prototype.visitMedia = function(media){
this.buf += '@media ' + media.val;
this.buf += this.compress ? '{' : ' {\n';
++this.indents;
this.visit(media.block);
--this.indents;
this.buf += '}' + (this.compress ? '' : '\n');
};
/**
* Visit MozDocument.
*/
Compiler.prototype.visitMozDocument = function(mozdocument){
this.buf += '@-moz-document ' + mozdocument.val;
this.buf += this.compress ? '{' : ' {\n';
++this.indents;
this.visit(mozdocument.block);
--this.indents;
this.buf += '}' + (this.compress ? '' : '\n');
};
/**
* Visit Page.
*/
Compiler.prototype.visitPage = function(page){
this.buf += this.indent + '@page';
this.buf += page.selector ? ' ' + page.selector : '';
this.visit(page.block);
};
/**
* Visit Import.
*/
Compiler.prototype.visitImport = function(imported){
this.buf += '@import ' + this.visit(imported.path) + ';\n';
};
/**
* Visit FontFace.
*/
Compiler.prototype.visitFontFace = function(face){
this.buf += this.indent + '@font-face';
this.visit(face.block);
};
/**
* Visit JSLiteral.
*/
Compiler.prototype.visitJSLiteral = function(js){
this.js += '\n' + js.val.replace(/@selector/g, '"' + this.selector + '"');
return '';
};
/**
* Visit Comment.
*/
Compiler.prototype.visitComment = function(comment){
return this.compress
? comment.suppress
? ''
: comment.str
: comment.str;
};
/**
* Visit Function.
*/
Compiler.prototype.visitFunction = function(fn){
return fn.name;
};
/**
* Visit Variable.
*/
Compiler.prototype.visitVariable = function(variable){
return '';
};
/**
* Visit Charset.
*/
Compiler.prototype.visitCharset = function(charset){
return '@charset ' + this.visit(charset.val) + ';';
};
/**
* Visit Literal.
*/
Compiler.prototype.visitLiteral = function(lit){
var val = lit.val.trim();
if (!this.includeCSS) val = val.replace(/^ /gm, '');
return val;
};
/**
* Visit Boolean.
*/
Compiler.prototype.visitBoolean = function(bool){
return bool.toString();
};
/**
* Visit RGBA.
*/
Compiler.prototype.visitRGBA = function(rgba){
return rgba.toString();
};
/**
* Visit HSLA.
*/
Compiler.prototype.visitHSLA = function(hsla){
return hsla.rgba.toString();
};
/**
* Visit Unit.
*/
Compiler.prototype.visitUnit = function(unit){
var type = unit.type || ''
, n = unit.val
, float = n != (n | 0);
// Compress
if (this.compress) {
// Zero is always '0', unless when
// a percentage, this is required by keyframes
if ('%' != type && 0 == n) return '0';
// Omit leading '0' on floats
if (float && n < 1 && n > -1) {
return n.toString().replace('0.', '.') + type;
}
}
return n.toString() + type;
};
/**
* Visit Group.
*/
Compiler.prototype.visitGroup = function(group){
var stack = this.stack;
stack.push(group.nodes);
// selectors
if (group.block.hasProperties) {
var selectors = this.compileSelectors(stack);
if(selectors.length)
this.buf += (this.selector = selectors.join(this.compress ? ',' : ',\n'));
else
group.block.lacksRenderedSelectors = true;
}
// output block
this.visit(group.block);
stack.pop();
};
/**
* Visit Ident.
*/
Compiler.prototype.visitIdent = function(ident){
return ident.name;
};
/**
* Visit String.
*/
Compiler.prototype.visitString = function(string){
return this.isURL
? string.val
: string.toString();
};
/**
* Visit Null.
*/
Compiler.prototype.visitNull = function(node){
return '';
};
/**
* Visit Call.
*/
Compiler.prototype.visitCall = function(call){
this.isURL = 'url' == call.name;
var args = call.args.nodes.map(function(arg){
return this.visit(arg);
}, this).join(this.compress ? ',' : ', ');
if (this.isURL) args = '"' + args + '"';
this.isURL = false;
return call.name + '(' + args + ')';
};
/**
* Visit Expression.
*/
Compiler.prototype.visitExpression = function(expr){
var buf = []
, self = this
, len = expr.nodes.length
, nodes = expr.nodes.map(function(node){ return self.visit(node); });
nodes.forEach(function(node, i){
var last = i == len - 1;
buf.push(node);
if ('/' == nodes[i + 1] || '/' == node) return;
if (last) return;
buf.push(expr.isList
? (self.compress ? ',' : ', ')
: (self.isURL ? '' : ' '));
});
return buf.join('');
};
/**
* Visit Arguments.
*/
Compiler.prototype.visitArguments = Compiler.prototype.visitExpression;
/**
* Visit Property.
*/
Compiler.prototype.visitProperty = function(prop){
var self = this
, val = this.visit(prop.expr).trim();
return this.indent + (prop.name || prop.segments.join(''))
+ (this.compress ? ':' + val : ': ' + val)
+ (this.compress
? (this.last ? '' : ';')
: ';');
};
/**
* Compile selector strings in `arr` from the bottom-up
* to produce the selector combinations. For example
* the following Stylus:
*
* ul
* li
* p
* a
* color: red
*
* Would return:
*
* [ 'ul li a', 'ul p a' ]
*
* @param {Array} arr
* @return {Array}
* @api private
*/
Compiler.prototype.compileSelectors = function(arr){
var stack = this.stack
, self = this
, selectors = []
, buf = []
, hiddenSelectorRegexp = /^\s*\$/;
function interpolateParent(selector, buf) {
var str = selector.val.trim();
if (buf.length) {
for (var i = 0, len = buf.length; i < len; ++i) {
if (~buf[i].indexOf('&')) {
str = buf[i].replace(/&/g, str).trim();
} else {
str += ' ' + buf[i].trim();
}
}
}
return str;
}
function compile(arr, i) {
if (i) {
arr[i].forEach(function(selector){
if(selector.val.match(hiddenSelectorRegexp)) return;
if (selector.inherits) {
buf.unshift(selector.val);
compile(arr, i - 1);
buf.shift();
} else {
selectors.push(interpolateParent(selector, buf));
}
});
} else {
arr[0].forEach(function(selector){
if(selector.val.match(hiddenSelectorRegexp)) return;
var str = interpolateParent(selector, buf);
selectors.push(self.indent + str.trimRight());
});
}
}
compile(arr, arr.length - 1);
return selectors;
};
/**
* Debug info.
*/
Compiler.prototype.debugInfo = function(node){
var path = node.filename == 'stdin' ? 'stdin' : fs.realpathSync(node.filename)
, line = node.nodes ? node.nodes[0].lineno : node.lineno;
if (this.linenos){
this.buf += '\n/* ' + 'line ' + line + ' : ' + path + ' */\n';
}
if (this.firebug){
// debug info for firebug, the crazy formatting is needed
path = 'file\\\:\\\/\\\/' + path.replace(/(\/|\.)/g, '\\$1');
line = '\\00003' + line;
this.buf += '\n@media -stylus-debug-info'
+ '{filename{font-family:' + path
+ '}line{font-family:' + line + '}}\n';
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
/*!
* Stylus - Visitor
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Initialize a new `Visitor` with the given `root` Node.
*
* @param {Node} root
* @api private
*/
var Visitor = module.exports = function Visitor(root) {
this.root = root;
};
/**
* Visit the given `node`.
*
* @param {Node|Array} node
* @api public
*/
Visitor.prototype.visit = function(node, fn){
var method = 'visit' + node.constructor.name;
if (this[method]) return this[method](node);
return node;
};

View File

@@ -0,0 +1,283 @@
/*!
* Stylus - Normalizer
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Visitor = require('./')
, nodes = require('../nodes')
, utils = require('../utils')
, fs = require('fs');
/**
* Initialize a new `Normalizer` with the given `root` Node.
*
* This visitor implements the first stage of the duel-stage
* compiler, tasked with stripping the "garbage" from
* the evaluated nodes, ditching null rules, resolving
* ruleset selectors etc. This step performs the logic
* necessary to facilitate the "@extend" functionality,
* as these must be resolved _before_ buffering output.
*
* @param {Node} root
* @api public
*/
var Normalizer = module.exports = function Normalizer(root, options) {
options = options || {};
Visitor.call(this, root);
this.stack = [];
this.extends = {};
this.map = {};
};
/**
* Inherit from `Visitor.prototype`.
*/
Normalizer.prototype.__proto__ = Visitor.prototype;
/**
* Normalize the node tree.
*
* @return {Node}
* @api private
*/
Normalizer.prototype.normalize = function(){
return this.visit(this.root);
};
/**
* Visit Root.
*/
Normalizer.prototype.visitRoot = function(block){
var ret = new nodes.Root
, node;
for (var i = 0, len = block.nodes.length; i < len; ++i) {
node = block.nodes[i];
switch (node.nodeName) {
case 'null':
case 'expression':
case 'function':
case 'jsliteral':
case 'unit':
continue;
default:
ret.push(this.visit(node));
}
}
return ret;
};
/**
* Visit Block.
*/
Normalizer.prototype.visitBlock = function(block){
var ret = new nodes.Block
, node;
if (block.hasProperties) {
for (var i = 0, len = block.nodes.length; i < len; ++i) {
this.last = len - 1 == i;
node = block.nodes[i];
switch (node.nodeName) {
case 'null':
case 'expression':
case 'function':
case 'jsliteral':
case 'group':
case 'unit':
continue;
default:
ret.push(this.visit(node));
}
}
}
// nesting
for (var i = 0, len = block.nodes.length; i < len; ++i) {
node = block.nodes[i];
ret.push(this.visit(node));
}
return block;
};
/**
* Visit Group.
*/
Normalizer.prototype.visitGroup = function(group){
// TODO: clean this mess up
var stack = this.stack
, map = this.map
, self = this;
stack.push(group.nodes);
var selectors = this.compileSelectors(stack);
// map for extension lookup
selectors.forEach(function(selector){
map[selector] = map[selector] || [];
map[selector].push(group);
});
// extensions
this.extend(group, selectors);
group.block = this.visit(group.block);
stack.pop();
return group;
};
/**
* Visit Media.
*/
Normalizer.prototype.visitMedia = function(media){
var props = []
, other = [];
media.block.nodes.forEach(function(node, i) {
node = this.visit(node);
if ('property' == node.nodeName) {
props.push(node);
} else {
other.push(node);
}
}, this);
// Fake self-referencing group to contain
// any props that are floating
// directly on the @media declaration
if (props.length) {
var selfLiteral = new nodes.Literal('&');
selfLiteral.lineno = media.lineno;
selfLiteral.filename = media.filename;
var selfSelector = new nodes.Selector(selfLiteral);
selfSelector.lineno = media.lineno;
selfSelector.filename = media.filename;
selfSelector.val = selfLiteral.val;
var propertyGroup = new nodes.Group;
propertyGroup.lineno = media.lineno;
propertyGroup.filename = media.filename;
var propertyBlock = new nodes.Block(media.block, propertyGroup);
propertyBlock.lineno = media.lineno;
propertyBlock.filename = media.filename;
props.forEach(function(prop){
propertyBlock.push(prop);
});
propertyGroup.push(selfSelector);
propertyGroup.block = propertyBlock;
media.block.nodes = [];
media.block.push(propertyGroup);
other.forEach(function(node){
media.block.push(node);
});
}
return media;
}
/**
* Apply `group` extensions.
*
* @param {Group} group
* @param {Array} selectors
* @api private
*/
Normalizer.prototype.extend = function(group, selectors){
var map = this.map
, self = this;
group.block.node.extends.forEach(function(extend){
var groups = map[extend];
if (!groups) throw new Error('Failed to @extend "' + extend + '"');
selectors.forEach(function(selector){
var node = new nodes.Selector;
node.val = selector;
node.inherits = false;
groups.forEach(function(group){
if (!group.nodes.some(function(n){ return n.val == selector })) {
self.extend(group, selectors);
group.push(node);
}
});
});
});
};
/**
* Compile selector strings in `arr` from the bottom-up
* to produce the selector combinations. For example
* the following Stylus:
*
* ul
* li
* p
* a
* color: red
*
* Would return:
*
* [ 'ul li a', 'ul p a' ]
*
* @param {Array} arr
* @return {Array}
* @api private
*/
Normalizer.prototype.compileSelectors = function(arr){
// TODO: remove this duplication
var stack = this.stack
, self = this
, selectors = []
, buf = [];
function compile(arr, i) {
if (i) {
arr[i].forEach(function(selector){
buf.unshift(selector.val);
compile(arr, i - 1);
buf.shift();
});
} else {
arr[0].forEach(function(selector){
var str = selector.val.trim();
if (buf.length) {
for (var i = 0, len = buf.length; i < len; ++i) {
if (~buf[i].indexOf('&')) {
str = buf[i].replace(/&/g, str).trim();
} else {
str += ' ' + buf[i].trim();
}
}
}
selectors.push(str.trimRight());
});
}
}
compile(arr, arr.length - 1);
return selectors;
};

View File

@@ -0,0 +1,6 @@
[submodule "spec/vendor/objectDiff"]
path = spec/vendor/objectDiff
url = git://github.com/NV/objectDiff.js.git
[submodule "spec/vendor/jasmine-html-reporter"]
path = spec/vendor/jasmine-html-reporter
url = git://github.com/NV/jasmine-html-reporter.git

Some files were not shown because too many files have changed in this diff Show More